浏览代码

Convert to using file-scoped namespaces (#1931)

Marko Lahma 1 年之前
父节点
当前提交
9079aef684
共有 100 个文件被更改,包括 13917 次插入14016 次删除
  1. 115 116
      Jint.Tests.PublicInterface/InteropTests.Dynamic.cs
  2. 121 122
      Jint.Tests.PublicInterface/InteropTests.NewtonsoftJson.cs
  3. 17 18
      Jint.Tests.PublicInterface/InteropTests.cs
  4. 25 26
      Jint.Tests.PublicInterface/JavaScriptExceptionTests.cs
  5. 46 47
      Jint.Tests/ReplaceCulture.cs
  6. 7 8
      Jint.Tests/RunnableInDebugOnlyAttribute.cs
  7. 17 18
      Jint.Tests/Runtime/CallStackTests.cs
  8. 26 27
      Jint.Tests/Runtime/ConstTests.cs
  9. 11 12
      Jint.Tests/Runtime/Converters/EnumsToStringConverter.cs
  10. 11 12
      Jint.Tests/Runtime/Converters/NegateBoolConverter.cs
  11. 352 353
      Jint.Tests/Runtime/Debugger/BreakPointTests.cs
  12. 170 171
      Jint.Tests/Runtime/Debugger/CallStackTests.cs
  13. 32 33
      Jint.Tests/Runtime/Debugger/DebugHandlerTests.cs
  14. 62 63
      Jint.Tests/Runtime/Debugger/EvaluateTests.cs
  15. 293 294
      Jint.Tests/Runtime/Debugger/ScopeTests.cs
  16. 181 182
      Jint.Tests/Runtime/Debugger/StepFlowTests.cs
  17. 238 239
      Jint.Tests/Runtime/Debugger/StepModeTests.cs
  18. 56 57
      Jint.Tests/Runtime/Debugger/TestHelpers.cs
  19. 123 124
      Jint.Tests/Runtime/Domain/A.cs
  20. 123 124
      Jint.Tests/Runtime/Domain/ArrayConverterTestClass.cs
  21. 5 6
      Jint.Tests/Runtime/Domain/ClassWithField.cs
  22. 38 39
      Jint.Tests/Runtime/Domain/ClassWithStaticFields.cs
  23. 8 9
      Jint.Tests/Runtime/Domain/Colors.cs
  24. 32 33
      Jint.Tests/Runtime/Domain/Company.cs
  25. 47 48
      Jint.Tests/Runtime/Domain/CustomNamed.cs
  26. 82 83
      Jint.Tests/Runtime/Domain/Dimensional.cs
  27. 10 11
      Jint.Tests/Runtime/Domain/Enums.cs
  28. 5 6
      Jint.Tests/Runtime/Domain/FloatIndexer.cs
  29. 14 15
      Jint.Tests/Runtime/Domain/HiddenMembers.cs
  30. 5 6
      Jint.Tests/Runtime/Domain/ICompany.cs
  31. 5 7
      Jint.Tests/Runtime/Domain/IPerson.cs
  32. 12 13
      Jint.Tests/Runtime/Domain/IntegerIndexer.cs
  33. 14 15
      Jint.Tests/Runtime/Domain/JsUuid.cs
  34. 21 22
      Jint.Tests/Runtime/Domain/OverLoading.cs
  35. 30 31
      Jint.Tests/Runtime/Domain/Person.cs
  36. 18 19
      Jint.Tests/Runtime/Domain/Thrower.cs
  37. 43 44
      Jint.Tests/Runtime/Domain/UuidConstructor.cs
  38. 15 16
      Jint.Tests/Runtime/Domain/UuidConverter.cs
  39. 10 11
      Jint.Tests/Runtime/Domain/UuidInstance.cs
  40. 25 26
      Jint.Tests/Runtime/Domain/UuidPrototype.cs
  41. 406 406
      Jint.Tests/Runtime/EngineTests.cs
  42. 268 269
      Jint.Tests/Runtime/ErrorTests.cs
  43. 213 214
      Jint.Tests/Runtime/ExecutionConstraintTests.cs
  44. 24 25
      Jint.Tests/Runtime/ExtensionMethods/CustomStringExtensions.cs
  45. 6 7
      Jint.Tests/Runtime/ExtensionMethods/DoubleExtensions.cs
  46. 208 209
      Jint.Tests/Runtime/ExtensionMethods/ExtensionMethodsTest.cs
  47. 13 14
      Jint.Tests/Runtime/ExtensionMethods/FlurlExtensionTest.cs
  48. 100 101
      Jint.Tests/Runtime/ExtensionMethods/ObservableExtensions.cs
  49. 6 7
      Jint.Tests/Runtime/ExtensionMethods/OverrideStringPrototypeExtensions.cs
  50. 5 6
      Jint.Tests/Runtime/ExtensionMethods/PersonExtensions.cs
  51. 12 13
      Jint.Tests/Runtime/GlobalTests.cs
  52. 207 208
      Jint.Tests/Runtime/InteropTests.MemberAccess.cs
  53. 504 504
      Jint.Tests/Runtime/InteropTests.cs
  54. 195 196
      Jint.Tests/Runtime/JsValueConversionTests.cs
  55. 156 157
      Jint.Tests/Runtime/JsonSerializerTests.cs
  56. 261 262
      Jint.Tests/Runtime/JsonTests.cs
  57. 95 96
      Jint.Tests/Runtime/MethodAmbiguityTests.cs
  58. 76 77
      Jint.Tests/Runtime/NullPropagation.cs
  59. 134 135
      Jint.Tests/Runtime/NumberTests.cs
  60. 35 36
      Jint.Tests/Runtime/ObjectInstanceTests.cs
  61. 146 147
      Jint.Tests/Runtime/OperatorOverloadingTests.cs
  62. 25 26
      Jint.Tests/Runtime/SamplesTests.cs
  63. 87 88
      Jint.Tests/Runtime/StringTetsLithuaniaData.cs
  64. 28 29
      Jint.Tests/Runtime/TestClasses/AsyncTestClass.cs
  65. 7 8
      Jint.Tests/Runtime/TestClasses/HelloWorld.cs
  66. 70 72
      Jint.Tests/Runtime/TypeConverterTests.cs
  67. 145 146
      Jint.Tests/Runtime/TypedArrayInteropTests.cs
  68. 61 62
      Jint.Tests/Runtime/UnicodeTests.cs
  69. 41 42
      Jint.Tests/Runtime/UuidTests.cs
  70. 406 407
      Jint/AstExtensions.cs
  71. 229 230
      Jint/Collections/DictionarySlim.cs
  72. 165 166
      Jint/Collections/HybridDictionary.cs
  73. 186 187
      Jint/Collections/ListDictionary.cs
  74. 24 25
      Jint/Collections/ObjectTraverseStack.cs
  75. 10 11
      Jint/Collections/PropertyDictionary.cs
  76. 134 135
      Jint/Collections/RefStack.cs
  77. 266 267
      Jint/Collections/StringDictionarySlim.cs
  78. 7 8
      Jint/Collections/SymbolDictionary.cs
  79. 7 8
      Jint/DeclarationBindingType.cs
  80. 1201 1202
      Jint/Engine.cs
  81. 36 37
      Jint/Extensions/Character.cs
  82. 10 11
      Jint/Extensions/JavascriptExtensions.cs
  83. 126 127
      Jint/Extensions/ReflectionExtensions.cs
  84. 244 245
      Jint/HoistingScope.cs
  85. 48 49
      Jint/Key.cs
  86. 344 345
      Jint/Native/Array/ArrayConstructor.cs
  87. 979 980
      Jint/Native/Array/ArrayInstance.cs
  88. 440 441
      Jint/Native/Array/ArrayOperations.cs
  89. 853 853
      Jint/Native/Array/ArrayPrototype.cs
  90. 47 48
      Jint/Native/Boolean/BooleanConstructor.cs
  91. 42 43
      Jint/Native/Boolean/BooleanPrototype.cs
  92. 79 80
      Jint/Native/DataView/DataViewConstructor.cs
  93. 311 312
      Jint/Native/DataView/DataViewPrototype.cs
  94. 1092 1093
      Jint/Native/Date/DatePrototype.cs
  95. 61 62
      Jint/Native/Error/ErrorConstructor.cs
  96. 49 50
      Jint/Native/Error/ErrorPrototype.cs
  97. 75 76
      Jint/Native/Function/BindFunction.cs
  98. 5 6
      Jint/Native/Function/ConstructorKind.cs
  99. 334 335
      Jint/Native/Function/Function.cs
  100. 108 109
      Jint/Native/Function/FunctionConstructor.cs

+ 115 - 116
Jint.Tests.PublicInterface/InteropTests.Dynamic.cs

@@ -2,151 +2,150 @@ using System.Dynamic;
 using Jint.Native;
 using Jint.Native.Symbol;
 
-namespace Jint.Tests.PublicInterface
+namespace Jint.Tests.PublicInterface;
+
+public partial class InteropTests
 {
-    public partial class InteropTests
+    [Fact]
+    public void CanAccessExpandoObject()
     {
-        [Fact]
-        public void CanAccessExpandoObject()
-        {
-            var engine = new Engine();
-            dynamic expando = new ExpandoObject();
-            expando.Name = "test";
-            engine.SetValue("expando", expando);
-            Assert.Equal("test", engine.Evaluate("expando.Name").ToString());
-        }
-
-        [Fact]
-        public void DebugView()
-        {
-            // allows displaying different local variables under debugger
-
-            var engine = new Engine();
-            var boolNet = true;
-            var boolJint = (JsBoolean) boolNet;
-            var doubleNet = 12.34;
-            var doubleJint = (JsNumber) doubleNet;
-            var integerNet = 42;
-            var integerJint = (JsNumber) integerNet;
-            var stringNet = "ABC";
-            var stringJint = (JsString) stringNet;
-            var arrayNet = new[] { 1, 2, 3 };
-            var arrayListNet = new List<int> { 1, 2, 3 };
-            var arrayJint = new JsArray(engine, arrayNet.Select(x => (JsNumber) x).ToArray());
-
-            var objectNet = new Person { Name = "name", Age = 12 };
-            var objectJint = new JsObject(engine);
-            objectJint["name"] = "name";
-            objectJint["age"] = 12;
-            objectJint[GlobalSymbolRegistry.ToStringTag] = "Object";
-
-            var dictionaryNet = new Dictionary<JsValue, JsValue>();
-            dictionaryNet["name"] = "name";
-            dictionaryNet["age"] = 12;
-            dictionaryNet[GlobalSymbolRegistry.ToStringTag] = "Object";
-        }
+        var engine = new Engine();
+        dynamic expando = new ExpandoObject();
+        expando.Name = "test";
+        engine.SetValue("expando", expando);
+        Assert.Equal("test", engine.Evaluate("expando.Name").ToString());
+    }
 
-        [Fact]
-        public void CanAccessMemberNamedItemThroughExpando()
-        {
-            var parent = (IDictionary<string, object>) new ExpandoObject();
-            var child = (IDictionary<string, object>) new ExpandoObject();
-            var values = (IDictionary<string, object>) new ExpandoObject();
+    [Fact]
+    public void DebugView()
+    {
+        // allows displaying different local variables under debugger
+
+        var engine = new Engine();
+        var boolNet = true;
+        var boolJint = (JsBoolean) boolNet;
+        var doubleNet = 12.34;
+        var doubleJint = (JsNumber) doubleNet;
+        var integerNet = 42;
+        var integerJint = (JsNumber) integerNet;
+        var stringNet = "ABC";
+        var stringJint = (JsString) stringNet;
+        var arrayNet = new[] { 1, 2, 3 };
+        var arrayListNet = new List<int> { 1, 2, 3 };
+        var arrayJint = new JsArray(engine, arrayNet.Select(x => (JsNumber) x).ToArray());
+
+        var objectNet = new Person { Name = "name", Age = 12 };
+        var objectJint = new JsObject(engine);
+        objectJint["name"] = "name";
+        objectJint["age"] = 12;
+        objectJint[GlobalSymbolRegistry.ToStringTag] = "Object";
+
+        var dictionaryNet = new Dictionary<JsValue, JsValue>();
+        dictionaryNet["name"] = "name";
+        dictionaryNet["age"] = 12;
+        dictionaryNet[GlobalSymbolRegistry.ToStringTag] = "Object";
+    }
 
-            parent["child"] = child;
-            child["item"] = values;
-            values["title"] = "abc";
+    [Fact]
+    public void CanAccessMemberNamedItemThroughExpando()
+    {
+        var parent = (IDictionary<string, object>) new ExpandoObject();
+        var child = (IDictionary<string, object>) new ExpandoObject();
+        var values = (IDictionary<string, object>) new ExpandoObject();
 
-            _engine.SetValue("parent", parent);
-            Assert.Equal("abc", _engine.Evaluate("parent.child.item.title"));
-        }
+        parent["child"] = child;
+        child["item"] = values;
+        values["title"] = "abc";
 
-        [Fact]
-        public void ShouldForOfOnExpandoObject()
-        {
-            dynamic o = new ExpandoObject();
-            o.a = 1;
-            o.b = 2;
+        _engine.SetValue("parent", parent);
+        Assert.Equal("abc", _engine.Evaluate("parent.child.item.title"));
+    }
 
-            _engine.SetValue("dynamic", o);
+    [Fact]
+    public void ShouldForOfOnExpandoObject()
+    {
+        dynamic o = new ExpandoObject();
+        o.a = 1;
+        o.b = 2;
 
-            var result = _engine.Evaluate("var l = ''; for (var x of dynamic) l += x; return l;").AsString();
+        _engine.SetValue("dynamic", o);
 
-            Assert.Equal("a,1b,2", result);
-        }
+        var result = _engine.Evaluate("var l = ''; for (var x of dynamic) l += x; return l;").AsString();
 
-        [Fact]
-        public void ShouldConvertObjectInstanceToExpando()
-        {
-            _engine.Evaluate("var o = {a: 1, b: 'foo'}");
-            var result = _engine.GetValue("o");
+        Assert.Equal("a,1b,2", result);
+    }
 
-            dynamic value = result.ToObject();
+    [Fact]
+    public void ShouldConvertObjectInstanceToExpando()
+    {
+        _engine.Evaluate("var o = {a: 1, b: 'foo'}");
+        var result = _engine.GetValue("o");
 
-            Assert.Equal(1, value.a);
-            Assert.Equal("foo", value.b);
+        dynamic value = result.ToObject();
 
-            var dic = (IDictionary<string, object>) result.ToObject();
+        Assert.Equal(1, value.a);
+        Assert.Equal("foo", value.b);
 
-            Assert.Equal(1d, dic["a"]);
-            Assert.Equal("foo", dic["b"]);
-        }
+        var dic = (IDictionary<string, object>) result.ToObject();
 
-        [Fact]
-        public void CanAccessDynamicObject()
-        {
-            var test = new DynamicClass();
-            var engine = new Engine();
-
-            engine.SetValue("test", test);
+        Assert.Equal(1d, dic["a"]);
+        Assert.Equal("foo", dic["b"]);
+    }
 
-            Assert.Equal("a", engine.Evaluate("test.a").AsString());
-            Assert.Equal("b", engine.Evaluate("test.b").AsString());
+    [Fact]
+    public void CanAccessDynamicObject()
+    {
+        var test = new DynamicClass();
+        var engine = new Engine();
 
-            engine.Evaluate("test.a = 5; test.b = 10; test.Name = 'Jint'");
+        engine.SetValue("test", test);
 
-            Assert.Equal(5, engine.Evaluate("test.a").AsNumber());
-            Assert.Equal(10, engine.Evaluate("test.b").AsNumber());
+        Assert.Equal("a", engine.Evaluate("test.a").AsString());
+        Assert.Equal("b", engine.Evaluate("test.b").AsString());
 
-            Assert.Equal("Jint", engine.Evaluate("test.Name").AsString());
-            Assert.True(engine.Evaluate("test.ContainsKey('a')").AsBoolean());
-            Assert.True(engine.Evaluate("test.ContainsKey('b')").AsBoolean());
-            Assert.False(engine.Evaluate("test.ContainsKey('c')").AsBoolean());
-        }
+        engine.Evaluate("test.a = 5; test.b = 10; test.Name = 'Jint'");
 
-        private class DynamicClass : DynamicObject
-        {
-            private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
+        Assert.Equal(5, engine.Evaluate("test.a").AsNumber());
+        Assert.Equal(10, engine.Evaluate("test.b").AsNumber());
 
-            public override bool TryGetMember(GetMemberBinder binder, out object result)
-            {
-                result = binder.Name;
-                if (_properties.TryGetValue(binder.Name, out var value))
-                {
-                    result = value;
-                }
+        Assert.Equal("Jint", engine.Evaluate("test.Name").AsString());
+        Assert.True(engine.Evaluate("test.ContainsKey('a')").AsBoolean());
+        Assert.True(engine.Evaluate("test.ContainsKey('b')").AsBoolean());
+        Assert.False(engine.Evaluate("test.ContainsKey('c')").AsBoolean());
+    }
 
-                return true;
-            }
+    private class DynamicClass : DynamicObject
+    {
+        private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
 
-            public override bool TrySetMember(SetMemberBinder binder, object value)
+        public override bool TryGetMember(GetMemberBinder binder, out object result)
+        {
+            result = binder.Name;
+            if (_properties.TryGetValue(binder.Name, out var value))
             {
-                _properties[binder.Name] = value;
-                return true;
+                result = value;
             }
 
-            public string Name { get; set; }
+            return true;
+        }
 
-            public bool ContainsKey(string key)
-            {
-                return _properties.ContainsKey(key);
-            }
+        public override bool TrySetMember(SetMemberBinder binder, object value)
+        {
+            _properties[binder.Name] = value;
+            return true;
         }
 
-        private class Person
+        public string Name { get; set; }
+
+        public bool ContainsKey(string key)
         {
-            public string Name { get; set; }
-            public int Age { get; set; }
+            return _properties.ContainsKey(key);
         }
     }
-}
+
+    private class Person
+    {
+        public string Name { get; set; }
+        public int Age { get; set; }
+    }
+}

+ 121 - 122
Jint.Tests.PublicInterface/InteropTests.NewtonsoftJson.cs

@@ -2,53 +2,53 @@ using Jint.Native;
 using Jint.Runtime;
 using Newtonsoft.Json.Linq;
 
-namespace Jint.Tests.PublicInterface
+namespace Jint.Tests.PublicInterface;
+
+public partial class InteropTests
 {
-    public partial class InteropTests
+    [Fact]
+    public void AccessingJObjectShouldWork()
     {
-        [Fact]
-        public void AccessingJObjectShouldWork()
-        {
-            var o = new JObject
-            {
-                new JProperty("name", "test-name")
-            };
-            _engine.SetValue("o", o);
-            Assert.True(_engine.Evaluate("return o.name == 'test-name'").AsBoolean());
-        }
-
-        [Fact]
-        public void AccessingJArrayViaIntegerIndexShouldWork()
-        {
-            var o = new JArray("item1", "item2");
-            _engine.SetValue("o", o);
-            Assert.True(_engine.Evaluate("return o[0] == 'item1'").AsBoolean());
-            Assert.True(_engine.Evaluate("return o[1] == 'item2'").AsBoolean());
-        }
-
-        [Fact]
-        public void DictionaryLikeShouldCheckIndexerAndFallBackToProperty()
+        var o = new JObject
         {
-            const string json = @"{ ""Type"": ""Cat"" }";
-            var jObjectWithTypeProperty = JObject.Parse(json);
+            new JProperty("name", "test-name")
+        };
+        _engine.SetValue("o", o);
+        Assert.True(_engine.Evaluate("return o.name == 'test-name'").AsBoolean());
+    }
+
+    [Fact]
+    public void AccessingJArrayViaIntegerIndexShouldWork()
+    {
+        var o = new JArray("item1", "item2");
+        _engine.SetValue("o", o);
+        Assert.True(_engine.Evaluate("return o[0] == 'item1'").AsBoolean());
+        Assert.True(_engine.Evaluate("return o[1] == 'item2'").AsBoolean());
+    }
 
-            _engine.SetValue("o", jObjectWithTypeProperty);
+    [Fact]
+    public void DictionaryLikeShouldCheckIndexerAndFallBackToProperty()
+    {
+        const string json = @"{ ""Type"": ""Cat"" }";
+        var jObjectWithTypeProperty = JObject.Parse(json);
 
-            var typeResult = _engine.Evaluate("o.Type");
+        _engine.SetValue("o", jObjectWithTypeProperty);
 
-            // JToken requires conversion
-            Assert.Equal("Cat", TypeConverter.ToString(typeResult));
+        var typeResult = _engine.Evaluate("o.Type");
 
-            // weak equality does conversions from native types
-            Assert.True(_engine.Evaluate("o.Type == 'Cat'").AsBoolean());
-        }
+        // JToken requires conversion
+        Assert.Equal("Cat", TypeConverter.ToString(typeResult));
 
-        [Fact]
-        public void ShouldBeAbleToIndexJObjectWithStrings()
-        {
-            var engine = new Engine();
+        // weak equality does conversions from native types
+        Assert.True(_engine.Evaluate("o.Type == 'Cat'").AsBoolean());
+    }
+
+    [Fact]
+    public void ShouldBeAbleToIndexJObjectWithStrings()
+    {
+        var engine = new Engine();
 
-            const string json = @"
+        const string json = @"
             {
                 'Properties': {
                     'expirationDate': {
@@ -57,103 +57,102 @@ namespace Jint.Tests.PublicInterface
                 }
             }";
 
-            var obj = JObject.Parse(json);
-            engine.SetValue("o", obj);
-            var value = engine.Evaluate("o.Properties.expirationDate.Value");
-            var dateInstance = Assert.IsAssignableFrom<JsDate>(value);
-            Assert.Equal(DateTime.Parse("2021-10-09T00:00:00Z").ToUniversalTime(), dateInstance.ToDateTime());
-        }
+        var obj = JObject.Parse(json);
+        engine.SetValue("o", obj);
+        var value = engine.Evaluate("o.Properties.expirationDate.Value");
+        var dateInstance = Assert.IsAssignableFrom<JsDate>(value);
+        Assert.Equal(DateTime.Parse("2021-10-09T00:00:00Z").ToUniversalTime(), dateInstance.ToDateTime());
+    }
 
-        // https://github.com/OrchardCMS/OrchardCore/issues/10648
-        [Fact]
-        public void EngineShouldStringifyAnJObjectListWithValuesCorrectly()
+    // https://github.com/OrchardCMS/OrchardCore/issues/10648
+    [Fact]
+    public void EngineShouldStringifyAnJObjectListWithValuesCorrectly()
+    {
+        var engine = new Engine();
+        var queryResults = new List<dynamic>
         {
-            var engine = new Engine();
-            var queryResults = new List<dynamic>
-            {
-                new { Text = "Text1", Value = 1 },
-                new { Text = "Text2", Value = 2 }
-            };
+            new { Text = "Text1", Value = 1 },
+            new { Text = "Text2", Value = 2 }
+        };
 
-            engine.SetValue("testSubject", queryResults.Select(x => JObject.FromObject(x)));
-            var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
-            var result = fromEngine.ToString();
+        engine.SetValue("testSubject", queryResults.Select(x => JObject.FromObject(x)));
+        var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
+        var result = fromEngine.ToString();
 
-            // currently we do not materialize LINQ enumerables
-            // Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result);
+        // currently we do not materialize LINQ enumerables
+        // Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result);
 
-            Assert.Equal("{\"Current\":null}", result);
-        }
+        Assert.Equal("{\"Current\":null}", result);
+    }
 
-        [Fact]
-        public void EngineShouldStringifyJObjectFromObjectListWithValuesCorrectly()
-        {
-            var engine = new Engine();
+    [Fact]
+    public void EngineShouldStringifyJObjectFromObjectListWithValuesCorrectly()
+    {
+        var engine = new Engine();
 
-            var source = new dynamic[]
-            {
-                new { Text = "Text1", Value = 1 },
-                new { Text = "Text2", Value = 2, Null = (object) null, Date = new DateTime(2015, 6, 25, 0, 0, 0, DateTimeKind.Utc) }
-            };
+        var source = new dynamic[]
+        {
+            new { Text = "Text1", Value = 1 },
+            new { Text = "Text2", Value = 2, Null = (object) null, Date = new DateTime(2015, 6, 25, 0, 0, 0, DateTimeKind.Utc) }
+        };
 
-            engine.SetValue("testSubject", source.Select(x => JObject.FromObject(x)).ToList());
-            var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
-            var result = fromEngine.ToString();
+        engine.SetValue("testSubject", source.Select(x => JObject.FromObject(x)).ToList());
+        var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
+        var result = fromEngine.ToString();
 
-            Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2,\"Null\":null,\"Date\":\"2015-06-25T00:00:00.000Z\"}]", result);
-        }
+        Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2,\"Null\":null,\"Date\":\"2015-06-25T00:00:00.000Z\"}]", result);
+    }
 
-        [Fact]
-        public void DecimalsShouldBeHandledFromJObjects()
-        {
-            var test = JObject.FromObject(new
-            {
-                DecimalValue = 123.456m
-            });
-            _engine.SetValue("test", test);
-            var fromInterop = _engine.Evaluate("test.DecimalValue");
-            var number = Assert.IsType<JsNumber>(fromInterop);
-            Assert.Equal(123.456d, number.AsNumber());
-        }
-
-        [Fact]
-        public void ShouldBeAbleToChangePropertyWithNameValue()
+    [Fact]
+    public void DecimalsShouldBeHandledFromJObjects()
+    {
+        var test = JObject.FromObject(new
         {
-            var engine = new Engine();
+            DecimalValue = 123.456m
+        });
+        _engine.SetValue("test", test);
+        var fromInterop = _engine.Evaluate("test.DecimalValue");
+        var number = Assert.IsType<JsNumber>(fromInterop);
+        Assert.Equal(123.456d, number.AsNumber());
+    }
 
-            var input = Newtonsoft.Json.JsonConvert.DeserializeObject(@"{ ""value"": ""ORIGINAL"" }");
-            var result = engine
-                .SetValue("input", input)
-                .Evaluate("input.value = \"CHANGED\"; input.value")
-                .AsString();
+    [Fact]
+    public void ShouldBeAbleToChangePropertyWithNameValue()
+    {
+        var engine = new Engine();
 
-            Assert.Equal("CHANGED", result);
-        }
+        var input = Newtonsoft.Json.JsonConvert.DeserializeObject(@"{ ""value"": ""ORIGINAL"" }");
+        var result = engine
+            .SetValue("input", input)
+            .Evaluate("input.value = \"CHANGED\"; input.value")
+            .AsString();
 
-        [Fact]
-        public void ArraysShouldPassThroughCorrectly()
-        {
-            var engine = new Engine();
+        Assert.Equal("CHANGED", result);
+    }
 
-            const string Json = """
-            {
-                'entries': [
-                    { 'id': 1, 'name': 'One' },
-                    { 'id': 2, 'name': 'Two' },
-                    { 'id': 3, 'name': 'Three' }
-                ]
-            }
-            """;
-
-            var obj = JObject.Parse(Json);
-            engine.SetValue("o", obj);
-
-            var names = engine.Evaluate("o.entries.map(e => e.name)").AsArray();
-
-            Assert.Equal((uint) 3, names.Length);
-            Assert.Equal("One", names[0]);
-            Assert.Equal("Two", names[1]);
-            Assert.Equal("Three", names[2]);
-        }
+    [Fact]
+    public void ArraysShouldPassThroughCorrectly()
+    {
+        var engine = new Engine();
+
+        const string Json = """
+                            {
+                                'entries': [
+                                    { 'id': 1, 'name': 'One' },
+                                    { 'id': 2, 'name': 'Two' },
+                                    { 'id': 3, 'name': 'Three' }
+                                ]
+                            }
+                            """;
+
+        var obj = JObject.Parse(Json);
+        engine.SetValue("o", obj);
+
+        var names = engine.Evaluate("o.entries.map(e => e.name)").AsArray();
+
+        Assert.Equal((uint) 3, names.Length);
+        Assert.Equal("One", names[0]);
+        Assert.Equal("Two", names[1]);
+        Assert.Equal("Three", names[2]);
     }
-}
+}

+ 17 - 18
Jint.Tests.PublicInterface/InteropTests.cs

@@ -1,24 +1,23 @@
 using System.Reflection;
 
-namespace Jint.Tests.PublicInterface
+namespace Jint.Tests.PublicInterface;
+
+public partial class InteropTests : IDisposable
 {
-    public partial class InteropTests : IDisposable
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public InteropTests()
-        {
-            _engine = new Engine(cfg => cfg.AllowClr(
-                        typeof(Console).GetTypeInfo().Assembly,
-                        typeof(File).GetTypeInfo().Assembly))
-                    .SetValue("log", new Action<object>(Console.WriteLine))
-                    .SetValue("assert", new Action<bool>(Assert.True))
-                    .SetValue("equal", new Action<object, object>(Assert.Equal))
-                ;
-        }
+    public InteropTests()
+    {
+        _engine = new Engine(cfg => cfg.AllowClr(
+                    typeof(Console).GetTypeInfo().Assembly,
+                    typeof(File).GetTypeInfo().Assembly))
+                .SetValue("log", new Action<object>(Console.WriteLine))
+                .SetValue("assert", new Action<bool>(Assert.True))
+                .SetValue("equal", new Action<object, object>(Assert.Equal))
+            ;
+    }
 
-        void IDisposable.Dispose()
-        {
-        }
+    void IDisposable.Dispose()
+    {
     }
-}
+}

+ 25 - 26
Jint.Tests.PublicInterface/JavaScriptExceptionTests.cs

@@ -1,37 +1,36 @@
 using Jint.Native;
 using Jint.Runtime;
 
-namespace Jint.Tests.PublicInterface
+namespace Jint.Tests.PublicInterface;
+
+public class JavaScriptExceptionTests
 {
-    public class JavaScriptExceptionTests
+    [Fact]
+    public void CanCreateAndThrowJavaScriptException()
     {
-        [Fact]
-        public void CanCreateAndThrowJavaScriptException()
-        {
-            var engine = new Engine();
+        var engine = new Engine();
 
-            engine.SetValue("throw1", () =>
-            {
-                throw new JavaScriptException(engine.Intrinsics.Error, "message 1");
-            });
+        engine.SetValue("throw1", () =>
+        {
+            throw new JavaScriptException(engine.Intrinsics.Error, "message 1");
+        });
 
-            engine.SetValue("throw2", () =>
-            {
-                throw new JavaScriptException(new JsString("message 2"));
-            });
+        engine.SetValue("throw2", () =>
+        {
+            throw new JavaScriptException(new JsString("message 2"));
+        });
 
-            Assert.Throws<JavaScriptException>(() =>
-            {
-                engine.Evaluate(@"throw1()");
-            });
+        Assert.Throws<JavaScriptException>(() =>
+        {
+            engine.Evaluate(@"throw1()");
+        });
 
-            var result1 = engine.Evaluate(@"try { throw1() } catch (e) { return e; }");
-            var error1 = Assert.IsType<JsError>(result1);
-            Assert.Equal("message 1", error1.Get("message").ToString());
+        var result1 = engine.Evaluate(@"try { throw1() } catch (e) { return e; }");
+        var error1 = Assert.IsType<JsError>(result1);
+        Assert.Equal("message 1", error1.Get("message").ToString());
 
-            var result2 = engine.Evaluate(@"try { throw2() } catch (e) { return e; }");
-            var jsString = Assert.IsType<JsString>(result2);
-            Assert.Equal("message 2", jsString.ToString());
-        }
+        var result2 = engine.Evaluate(@"try { throw2() } catch (e) { return e; }");
+        var jsString = Assert.IsType<JsString>(result2);
+        Assert.Equal("message 2", jsString.ToString());
     }
-}
+}

+ 46 - 47
Jint.Tests/ReplaceCulture.cs

@@ -5,42 +5,42 @@ using System.Globalization;
 using System.Reflection;
 using Xunit.Sdk;
 
-namespace Jint.Tests
+namespace Jint.Tests;
+
+/// <summary>
+/// Replaces the current culture and UI culture for the test.
+/// </summary>
+[AttributeUsage(AttributeTargets.Method)]
+public class ReplaceCultureAttribute : BeforeAfterTestAttribute
 {
+    private CultureInfo _originalCulture;
+    private CultureInfo _originalUICulture;
+
     /// <summary>
-    /// Replaces the current culture and UI culture for the test.
+    /// Replaces the current culture and UI culture based on specified value.
     /// </summary>
-    [AttributeUsage(AttributeTargets.Method)]
-    public class ReplaceCultureAttribute : BeforeAfterTestAttribute
+    public ReplaceCultureAttribute(string currentCulture) : this(currentCulture, currentCulture)
     {
-        private CultureInfo _originalCulture;
-        private CultureInfo _originalUICulture;
-
-        /// <summary>
-        /// Replaces the current culture and UI culture based on specified value.
-        /// </summary>
-        public ReplaceCultureAttribute(string currentCulture) : this(currentCulture, currentCulture)
-        {
-        }
+    }
 
-        /// <summary>
-        /// Replaces the current culture and UI culture based on specified values.
-        /// </summary>
-        public ReplaceCultureAttribute(string currentCulture, string currentUICulture)
-        {
-            Culture = new CultureInfo(currentCulture);
-            UICulture = new CultureInfo(currentUICulture);
-        }
+    /// <summary>
+    /// Replaces the current culture and UI culture based on specified values.
+    /// </summary>
+    public ReplaceCultureAttribute(string currentCulture, string currentUICulture)
+    {
+        Culture = new CultureInfo(currentCulture);
+        UICulture = new CultureInfo(currentUICulture);
+    }
 
 #if NETFRAMEWORK
-        /// <summary>
-        /// The <see cref="Thread.CurrentCulture"/> for the test. Defaults to en-GB.
-        /// </summary>
-        /// <remarks>
-        /// en-GB is used here as the default because en-US is equivalent to the InvariantCulture. We
-        /// want to be able to find bugs where we're accidentally relying on the Invariant instead of the
-        /// user's culture.
-        /// </remarks>
+    /// <summary>
+    /// The <see cref="Thread.CurrentCulture"/> for the test. Defaults to en-GB.
+    /// </summary>
+    /// <remarks>
+    /// en-GB is used here as the default because en-US is equivalent to the InvariantCulture. We
+    /// want to be able to find bugs where we're accidentally relying on the Invariant instead of the
+    /// user's culture.
+    /// </remarks>
 #else
         /// <summary>
         /// The <see cref="CultureInfo.CurrentCulture"/> for the test. Defaults to en-GB.
@@ -51,43 +51,42 @@ namespace Jint.Tests
         /// user's culture.
         /// </remarks>
 #endif
-        public CultureInfo Culture { get; }
+    public CultureInfo Culture { get; }
 
 #if NETFRAMEWORK
-        /// <summary>
-        /// The <see cref="Thread.CurrentUICulture"/> for the test. Defaults to en-US.
-        /// </summary>
+    /// <summary>
+    /// The <see cref="Thread.CurrentUICulture"/> for the test. Defaults to en-US.
+    /// </summary>
 #else
         /// <summary>
         /// The <see cref="CultureInfo.CurrentUICulture"/> for the test. Defaults to en-US.
         /// </summary>
 #endif
-        public CultureInfo UICulture { get; }
+    public CultureInfo UICulture { get; }
 
-        public override void Before(MethodInfo methodUnderTest)
-        {
-            _originalCulture = CultureInfo.CurrentCulture;
-            _originalUICulture = CultureInfo.CurrentUICulture;
+    public override void Before(MethodInfo methodUnderTest)
+    {
+        _originalCulture = CultureInfo.CurrentCulture;
+        _originalUICulture = CultureInfo.CurrentUICulture;
 
 #if NETFRAMEWORK
-            System.Threading.Thread.CurrentThread.CurrentCulture = Culture;
-            System.Threading.Thread.CurrentThread.CurrentUICulture = UICulture;
+        System.Threading.Thread.CurrentThread.CurrentCulture = Culture;
+        System.Threading.Thread.CurrentThread.CurrentUICulture = UICulture;
 #else
             CultureInfo.CurrentCulture = Culture;
             CultureInfo.CurrentUICulture = UICulture;
 #endif
 
-        }
+    }
 
-        public override void After(MethodInfo methodUnderTest)
-        {
+    public override void After(MethodInfo methodUnderTest)
+    {
 #if NETFRAMEWORK
-            System.Threading.Thread.CurrentThread.CurrentCulture = _originalCulture;
-            System.Threading.Thread.CurrentThread.CurrentUICulture = _originalUICulture;
+        System.Threading.Thread.CurrentThread.CurrentCulture = _originalCulture;
+        System.Threading.Thread.CurrentThread.CurrentUICulture = _originalUICulture;
 #else
             CultureInfo.CurrentCulture = _originalCulture;
             CultureInfo.CurrentUICulture = _originalUICulture;
 #endif
-        }
     }
-}
+}

+ 7 - 8
Jint.Tests/RunnableInDebugOnlyAttribute.cs

@@ -1,15 +1,14 @@
 using System.Diagnostics;
 
-namespace Jint.Tests
+namespace Jint.Tests;
+
+public class RunnableInDebugOnlyAttribute : FactAttribute
 {
-    public class RunnableInDebugOnlyAttribute : FactAttribute
+    public RunnableInDebugOnlyAttribute()
     {
-        public RunnableInDebugOnlyAttribute()
+        if (!Debugger.IsAttached)
         {
-            if (!Debugger.IsAttached)
-            {
-                Skip = "Only running in interactive mode.";
-            }
+            Skip = "Only running in interactive mode.";
         }
     }
-}
+}

+ 17 - 18
Jint.Tests/Runtime/CallStackTests.cs

@@ -1,12 +1,12 @@
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class CallStackTests
 {
-    public class CallStackTests
+    [Fact]
+    public void ShouldUnwindAfterCaughtException()
     {
-        [Fact]
-        public void ShouldUnwindAfterCaughtException()
-        {
-            var engine = new Engine();
-            engine.Execute(@"
+        var engine = new Engine();
+        engine.Execute(@"
                 function thrower()
                 {
                     throw new Error('test');
@@ -20,15 +20,15 @@
                 {
                 }
                 "
-            );
-            Assert.Equal(0, engine.CallStack.Count);
-        }
+        );
+        Assert.Equal(0, engine.CallStack.Count);
+    }
 
-        [Fact]
-        public void ShouldUnwindAfterCaughtExceptionNested()
-        {
-            var engine = new Engine();
-            engine.Execute(@"
+    [Fact]
+    public void ShouldUnwindAfterCaughtExceptionNested()
+    {
+        var engine = new Engine();
+        engine.Execute(@"
                 function thrower2()
                 {
                     throw new Error('test');
@@ -47,7 +47,6 @@
                 {
                 }
             ");
-            Assert.Equal(0, engine.CallStack.Count);
-        }
+        Assert.Equal(0, engine.CallStack.Count);
     }
-}
+}

+ 26 - 27
Jint.Tests/Runtime/ConstTests.cs

@@ -1,21 +1,21 @@
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class ConstTests
 {
-    public class ConstTests
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public ConstTests()
-        {
-            _engine = new Engine()
-                .SetValue("log", new Action<object>(Console.WriteLine))
-                .SetValue("assert", new Action<bool>(Assert.True))
-                .SetValue("equal", new Action<object, object>(Assert.Equal));
-        }
+    public ConstTests()
+    {
+        _engine = new Engine()
+            .SetValue("log", new Action<object>(Console.WriteLine))
+            .SetValue("assert", new Action<bool>(Assert.True))
+            .SetValue("equal", new Action<object, object>(Assert.Equal));
+    }
 
-        [Fact]
-        public void ConstInsideIife()
-        {
-            _engine.Execute(@"
+    [Fact]
+    public void ConstInsideIife()
+    {
+        _engine.Execute(@"
                 (function(){
                     const testVariable = 'test';
                     function render() {
@@ -24,23 +24,23 @@ namespace Jint.Tests.Runtime
                     render();
                 })();
             ");
-        }
+    }
 
-        [Fact]
-        public void ConstDestructuring()
-        {
-            _engine.Execute(@"
+    [Fact]
+    public void ConstDestructuring()
+    {
+        _engine.Execute(@"
                 let obj = {};
                 for (var i = 0; i < 1; i++) {
                     const { subElement } = obj;
                 }
             ");
-        }
+    }
 
-        [Fact]
-        public void DestructuringWithFunctionArgReferenceInStrictMode()
-        {
-            _engine.Execute(@"
+    [Fact]
+    public void DestructuringWithFunctionArgReferenceInStrictMode()
+    {
+        _engine.Execute(@"
                 'use strict';
                 function tst(a) {
                     let [let1, let2, let3] = a;
@@ -60,6 +60,5 @@ namespace Jint.Tests.Runtime
 
                 tst([1,2])
             ");
-        }
     }
-}
+}

+ 11 - 12
Jint.Tests/Runtime/Converters/EnumsToStringConverter.cs

@@ -1,20 +1,19 @@
 using Jint.Native;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime.Converters
+namespace Jint.Tests.Runtime.Converters;
+
+public class EnumsToStringConverter : IObjectConverter
 {
-    public class EnumsToStringConverter : IObjectConverter
+    public bool TryConvert(Engine engine, object value, out JsValue result)
     {
-        public bool TryConvert(Engine engine, object value, out JsValue result)
+        if (value is Enum)
         {
-            if (value is Enum)
-            {
-                result = value.ToString();
-                return true;
-            }
-
-            result = JsValue.Null;
-            return false;
+            result = value.ToString();
+            return true;
         }
+
+        result = JsValue.Null;
+        return false;
     }
-}
+}

+ 11 - 12
Jint.Tests/Runtime/Converters/NegateBoolConverter.cs

@@ -1,20 +1,19 @@
 using Jint.Native;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime.Converters
+namespace Jint.Tests.Runtime.Converters;
+
+public class NegateBoolConverter : IObjectConverter
 {
-    public class NegateBoolConverter : IObjectConverter
+    public bool TryConvert(Engine engine, object value, out JsValue result)
     {
-        public bool TryConvert(Engine engine, object value, out JsValue result)
+        if (value is bool b)
         {
-            if (value is bool b)
-            {
-                result = !b;
-                return true;
-            }
-
-            result = JsValue.Null;
-            return false;
+            result = !b;
+            return true;
         }
+
+        result = JsValue.Null;
+        return false;
     }
-}
+}

+ 352 - 353
Jint.Tests/Runtime/Debugger/BreakPointTests.cs

@@ -1,338 +1,338 @@
 using Jint.Runtime.Debugger;
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public class BreakPointTests
 {
-    public class BreakPointTests
+    [Fact]
+    public void BreakLocationsCompareEqualityByValue()
     {
-        [Fact]
-        public void BreakLocationsCompareEqualityByValue()
-        {
-            var loc1 = new BreakLocation(42, 23);
-            var loc2 = new BreakLocation(42, 23);
-            var loc3 = new BreakLocation(17, 7);
-
-            Assert.Equal(loc1, loc2);
-            Assert.True(loc1 == loc2);
-            Assert.True(loc2 != loc3);
-            Assert.False(loc1 != loc2);
-            Assert.False(loc2 == loc3);
-        }
+        var loc1 = new BreakLocation(42, 23);
+        var loc2 = new BreakLocation(42, 23);
+        var loc3 = new BreakLocation(17, 7);
+
+        Assert.Equal(loc1, loc2);
+        Assert.True(loc1 == loc2);
+        Assert.True(loc2 != loc3);
+        Assert.False(loc1 != loc2);
+        Assert.False(loc2 == loc3);
+    }
 
-        [Fact]
-        public void BreakLocationsWithSourceCompareEqualityByValue()
-        {
-            var loc1 = new BreakLocation("script1", 42, 23);
-            var loc2 = new BreakLocation("script1", 42, 23);
-            var loc3 = new BreakLocation("script2", 42, 23);
-
-            Assert.Equal(loc1, loc2);
-            Assert.True(loc1 == loc2);
-            Assert.True(loc2 != loc3);
-            Assert.False(loc1 != loc2);
-            Assert.False(loc2 == loc3);
-        }
+    [Fact]
+    public void BreakLocationsWithSourceCompareEqualityByValue()
+    {
+        var loc1 = new BreakLocation("script1", 42, 23);
+        var loc2 = new BreakLocation("script1", 42, 23);
+        var loc3 = new BreakLocation("script2", 42, 23);
+
+        Assert.Equal(loc1, loc2);
+        Assert.True(loc1 == loc2);
+        Assert.True(loc2 != loc3);
+        Assert.False(loc1 != loc2);
+        Assert.False(loc2 == loc3);
+    }
 
-        [Fact]
-        public void BreakLocationsOptionalSourceEqualityComparer()
-        {
-            var script1 = new BreakLocation("script1", 42, 23);
-            var script2 = new BreakLocation("script2", 42, 23);
-            var script2b = new BreakLocation("script2", 44, 23);
-            var any = new BreakLocation(null, 42, 23);
-
-            var comparer = new OptionalSourceBreakLocationEqualityComparer();
-            Assert.True(comparer.Equals(script1, any));
-            Assert.True(comparer.Equals(script2, any));
-            Assert.False(comparer.Equals(script1, script2));
-            Assert.False(comparer.Equals(script2, script2b));
-            Assert.Equal(comparer.GetHashCode(script1), comparer.GetHashCode(any));
-            Assert.Equal(comparer.GetHashCode(script1), comparer.GetHashCode(script2));
-            Assert.NotEqual(comparer.GetHashCode(script2), comparer.GetHashCode(script2b));
-        }
+    [Fact]
+    public void BreakLocationsOptionalSourceEqualityComparer()
+    {
+        var script1 = new BreakLocation("script1", 42, 23);
+        var script2 = new BreakLocation("script2", 42, 23);
+        var script2b = new BreakLocation("script2", 44, 23);
+        var any = new BreakLocation(null, 42, 23);
+
+        var comparer = new OptionalSourceBreakLocationEqualityComparer();
+        Assert.True(comparer.Equals(script1, any));
+        Assert.True(comparer.Equals(script2, any));
+        Assert.False(comparer.Equals(script1, script2));
+        Assert.False(comparer.Equals(script2, script2b));
+        Assert.Equal(comparer.GetHashCode(script1), comparer.GetHashCode(any));
+        Assert.Equal(comparer.GetHashCode(script1), comparer.GetHashCode(script2));
+        Assert.NotEqual(comparer.GetHashCode(script2), comparer.GetHashCode(script2b));
+    }
 
-        [Fact]
-        public void BreakPointReplacesPreviousBreakPoint()
-        {
-            var engine = new Engine(options => options.DebugMode());
-
-            engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5, "i === 1"));
-            Assert.Collection(engine.Debugger.BreakPoints,
-                breakPoint =>
-                {
-                    Assert.Equal(4, breakPoint.Location.Line);
-                    Assert.Equal(5, breakPoint.Location.Column);
-                    Assert.Equal("i === 1", breakPoint.Condition);
-                });
-
-            engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5));
-            Assert.Collection(engine.Debugger.BreakPoints,
-                breakPoint =>
-                {
-                    Assert.Equal(4, breakPoint.Location.Line);
-                    Assert.Equal(5, breakPoint.Location.Column);
-                    Assert.Equal(null, breakPoint.Condition);
-                });
-        }
+    [Fact]
+    public void BreakPointReplacesPreviousBreakPoint()
+    {
+        var engine = new Engine(options => options.DebugMode());
 
-        [Fact]
-        public void BreakPointRemovesBasedOnLocationEquality()
-        {
-            var engine = new Engine(options => options.DebugMode());
-
-            engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5, "i === 1"));
-            engine.Debugger.BreakPoints.Set(new BreakPoint(5, 6, "j === 2"));
-            engine.Debugger.BreakPoints.Set(new BreakPoint(10, 7, "x > 5"));
-            Assert.Equal(3, engine.Debugger.BreakPoints.Count);
-
-            engine.Debugger.BreakPoints.RemoveAt(new BreakLocation(null, 4, 5));
-            engine.Debugger.BreakPoints.RemoveAt(new BreakLocation(null, 10, 7));
-
-            Assert.Collection(engine.Debugger.BreakPoints,
-                breakPoint =>
-                {
-                    Assert.Equal(5, breakPoint.Location.Line);
-                    Assert.Equal(6, breakPoint.Location.Column);
-                    Assert.Equal("j === 2", breakPoint.Condition);
-                });
-        }
+        engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5, "i === 1"));
+        Assert.Collection(engine.Debugger.BreakPoints,
+            breakPoint =>
+            {
+                Assert.Equal(4, breakPoint.Location.Line);
+                Assert.Equal(5, breakPoint.Location.Column);
+                Assert.Equal("i === 1", breakPoint.Condition);
+            });
+
+        engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5));
+        Assert.Collection(engine.Debugger.BreakPoints,
+            breakPoint =>
+            {
+                Assert.Equal(4, breakPoint.Location.Line);
+                Assert.Equal(5, breakPoint.Location.Column);
+                Assert.Equal(null, breakPoint.Condition);
+            });
+    }
 
-        [Fact]
-        public void BreakPointContainsBasedOnLocationEquality()
-        {
-            var engine = new Engine(options => options.DebugMode());
+    [Fact]
+    public void BreakPointRemovesBasedOnLocationEquality()
+    {
+        var engine = new Engine(options => options.DebugMode());
 
-            engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5, "i === 1"));
-            engine.Debugger.BreakPoints.Set(new BreakPoint(5, 6, "j === 2"));
-            engine.Debugger.BreakPoints.Set(new BreakPoint(10, 7, "x > 5"));
-            Assert.True(engine.Debugger.BreakPoints.Contains(new BreakLocation(null, 5, 6)));
-            Assert.False(engine.Debugger.BreakPoints.Contains(new BreakLocation(null, 8, 9)));
-        }
+        engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5, "i === 1"));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(5, 6, "j === 2"));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(10, 7, "x > 5"));
+        Assert.Equal(3, engine.Debugger.BreakPoints.Count);
 
-        [Fact]
-        public void BreakPointBreaksAtPosition()
-        {
-            string script = @"let x = 1, y = 2;
+        engine.Debugger.BreakPoints.RemoveAt(new BreakLocation(null, 4, 5));
+        engine.Debugger.BreakPoints.RemoveAt(new BreakLocation(null, 10, 7));
+
+        Assert.Collection(engine.Debugger.BreakPoints,
+            breakPoint =>
+            {
+                Assert.Equal(5, breakPoint.Location.Line);
+                Assert.Equal(6, breakPoint.Location.Column);
+                Assert.Equal("j === 2", breakPoint.Condition);
+            });
+    }
+
+    [Fact]
+    public void BreakPointContainsBasedOnLocationEquality()
+    {
+        var engine = new Engine(options => options.DebugMode());
+
+        engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5, "i === 1"));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(5, 6, "j === 2"));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(10, 7, "x > 5"));
+        Assert.True(engine.Debugger.BreakPoints.Contains(new BreakLocation(null, 5, 6)));
+        Assert.False(engine.Debugger.BreakPoints.Contains(new BreakLocation(null, 8, 9)));
+    }
+
+    [Fact]
+    public void BreakPointBreaksAtPosition()
+    {
+        string script = @"let x = 1, y = 2;
 if (x === 1)
 {
 x++; y *= 2;
 }";
 
-            var engine = new Engine(options => options.DebugMode());
-
-            bool didBreak = false;
-            engine.Debugger.Break += (sender, info) =>
-            {
-                Assert.Equal(4, info.Location.Start.Line);
-                Assert.Equal(5, info.Location.Start.Column);
-                didBreak = true;
-                return StepMode.None;
-            };
-
-            engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5));
-            engine.Execute(script);
-            Assert.True(didBreak);
-        }
+        var engine = new Engine(options => options.DebugMode());
 
-        [Fact]
-        public void BreakPointBreaksInCorrectSource()
+        bool didBreak = false;
+        engine.Debugger.Break += (sender, info) =>
         {
-            string script1 = @"let x = 1, y = 2;
+            Assert.Equal(4, info.Location.Start.Line);
+            Assert.Equal(5, info.Location.Start.Column);
+            didBreak = true;
+            return StepMode.None;
+        };
+
+        engine.Debugger.BreakPoints.Set(new BreakPoint(4, 5));
+        engine.Execute(script);
+        Assert.True(didBreak);
+    }
+
+    [Fact]
+    public void BreakPointBreaksInCorrectSource()
+    {
+        string script1 = @"let x = 1, y = 2;
 if (x === 1)
 {
 x++; y *= 2;
 }";
 
-            string script2 = @"function test(x)
+        string script2 = @"function test(x)
 {
 return x + 2;
 }";
 
-            string script3 = @"const z = 3;
+        string script3 = @"const z = 3;
 test(z);";
 
-            var engine = new Engine(options => { options.DebugMode(); });
-
-            engine.Debugger.BreakPoints.Set(new BreakPoint("script2", 3, 0));
-
-            bool didBreak = false;
-            engine.Debugger.Break += (sender, info) =>
-            {
-                Assert.Equal("script2", info.Location.SourceFile);
-                Assert.Equal(3, info.Location.Start.Line);
-                Assert.Equal(0, info.Location.Start.Column);
-                didBreak = true;
-                return StepMode.None;
-            };
-
-            // We need to specify the source to the parser.
-            // And we need locations too (Jint specifies that in its default options)
-            engine.Execute(script1, "script1");
-            Assert.False(didBreak);
-
-            engine.Execute(script2, "script2");
-            Assert.False(didBreak);
+        var engine = new Engine(options => { options.DebugMode(); });
 
-            // Note that it's actually script3 that executes the function in script2
-            // and triggers the breakpoint
-            engine.Execute(script3, "script3");
-            Assert.True(didBreak);
-        }
+        engine.Debugger.BreakPoints.Set(new BreakPoint("script2", 3, 0));
 
-        [Fact]
-        public void DebuggerStatementTriggersBreak()
+        bool didBreak = false;
+        engine.Debugger.Break += (sender, info) =>
         {
-            string script = @"'dummy';
+            Assert.Equal("script2", info.Location.SourceFile);
+            Assert.Equal(3, info.Location.Start.Line);
+            Assert.Equal(0, info.Location.Start.Column);
+            didBreak = true;
+            return StepMode.None;
+        };
+
+        // We need to specify the source to the parser.
+        // And we need locations too (Jint specifies that in its default options)
+        engine.Execute(script1, "script1");
+        Assert.False(didBreak);
+
+        engine.Execute(script2, "script2");
+        Assert.False(didBreak);
+
+        // Note that it's actually script3 that executes the function in script2
+        // and triggers the breakpoint
+        engine.Execute(script3, "script3");
+        Assert.True(didBreak);
+    }
+
+    [Fact]
+    public void DebuggerStatementTriggersBreak()
+    {
+        string script = @"'dummy';
 debugger;
 'dummy';";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script));
 
-            bool didBreak = false;
-            engine.Debugger.Break += (sender, info) =>
-            {
-                Assert.Equal(PauseType.DebuggerStatement, info.PauseType);
-                didBreak = true;
-                return StepMode.None;
-            };
+        bool didBreak = false;
+        engine.Debugger.Break += (sender, info) =>
+        {
+            Assert.Equal(PauseType.DebuggerStatement, info.PauseType);
+            didBreak = true;
+            return StepMode.None;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            Assert.True(didBreak);
-        }
+        Assert.True(didBreak);
+    }
 
-        [Fact]
-        public void DebuggerStatementDoesNotTriggerBreakWhenStepping()
-        {
-            string script = @"'dummy';
+    [Fact]
+    public void DebuggerStatementDoesNotTriggerBreakWhenStepping()
+    {
+        string script = @"'dummy';
 debugger;
 'dummy';";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script)
-                .InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script)
+            .InitialStepMode(StepMode.Into));
 
-            bool didBreak = false;
-            int stepCount = 0;
-            engine.Debugger.Break += (sender, info) =>
-            {
-                didBreak = true;
-                return StepMode.None;
-            };
+        bool didBreak = false;
+        int stepCount = 0;
+        engine.Debugger.Break += (sender, info) =>
+        {
+            didBreak = true;
+            return StepMode.None;
+        };
 
-            engine.Debugger.Step += (sender, info) =>
-            {
-                stepCount++;
-                return StepMode.Into;
-            };
+        engine.Debugger.Step += (sender, info) =>
+        {
+            stepCount++;
+            return StepMode.Into;
+        };
 
-            engine.Execute(script);
-            Assert.Equal(3, stepCount);
-            Assert.False(didBreak);
-        }
+        engine.Execute(script);
+        Assert.Equal(3, stepCount);
+        Assert.False(didBreak);
+    }
 
-        [Fact]
-        public void DebuggerStatementDoesNotTriggerBreakWhenAtBreakPoint()
-        {
-            string script = @"'dummy';
+    [Fact]
+    public void DebuggerStatementDoesNotTriggerBreakWhenAtBreakPoint()
+    {
+        string script = @"'dummy';
 debugger;
 'dummy';";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script)
-                .InitialStepMode(StepMode.None));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script)
+            .InitialStepMode(StepMode.None));
 
-            int breakCount = 0;
+        int breakCount = 0;
 
-            engine.Debugger.BreakPoints.Set(new BreakPoint(2, 0));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(2, 0));
 
-            engine.Debugger.Break += (sender, info) =>
-            {
-                Assert.Equal(PauseType.Break, info.PauseType);
-                breakCount++;
-                return StepMode.None;
-            };
+        engine.Debugger.Break += (sender, info) =>
+        {
+            Assert.Equal(PauseType.Break, info.PauseType);
+            breakCount++;
+            return StepMode.None;
+        };
 
-            engine.Execute(script);
-            Assert.Equal(1, breakCount);
-        }
+        engine.Execute(script);
+        Assert.Equal(1, breakCount);
+    }
 
-        [Fact]
-        public void BreakPointDoesNotTriggerBreakWhenStepping()
-        {
-            string script = @"
+    [Fact]
+    public void BreakPointDoesNotTriggerBreakWhenStepping()
+    {
+        string script = @"
 'first breakpoint';
 'dummy';
 'second breakpoint';";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .InitialStepMode(StepMode.Into));
 
-            bool didStep = true;
-            bool didBreak = true;
+        bool didStep = true;
+        bool didBreak = true;
 
-            engine.Debugger.BreakPoints.Set(new BreakPoint(2, 0));
-            engine.Debugger.BreakPoints.Set(new BreakPoint(4, 0));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(2, 0));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(4, 0));
 
-            engine.Debugger.Break += (sender, info) =>
+        engine.Debugger.Break += (sender, info) =>
+        {
+            didBreak = true;
+            // first breakpoint shouldn't cause us to get here, because we're stepping,
+            // but when we reach the second, we're running:
+            Assert.True(TestHelpers.ReachedLiteral(info, "second breakpoint"));
+            return StepMode.None;
+        };
+
+        engine.Debugger.Step += (sender, info) =>
+        {
+            didStep = true;
+            if (TestHelpers.ReachedLiteral(info, "first breakpoint"))
             {
-                didBreak = true;
-                // first breakpoint shouldn't cause us to get here, because we're stepping,
-                // but when we reach the second, we're running:
-                Assert.True(TestHelpers.ReachedLiteral(info, "second breakpoint"));
+                // Run from here
                 return StepMode.None;
-            };
+            }
+            return StepMode.Into;
+        };
 
-            engine.Debugger.Step += (sender, info) =>
-            {
-                didStep = true;
-                if (TestHelpers.ReachedLiteral(info, "first breakpoint"))
-                {
-                    // Run from here
-                    return StepMode.None;
-                }
-                return StepMode.Into;
-            };
-
-            engine.Execute(script);
-
-            Assert.True(didStep);
-            Assert.True(didBreak);
-        }
+        engine.Execute(script);
 
-        [Fact(Skip = "Non-source breakpoint is triggered before Statement, while debugger statement is now triggered by ExecuteInternal")]
-        public void DebuggerStatementAndBreakpointTriggerSingleBreak()
-        {
-            string script = @"'dummy';
+        Assert.True(didStep);
+        Assert.True(didBreak);
+    }
+
+    [Fact(Skip = "Non-source breakpoint is triggered before Statement, while debugger statement is now triggered by ExecuteInternal")]
+    public void DebuggerStatementAndBreakpointTriggerSingleBreak()
+    {
+        string script = @"'dummy';
 debugger;
 'dummy';";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script));
 
-            engine.Debugger.BreakPoints.Set(new BreakPoint(2, 0));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(2, 0));
 
-            int breakTriggered = 0;
-            engine.Debugger.Break += (sender, info) =>
-            {
-                breakTriggered++;
-                return StepMode.None;
-            };
+        int breakTriggered = 0;
+        engine.Debugger.Break += (sender, info) =>
+        {
+            breakTriggered++;
+            return StepMode.None;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            Assert.Equal(1, breakTriggered);
-        }
+        Assert.Equal(1, breakTriggered);
+    }
 
-        [Fact]
-        public void BreakpointOverridesStepOut()
-        {
-            string script = @"function test()
+    [Fact]
+    public void BreakpointOverridesStepOut()
+    {
+        string script = @"function test()
 {
 'dummy';
 'source';
@@ -341,35 +341,35 @@ debugger;
 }
 test();";
 
-            var engine = new Engine(options => options.DebugMode());
+        var engine = new Engine(options => options.DebugMode());
 
-            engine.Debugger.BreakPoints.Set(new BreakPoint(4, 0));
-            engine.Debugger.BreakPoints.Set(new BreakPoint(6, 0));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(4, 0));
+        engine.Debugger.BreakPoints.Set(new BreakPoint(6, 0));
 
-            int step = 0;
-            engine.Debugger.Break += (sender, info) =>
+        int step = 0;
+        engine.Debugger.Break += (sender, info) =>
+        {
+            step++;
+            switch (step)
             {
-                step++;
-                switch (step)
-                {
-                    case 1:
-                        return StepMode.Out;
-                    case 2:
-                        Assert.True(info.ReachedLiteral("target"));
-                        break;
-                }
-                return StepMode.None;
-            };
+                case 1:
+                    return StepMode.Out;
+                case 2:
+                    Assert.True(info.ReachedLiteral("target"));
+                    break;
+            }
+            return StepMode.None;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            Assert.Equal(2, step);
-        }
+        Assert.Equal(2, step);
+    }
 
-        [Fact]
-        public void ErrorInConditionalBreakpointLeavesCallStackAlone()
-        {
-            string script = @"
+    [Fact]
+    public void ErrorInConditionalBreakpointLeavesCallStackAlone()
+    {
+        string script = @"
 function foo()
 {
 let x = 0;
@@ -381,93 +381,92 @@ let x = 0;
 
 foo();
 ";
-            var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));
 
-            int stepsReached = 0;
-            int breakpointsReached = 0;
+        int stepsReached = 0;
+        int breakpointsReached = 0;
 
-            // This breakpoint will be hit:
-            engine.Debugger.BreakPoints.Set(new BreakPoint(6, 0, "x == 0"));
-            // This condition is an error (y is not defined). DebugHandler will
-            // treat it as an unmatched breakpoint:
-            engine.Debugger.BreakPoints.Set(new BreakPoint(7, 0, "y == 0"));
+        // This breakpoint will be hit:
+        engine.Debugger.BreakPoints.Set(new BreakPoint(6, 0, "x == 0"));
+        // This condition is an error (y is not defined). DebugHandler will
+        // treat it as an unmatched breakpoint:
+        engine.Debugger.BreakPoints.Set(new BreakPoint(7, 0, "y == 0"));
 
-            engine.Debugger.Step += (sender, info) =>
+        engine.Debugger.Step += (sender, info) =>
+        {
+            if (info.ReachedLiteral("before breakpoint"))
             {
-                if (info.ReachedLiteral("before breakpoint"))
-                {
-                    Assert.Equal(1, engine.CallStack.Count);
-                    stepsReached++;
-                    return StepMode.None;
-                }
-                else if (info.ReachedLiteral("after breakpoint"))
-                {
-                    Assert.Equal(1, engine.CallStack.Count);
-                    stepsReached++;
-                    return StepMode.None;
-                }
-                return StepMode.Into;
-            };
-
-            engine.Debugger.Break += (sender, info) =>
+                Assert.Equal(1, engine.CallStack.Count);
+                stepsReached++;
+                return StepMode.None;
+            }
+            else if (info.ReachedLiteral("after breakpoint"))
             {
-                breakpointsReached++;
-                return StepMode.Into;
-            };
+                Assert.Equal(1, engine.CallStack.Count);
+                stepsReached++;
+                return StepMode.None;
+            }
+            return StepMode.Into;
+        };
 
-            engine.Execute(script);
+        engine.Debugger.Break += (sender, info) =>
+        {
+            breakpointsReached++;
+            return StepMode.Into;
+        };
 
-            Assert.Equal(1, breakpointsReached);
-            Assert.Equal(2, stepsReached);
-        }
+        engine.Execute(script);
 
-        private class SimpleHitConditionBreakPoint : BreakPoint
-        {
-            public SimpleHitConditionBreakPoint(int line, int column, string condition = null,
-                int? hitCondition = null) : base(line, column, condition)
-            {
-                HitCondition = hitCondition;
-            }
+        Assert.Equal(1, breakpointsReached);
+        Assert.Equal(2, stepsReached);
+    }
 
-            public int HitCount { get; set; }
-            public int? HitCondition { get; set; }
+    private class SimpleHitConditionBreakPoint : BreakPoint
+    {
+        public SimpleHitConditionBreakPoint(int line, int column, string condition = null,
+            int? hitCondition = null) : base(line, column, condition)
+        {
+            HitCondition = hitCondition;
         }
 
-        [Fact]
-        public void BreakPointCanBeExtended()
-        {
-            // More of a documentation than a required test, this shows the usefulness of BreakPoint being
-            // extensible - as a test, at least it ensures that it is.
-            var script = @"
+        public int HitCount { get; set; }
+        public int? HitCondition { get; set; }
+    }
+
+    [Fact]
+    public void BreakPointCanBeExtended()
+    {
+        // More of a documentation than a required test, this shows the usefulness of BreakPoint being
+        // extensible - as a test, at least it ensures that it is.
+        var script = @"
 for (let i = 0; i < 10; i++)
 {
     'breakpoint';
 }
 ";
-            var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.None));
+        var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.None));
 
-            engine.Debugger.BreakPoints.Set(
-                new SimpleHitConditionBreakPoint(4, 4, condition: null, hitCondition: 5));
+        engine.Debugger.BreakPoints.Set(
+            new SimpleHitConditionBreakPoint(4, 4, condition: null, hitCondition: 5));
 
-            int numberOfBreaks = 0;
-            engine.Debugger.Break += (sender, info) =>
+        int numberOfBreaks = 0;
+        engine.Debugger.Break += (sender, info) =>
+        {
+            Assert.True(info.ReachedLiteral("breakpoint"));
+            var extendedBreakPoint = Assert.IsType<SimpleHitConditionBreakPoint>(info.BreakPoint);
+            extendedBreakPoint.HitCount++;
+            if (extendedBreakPoint.HitCount == extendedBreakPoint.HitCondition)
             {
-                Assert.True(info.ReachedLiteral("breakpoint"));
-                var extendedBreakPoint = Assert.IsType<SimpleHitConditionBreakPoint>(info.BreakPoint);
-                extendedBreakPoint.HitCount++;
-                if (extendedBreakPoint.HitCount == extendedBreakPoint.HitCondition)
-                {
-                    // Here is where we would normally pause the execution.
-                    // the breakpoint is hit for the fifth time, when i is 4 (off by one)
-                    Assert.Equal(4, info.CurrentScopeChain[0].GetBindingValue("i").AsInteger());
-                    numberOfBreaks++;
-                }
-                return StepMode.None;
-            };
+                // Here is where we would normally pause the execution.
+                // the breakpoint is hit for the fifth time, when i is 4 (off by one)
+                Assert.Equal(4, info.CurrentScopeChain[0].GetBindingValue("i").AsInteger());
+                numberOfBreaks++;
+            }
+            return StepMode.None;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            Assert.Equal(1, numberOfBreaks);
-        }
+        Assert.Equal(1, numberOfBreaks);
     }
-}
+}

+ 170 - 171
Jint.Tests/Runtime/Debugger/CallStackTests.cs

@@ -1,13 +1,13 @@
 using Jint.Runtime.Debugger;
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public class CallStackTests
 {
-    public class CallStackTests
+    [Fact]
+    public void IncludesFunctionNames()
     {
-        [Fact]
-        public void IncludesFunctionNames()
-        {
-            var script = @"
+        var script = @"
             function foo()
             {
                 debugger;
@@ -20,20 +20,20 @@ namespace Jint.Tests.Runtime.Debugger
 
             bar()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CallStack,
-                    frame => Assert.Equal("foo", frame.FunctionName),
-                    frame => Assert.Equal("bar", frame.FunctionName),
-                    frame => Assert.Equal("(anonymous)", frame.FunctionName)
-                );
-            });
-        }
-
-        [Fact]
-        public void IncludesLocations()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            var script = @"
+            Assert.Collection(info.CallStack,
+                frame => Assert.Equal("foo", frame.FunctionName),
+                frame => Assert.Equal("bar", frame.FunctionName),
+                frame => Assert.Equal("(anonymous)", frame.FunctionName)
+            );
+        });
+    }
+
+    [Fact]
+    public void IncludesLocations()
+    {
+        var script = @"
 function foo()
 {
 debugger;
@@ -46,26 +46,26 @@ foo();
 
 bar()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                // The line numbers here may mislead - the positions are, as would be expected,
-                // at the position before the currently executing line, not the line after.
-                // Remember that Esprima (and hence Jint) line numbers are 1-based, not 0-based.
-                Assert.Collection(info.CallStack,
-                    // "debugger;"
-                    frame => Assert.Equal(Position.From(4, 0), frame.Location.Start),
-                    // "foo();"
-                    frame => Assert.Equal(Position.From(9, 0), frame.Location.Start),
-                    // "bar();"
-                    frame => Assert.Equal(Position.From(12, 0), frame.Location.Start)
-                );
-            });
-        }
-
-        [Fact]
-        public void IncludesFunctionLocations()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            var script = @"
+            // The line numbers here may mislead - the positions are, as would be expected,
+            // at the position before the currently executing line, not the line after.
+            // Remember that Esprima (and hence Jint) line numbers are 1-based, not 0-based.
+            Assert.Collection(info.CallStack,
+                // "debugger;"
+                frame => Assert.Equal(Position.From(4, 0), frame.Location.Start),
+                // "foo();"
+                frame => Assert.Equal(Position.From(9, 0), frame.Location.Start),
+                // "bar();"
+                frame => Assert.Equal(Position.From(12, 0), frame.Location.Start)
+            );
+        });
+    }
+
+    [Fact]
+    public void IncludesFunctionLocations()
+    {
+        var script = @"
 function foo()
 {
 debugger;
@@ -78,24 +78,24 @@ foo();
 
 bar()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                // Remember that Esprima (and hence Jint) line numbers are 1-based, not 0-based.
-                Assert.Collection(info.CallStack,
-                    // function foo()
-                    frame => Assert.Equal(Position.From(2, 0), frame.FunctionLocation?.Start),
-                    // function bar()
-                    frame => Assert.Equal(Position.From(7, 0), frame.FunctionLocation?.Start),
-                    // global - no function location
-                    frame => Assert.Equal(null, frame.FunctionLocation?.Start)
-                );
-            });
-        }
-
-        [Fact]
-        public void HasReturnValue()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            // Remember that Esprima (and hence Jint) line numbers are 1-based, not 0-based.
+            Assert.Collection(info.CallStack,
+                // function foo()
+                frame => Assert.Equal(Position.From(2, 0), frame.FunctionLocation?.Start),
+                // function bar()
+                frame => Assert.Equal(Position.From(7, 0), frame.FunctionLocation?.Start),
+                // global - no function location
+                frame => Assert.Equal(null, frame.FunctionLocation?.Start)
+            );
+        });
+    }
+
+    [Fact]
+    public void HasReturnValue()
+    {
+        string script = @"
             function foo()
             {
                 return 'result';
@@ -103,38 +103,38 @@ bar()";
 
             foo();";
 
-            var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));
 
-            bool atReturn = false;
-            bool didCheckReturn = false;
+        bool atReturn = false;
+        bool didCheckReturn = false;
 
-            engine.Debugger.Step += (sender, info) =>
+        engine.Debugger.Step += (sender, info) =>
+        {
+            if (atReturn)
             {
-                if (atReturn)
-                {
-                    Assert.NotNull(info.CurrentCallFrame.ReturnValue);
-                    Assert.Equal("result", info.CurrentCallFrame.ReturnValue.AsString());
-                    didCheckReturn = true;
-                    atReturn = false;
-                }
+                Assert.NotNull(info.CurrentCallFrame.ReturnValue);
+                Assert.Equal("result", info.CurrentCallFrame.ReturnValue.AsString());
+                didCheckReturn = true;
+                atReturn = false;
+            }
 
-                if (info.CurrentNode is ReturnStatement)
-                {
-                    // Step one further, and we should have the return value
-                    atReturn = true;
-                }
-                return StepMode.Into;
-            };
+            if (info.CurrentNode is ReturnStatement)
+            {
+                // Step one further, and we should have the return value
+                atReturn = true;
+            }
+            return StepMode.Into;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            Assert.True(didCheckReturn);
-        }
+        Assert.True(didCheckReturn);
+    }
 
-        [Fact]
-        public void HasThis()
-        {
-            string script = @"
+    [Fact]
+    public void HasThis()
+    {
+        string script = @"
 function Thing(name)
 {
     this.name = name;
@@ -149,113 +149,113 @@ var car = new Thing('car');
 car.test();
 ";
 
-            TestHelpers.TestAtBreak(script, (engine, info) =>
-            {
-                Assert.Collection(info.CallStack,
-                    frame => Assert.Equal(engine.Realm.GlobalObject.Get("car"), frame.This),
-                    frame => Assert.Equal(engine.Realm.GlobalObject, frame.This)
-                );
-            });
-        }
-
-        [Fact]
-        public void NamesRegularFunction()
+        TestHelpers.TestAtBreak(script, (engine, info) =>
         {
-            string script = @"
+            Assert.Collection(info.CallStack,
+                frame => Assert.Equal(engine.Realm.GlobalObject.Get("car"), frame.This),
+                frame => Assert.Equal(engine.Realm.GlobalObject, frame.This)
+            );
+        });
+    }
+
+    [Fact]
+    public void NamesRegularFunction()
+    {
+        string script = @"
             function regularFunction() { debugger; }
             regularFunction();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("regularFunction", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesFunctionExpression()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal("regularFunction", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesFunctionExpression()
+    {
+        string script = @"
             const functionExpression = function() { debugger; }
             functionExpression()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("functionExpression", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesNamedFunctionExpression()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal("functionExpression", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesNamedFunctionExpression()
+    {
+        string script = @"
             const functionExpression = function namedFunction() { debugger; }
             functionExpression()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("namedFunction", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesArrowFunction()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal("namedFunction", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesArrowFunction()
+    {
+        string script = @"
             const arrowFunction = () => { debugger; }
             arrowFunction()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("arrowFunction", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesNewFunction()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal("arrowFunction", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesNewFunction()
+    {
+        string script = @"
             const newFunction = new Function('debugger;');
             newFunction()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                // Ideally, this should be "(anonymous)", but FunctionConstructor sets the "anonymous" name.
-                Assert.Equal("anonymous", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesMemberFunction()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            // Ideally, this should be "(anonymous)", but FunctionConstructor sets the "anonymous" name.
+            Assert.Equal("anonymous", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesMemberFunction()
+    {
+        string script = @"
             const obj = { memberFunction() { debugger; } };
             obj.memberFunction()";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("memberFunction", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesAnonymousFunction()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal("memberFunction", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesAnonymousFunction()
+    {
+        string script = @"
             (function()
             {
                 debugger;
             }());";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("(anonymous)", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesGetAccessor()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal("(anonymous)", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesGetAccessor()
+    {
+        string script = @"
             const obj = {
                 get accessor()
                 {
@@ -265,16 +265,16 @@ car.test();
             };
             const x = obj.accessor;";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("get accessor", info.CurrentCallFrame.FunctionName);
-            });
-        }
-
-        [Fact]
-        public void NamesSetAccessor()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal("get accessor", info.CurrentCallFrame.FunctionName);
+        });
+    }
+
+    [Fact]
+    public void NamesSetAccessor()
+    {
+        string script = @"
             const obj = {
                 set accessor(value)
                 {
@@ -284,10 +284,9 @@ car.test();
             };
             obj.accessor = 42;";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal("set accessor", info.CurrentCallFrame.FunctionName);
-            });
-        }
+        TestHelpers.TestAtBreak(script, info =>
+        {
+            Assert.Equal("set accessor", info.CurrentCallFrame.FunctionName);
+        });
     }
-}
+}

+ 32 - 33
Jint.Tests/Runtime/Debugger/DebugHandlerTests.cs

@@ -3,46 +3,45 @@ using Jint.Runtime.Debugger;
 
 #pragma warning disable 618
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public class DebugHandlerTests
 {
-    public class DebugHandlerTests
+    [Fact]
+    public void AvoidsPauseRecursion()
     {
-        [Fact]
-        public void AvoidsPauseRecursion()
-        {
-            // While the DebugHandler is in a paused state, it shouldn't relay further OnStep calls to Break/Step.
-            // Such calls would occur e.g. if Step/Break event handlers evaluate accessors. Failing to avoid
-            // reentrance in a multithreaded environment (e.g. using ManualResetEvent(Slim)) would cause
-            // a deadlock.
-            string script = @"
+        // While the DebugHandler is in a paused state, it shouldn't relay further OnStep calls to Break/Step.
+        // Such calls would occur e.g. if Step/Break event handlers evaluate accessors. Failing to avoid
+        // reentrance in a multithreaded environment (e.g. using ManualResetEvent(Slim)) would cause
+        // a deadlock.
+        string script = @"
                 var obj = { get name() { 'fail'; return 'Smith'; } };
                 'target';
             ";
 
-            var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));
 
-            bool didPropertyAccess = false;
+        bool didPropertyAccess = false;
+
+        engine.Debugger.Step += (sender, info) =>
+        {
+            // We should never reach "fail", because the only way it's executed is from
+            // within this Step handler
+            Assert.False(info.ReachedLiteral("fail"));
 
-            engine.Debugger.Step += (sender, info) =>
+            if (info.ReachedLiteral("target"))
             {
-                // We should never reach "fail", because the only way it's executed is from
-                // within this Step handler
-                Assert.False(info.ReachedLiteral("fail"));
-
-                if (info.ReachedLiteral("target"))
-                {
-                    var obj = info.CurrentScopeChain[0].GetBindingValue("obj") as ObjectInstance;
-                    var prop = obj.GetOwnProperty("name");
-                    // This is where reentrance would occur:
-                    var value = engine.Invoke(prop.Get);
-                    didPropertyAccess = true;
-                }
-                return StepMode.Into;
-            };
-
-            engine.Execute(script);
-
-            Assert.True(didPropertyAccess);
-        }
+                var obj = info.CurrentScopeChain[0].GetBindingValue("obj") as ObjectInstance;
+                var prop = obj.GetOwnProperty("name");
+                // This is where reentrance would occur:
+                var value = engine.Invoke(prop.Get);
+                didPropertyAccess = true;
+            }
+            return StepMode.Into;
+        };
+
+        engine.Execute(script);
+
+        Assert.True(didPropertyAccess);
     }
-}
+}

+ 62 - 63
Jint.Tests/Runtime/Debugger/EvaluateTests.cs

@@ -2,14 +2,14 @@
 using Jint.Runtime;
 using Jint.Runtime.Debugger;
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public class EvaluateTests
 {
-    public class EvaluateTests
+    [Fact]
+    public void EvalutesInCurrentContext()
     {
-        [Fact]
-        public void EvalutesInCurrentContext()
-        {
-            var script = @"
+        var script = @"
             function test(x)
             {
                 x *= 10;
@@ -19,26 +19,26 @@ namespace Jint.Tests.Runtime.Debugger
             test(5);
             ";
 
-            TestHelpers.TestAtBreak(script, (engine, info) =>
-            {
-                var evaluated = engine.Debugger.Evaluate("x");
-                Assert.IsType<JsNumber>(evaluated);
-                Assert.Equal(50, evaluated.AsNumber());
-            });
-        }
-
-        [Fact]
-        public void ThrowsIfNoCurrentContext()
+        TestHelpers.TestAtBreak(script, (engine, info) =>
         {
-            var engine = new Engine(options => options.DebugMode());
-            var exception = Assert.Throws<DebugEvaluationException>(() => engine.Debugger.Evaluate("let x = 1;"));
-            Assert.Null(exception.InnerException); // Not a JavaScript or parser exception
-        }
+            var evaluated = engine.Debugger.Evaluate("x");
+            Assert.IsType<JsNumber>(evaluated);
+            Assert.Equal(50, evaluated.AsNumber());
+        });
+    }
 
-        [Fact]
-        public void ThrowsOnRuntimeError()
-        {
-            var script = @"
+    [Fact]
+    public void ThrowsIfNoCurrentContext()
+    {
+        var engine = new Engine(options => options.DebugMode());
+        var exception = Assert.Throws<DebugEvaluationException>(() => engine.Debugger.Evaluate("let x = 1;"));
+        Assert.Null(exception.InnerException); // Not a JavaScript or parser exception
+    }
+
+    [Fact]
+    public void ThrowsOnRuntimeError()
+    {
+        var script = @"
             function test(x)
             {
                 x *= 10;
@@ -48,17 +48,17 @@ namespace Jint.Tests.Runtime.Debugger
             test(5);
             ";
 
-            TestHelpers.TestAtBreak(script, (engine, info) =>
-            {
-                var exception = Assert.Throws<DebugEvaluationException>(() => engine.Debugger.Evaluate("y"));
-                Assert.IsType<JavaScriptException>(exception.InnerException);
-            });
-        }
-
-        [Fact]
-        public void ThrowsOnExecutionError()
+        TestHelpers.TestAtBreak(script, (engine, info) =>
         {
-            var script = @"
+            var exception = Assert.Throws<DebugEvaluationException>(() => engine.Debugger.Evaluate("y"));
+            Assert.IsType<JavaScriptException>(exception.InnerException);
+        });
+    }
+
+    [Fact]
+    public void ThrowsOnExecutionError()
+    {
+        var script = @"
             function test(x)
             {
                 x *= 10;
@@ -68,18 +68,18 @@ namespace Jint.Tests.Runtime.Debugger
             test(5);
             ";
 
-            TestHelpers.TestAtBreak(script, (engine, info) =>
-            {
-                var exception = Assert.Throws<DebugEvaluationException>(() =>
-                    engine.Debugger.Evaluate("this is a syntax error"));
-                Assert.IsType<SyntaxErrorException>(exception.InnerException);
-            });
-        }
-
-        [Fact]
-        public void RestoresStackAfterEvaluation()
+        TestHelpers.TestAtBreak(script, (engine, info) =>
         {
-            var script = @"
+            var exception = Assert.Throws<DebugEvaluationException>(() =>
+                engine.Debugger.Evaluate("this is a syntax error"));
+            Assert.IsType<SyntaxErrorException>(exception.InnerException);
+        });
+    }
+
+    [Fact]
+    public void RestoresStackAfterEvaluation()
+    {
+        var script = @"
             function throws()
             {
                 throw new Error('Take this!');
@@ -94,22 +94,21 @@ namespace Jint.Tests.Runtime.Debugger
             test(5);
             ";
 
-            TestHelpers.TestAtBreak(script, (engine, info) =>
-            {
-                Assert.Equal(1, engine.CallStack.Count);
-                var frameBefore = engine.CallStack.Stack[0];
-
-                Assert.Throws<DebugEvaluationException>(() => engine.Debugger.Evaluate("throws()"));
-                Assert.Equal(1, engine.CallStack.Count);
-                var frameAfter = engine.CallStack.Stack[0];
-                // Stack frames and some of their properties are structs - can't check reference equality
-                // Besides, even if we could, it would be no guarantee. Neither is the following, but it'll do for now.
-                Assert.Equal(frameBefore.CallingExecutionContext.LexicalEnvironment, frameAfter.CallingExecutionContext.LexicalEnvironment);
-                Assert.Equal(frameBefore.Arguments, frameAfter.Arguments);
-                Assert.Equal(frameBefore.Expression, frameAfter.Expression);
-                Assert.Equal(frameBefore.Location, frameAfter.Location);
-                Assert.Equal(frameBefore.Function, frameAfter.Function);
-            });
-        }
+        TestHelpers.TestAtBreak(script, (engine, info) =>
+        {
+            Assert.Equal(1, engine.CallStack.Count);
+            var frameBefore = engine.CallStack.Stack[0];
+
+            Assert.Throws<DebugEvaluationException>(() => engine.Debugger.Evaluate("throws()"));
+            Assert.Equal(1, engine.CallStack.Count);
+            var frameAfter = engine.CallStack.Stack[0];
+            // Stack frames and some of their properties are structs - can't check reference equality
+            // Besides, even if we could, it would be no guarantee. Neither is the following, but it'll do for now.
+            Assert.Equal(frameBefore.CallingExecutionContext.LexicalEnvironment, frameAfter.CallingExecutionContext.LexicalEnvironment);
+            Assert.Equal(frameBefore.Arguments, frameAfter.Arguments);
+            Assert.Equal(frameBefore.Expression, frameAfter.Expression);
+            Assert.Equal(frameBefore.Location, frameAfter.Location);
+            Assert.Equal(frameBefore.Function, frameAfter.Function);
+        });
     }
-}
+}

+ 293 - 294
Jint.Tests/Runtime/Debugger/ScopeTests.cs

@@ -1,53 +1,53 @@
 using Jint.Native;
 using Jint.Runtime.Debugger;
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public class ScopeTests
 {
-    public class ScopeTests
+    private static JsValue AssertOnlyScopeContains(DebugScopes scopes, string name, DebugScopeType scopeType)
     {
-        private static JsValue AssertOnlyScopeContains(DebugScopes scopes, string name, DebugScopeType scopeType)
-        {
-            var containingScope = Assert.Single(scopes, s => s.ScopeType == scopeType && s.BindingNames.Contains(name));
-            Assert.DoesNotContain(scopes, s => s != containingScope && s.BindingNames.Contains(name));
+        var containingScope = Assert.Single(scopes, s => s.ScopeType == scopeType && s.BindingNames.Contains(name));
+        Assert.DoesNotContain(scopes, s => s != containingScope && s.BindingNames.Contains(name));
 
-            return containingScope.GetBindingValue(name);
-        }
+        return containingScope.GetBindingValue(name);
+    }
 
-        private static void AssertScope(DebugScope actual, DebugScopeType expectedType, params string[] expectedBindingNames)
+    private static void AssertScope(DebugScope actual, DebugScopeType expectedType, params string[] expectedBindingNames)
+    {
+        Assert.Equal(expectedType, actual.ScopeType);
+        // Global scope will have a number of intrinsic bindings that are outside the scope [no pun] of these tests
+        if (actual.ScopeType != DebugScopeType.Global)
         {
-            Assert.Equal(expectedType, actual.ScopeType);
-            // Global scope will have a number of intrinsic bindings that are outside the scope [no pun] of these tests
-            if (actual.ScopeType != DebugScopeType.Global)
-            {
-                Assert.Equal(expectedBindingNames.Length, actual.BindingNames.Count);
-            }
-            foreach (string expectedName in expectedBindingNames)
-            {
-                Assert.Contains(expectedName, actual.BindingNames);
-            }
+            Assert.Equal(expectedBindingNames.Length, actual.BindingNames.Count);
         }
-
-        [Fact]
-        public void AllowsInspectionOfUninitializedGlobalBindings()
+        foreach (string expectedName in expectedBindingNames)
         {
-            string script = @"
+            Assert.Contains(expectedName, actual.BindingNames);
+        }
+    }
+
+    [Fact]
+    public void AllowsInspectionOfUninitializedGlobalBindings()
+    {
+        string script = @"
                 debugger;
                 const globalConstant = 'test';
                 let globalLet = 'test';
             ";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                // Uninitialized global block scoped ("script scoped") bindings return null (and, just as importantly, don't throw):
-                Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalConstant"));
-                Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalLet"));
-            });
-        }
-
-        [Fact]
-        public void AllowsInspectionOfUninitializedBlockBindings()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            // Uninitialized global block scoped ("script scoped") bindings return null (and, just as importantly, don't throw):
+            Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalConstant"));
+            Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalLet"));
+        });
+    }
+
+    [Fact]
+    public void AllowsInspectionOfUninitializedBlockBindings()
+    {
+        string script = @"
                 function test()
                 {
                     debugger;
@@ -57,61 +57,61 @@ namespace Jint.Tests.Runtime.Debugger
                 test();
             ";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                // Uninitialized block scoped bindings return null (and, just as importantly, don't throw):
-                Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalConstant"));
-                Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalLet"));
-            });
-        }
-
-        [Fact]
-        public void ScriptScopeIncludesGlobalConst()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            // Uninitialized block scoped bindings return null (and, just as importantly, don't throw):
+            Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalConstant"));
+            Assert.Null(info.CurrentScopeChain[0].GetBindingValue("globalLet"));
+        });
+    }
+
+    [Fact]
+    public void ScriptScopeIncludesGlobalConst()
+    {
+        string script = @"
                 const globalConstant = 'test';
                 debugger;
             ";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                var value = AssertOnlyScopeContains(info.CurrentScopeChain, "globalConstant", DebugScopeType.Script);
-                Assert.Equal("test", value.AsString());
-            });
-        }
-
-        [Fact]
-        public void ScriptScopeIncludesGlobalLet()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            var value = AssertOnlyScopeContains(info.CurrentScopeChain, "globalConstant", DebugScopeType.Script);
+            Assert.Equal("test", value.AsString());
+        });
+    }
+
+    [Fact]
+    public void ScriptScopeIncludesGlobalLet()
+    {
+        string script = @"
                 let globalLet = 'test';
                 debugger;";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                var value = AssertOnlyScopeContains(info.CurrentScopeChain, "globalLet", DebugScopeType.Script);
-                Assert.Equal("test", value.AsString());
-            });
-        }
-
-        [Fact]
-        public void GlobalScopeIncludesGlobalVar()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            var value = AssertOnlyScopeContains(info.CurrentScopeChain, "globalLet", DebugScopeType.Script);
+            Assert.Equal("test", value.AsString());
+        });
+    }
+
+    [Fact]
+    public void GlobalScopeIncludesGlobalVar()
+    {
+        string script = @"
                 var globalVar = 'test';
                 debugger;";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                var value = AssertOnlyScopeContains(info.CurrentScopeChain, "globalVar", DebugScopeType.Global);
-                Assert.Equal("test", value.AsString());
-            });
-        }
-
-        [Fact]
-        public void TopLevelBlockScopeIsIdentified()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            var value = AssertOnlyScopeContains(info.CurrentScopeChain, "globalVar", DebugScopeType.Global);
+            Assert.Equal("test", value.AsString());
+        });
+    }
+
+    [Fact]
+    public void TopLevelBlockScopeIsIdentified()
+    {
+        string script = @"
                 function test()
                 {
                     const localConst = 'test';
@@ -119,18 +119,18 @@ namespace Jint.Tests.Runtime.Debugger
                 }
                 test();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Equal(3, info.CurrentScopeChain.Count);
-                Assert.Equal(DebugScopeType.Block, info.CurrentScopeChain[0].ScopeType);
-                Assert.True(info.CurrentScopeChain[0].IsTopLevel);
-            });
-        }
-
-        [Fact]
-        public void NonTopLevelBlockScopeIsIdentified()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Equal(3, info.CurrentScopeChain.Count);
+            Assert.Equal(DebugScopeType.Block, info.CurrentScopeChain[0].ScopeType);
+            Assert.True(info.CurrentScopeChain[0].IsTopLevel);
+        });
+    }
+
+    [Fact]
+    public void NonTopLevelBlockScopeIsIdentified()
+    {
+        string script = @"
                 function test()
                 {
                     {
@@ -140,19 +140,19 @@ namespace Jint.Tests.Runtime.Debugger
                 }
                 test();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                // We only have 3 scopes, because the function top level block scope is empty.
-                Assert.Equal(3, info.CurrentScopeChain.Count);
-                Assert.Equal(DebugScopeType.Block, info.CurrentScopeChain[0].ScopeType);
-                Assert.False(info.CurrentScopeChain[0].IsTopLevel);
-            });
-        }
-
-        [Fact]
-        public void BlockScopeIncludesLocalConst()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            // We only have 3 scopes, because the function top level block scope is empty.
+            Assert.Equal(3, info.CurrentScopeChain.Count);
+            Assert.Equal(DebugScopeType.Block, info.CurrentScopeChain[0].ScopeType);
+            Assert.False(info.CurrentScopeChain[0].IsTopLevel);
+        });
+    }
+
+    [Fact]
+    public void BlockScopeIncludesLocalConst()
+    {
+        string script = @"
                 function test()
                 {
                     {
@@ -162,16 +162,16 @@ namespace Jint.Tests.Runtime.Debugger
                 }
                 test();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                var value = AssertOnlyScopeContains(info.CurrentScopeChain, "localConst", DebugScopeType.Block);
-                Assert.Equal("test", value.AsString());
-            });
-        }
-        [Fact]
-        public void BlockScopeIncludesLocalLet()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            var value = AssertOnlyScopeContains(info.CurrentScopeChain, "localConst", DebugScopeType.Block);
+            Assert.Equal("test", value.AsString());
+        });
+    }
+    [Fact]
+    public void BlockScopeIncludesLocalLet()
+    {
+        string script = @"
                 function test()
                 {
                     {
@@ -181,17 +181,17 @@ namespace Jint.Tests.Runtime.Debugger
                 }
                 test();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                var value = AssertOnlyScopeContains(info.CurrentScopeChain, "localLet", DebugScopeType.Block);
-                Assert.Equal("test", value.AsString());
-            });
-        }
-
-        [Fact]
-        public void LocalScopeIncludesLocalVar()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            var value = AssertOnlyScopeContains(info.CurrentScopeChain, "localLet", DebugScopeType.Block);
+            Assert.Equal("test", value.AsString());
+        });
+    }
+
+    [Fact]
+    public void LocalScopeIncludesLocalVar()
+    {
+        string script = @"
                 function test()
                 {
                     var localVar = 'test';
@@ -199,16 +199,16 @@ namespace Jint.Tests.Runtime.Debugger
                 }
                 test();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                AssertOnlyScopeContains(info.CurrentScopeChain, "localVar", DebugScopeType.Local);
-            });
-        }
-
-        [Fact]
-        public void LocalScopeIncludesBlockVar()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            AssertOnlyScopeContains(info.CurrentScopeChain, "localVar", DebugScopeType.Local);
+        });
+    }
+
+    [Fact]
+    public void LocalScopeIncludesBlockVar()
+    {
+        string script = @"
                 function test()
                 {
                     debugger;
@@ -218,48 +218,48 @@ namespace Jint.Tests.Runtime.Debugger
                 }
                 test();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                AssertOnlyScopeContains(info.CurrentScopeChain, "localVar", DebugScopeType.Local);
-            });
-        }
-
-        [Fact]
-        public void BlockScopedConstIsVisibleInsideBlock()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            AssertOnlyScopeContains(info.CurrentScopeChain, "localVar", DebugScopeType.Local);
+        });
+    }
+
+    [Fact]
+    public void BlockScopedConstIsVisibleInsideBlock()
+    {
+        string script = @"
             'dummy statement';
             {
                 const blockConst = 'block';
                 debugger; // const isn't initialized until declaration
             }";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                AssertOnlyScopeContains(info.CurrentScopeChain, "blockConst", DebugScopeType.Block);
-            });
-        }
-
-        [Fact]
-        public void BlockScopedLetIsVisibleInsideBlock()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            AssertOnlyScopeContains(info.CurrentScopeChain, "blockConst", DebugScopeType.Block);
+        });
+    }
+
+    [Fact]
+    public void BlockScopedLetIsVisibleInsideBlock()
+    {
+        string script = @"
             'dummy statement';
             {
                 let blockLet = 'block';
                 debugger; // let isn't initialized until declaration
             }";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                AssertOnlyScopeContains(info.CurrentScopeChain, "blockLet", DebugScopeType.Block);
-            });
-        }
-
-        [Fact]
-        public void HasCorrectScopeChainForFunction()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            AssertOnlyScopeContains(info.CurrentScopeChain, "blockLet", DebugScopeType.Block);
+        });
+    }
+
+    [Fact]
+    public void HasCorrectScopeChainForFunction()
+    {
+        string script = @"
             function add(a, b)
             {
                 debugger;
@@ -269,19 +269,19 @@ namespace Jint.Tests.Runtime.Debugger
             const y = 2;
             const z = add(x, y);";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "b"),
-                    scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"),
-                    scope => AssertScope(scope, DebugScopeType.Global, "add"));
-            });
-        }
-
-        [Fact]
-        public void HasCorrectScopeChainForNestedFunction()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "b"),
+                scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"),
+                scope => AssertScope(scope, DebugScopeType.Global, "add"));
+        });
+    }
+
+    [Fact]
+    public void HasCorrectScopeChainForNestedFunction()
+    {
+        string script = @"
             function add(a, b)
             {
                 function power(a)
@@ -295,21 +295,21 @@ namespace Jint.Tests.Runtime.Debugger
             const y = 2;
             const z = add(x, y);";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a"),
-                    // a, arguments shadowed by local - but still exist in this scope
-                    scope => AssertScope(scope, DebugScopeType.Closure, "a", "arguments", "b", "power"),
-                    scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"),
-                    scope => AssertScope(scope, DebugScopeType.Global, "add"));
-            });
-        }
-
-        [Fact]
-        public void HasCorrectScopeChainForBlock()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a"),
+                // a, arguments shadowed by local - but still exist in this scope
+                scope => AssertScope(scope, DebugScopeType.Closure, "a", "arguments", "b", "power"),
+                scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"),
+                scope => AssertScope(scope, DebugScopeType.Global, "add"));
+        });
+    }
+
+    [Fact]
+    public void HasCorrectScopeChainForBlock()
+    {
+        string script = @"
             function add(a, b)
             {
                 if (a > 0)
@@ -323,20 +323,20 @@ namespace Jint.Tests.Runtime.Debugger
             const y = 2;
             const z = add(x, y);";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Block, "y"),
-                    scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "b"),
-                    scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"), // y is shadowed, but still in the scope
-                    scope => AssertScope(scope, DebugScopeType.Global, "add"));
-            });
-        }
-
-        [Fact]
-        public void HasCorrectScopeChainForModule()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string imported = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Block, "y"),
+                scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "b"),
+                scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"), // y is shadowed, but still in the scope
+                scope => AssertScope(scope, DebugScopeType.Global, "add"));
+        });
+    }
+
+    [Fact]
+    public void HasCorrectScopeChainForModule()
+    {
+        string imported = @"
             function add(a, b)
             {
                 debugger;
@@ -345,12 +345,12 @@ namespace Jint.Tests.Runtime.Debugger
             
             export { add };";
 
-            string main = @"
+        string main = @"
             import { add } from 'imported-module';
             const x = 1;
             const y = 2;
             add(x, y);";
-            TestHelpers.TestAtBreak(engine =>
+        TestHelpers.TestAtBreak(engine =>
             {
                 engine.Modules.Add("imported-module", imported);
                 engine.Modules.Add("main", main);
@@ -363,12 +363,12 @@ namespace Jint.Tests.Runtime.Debugger
                     scope => AssertScope(scope, DebugScopeType.Module, "add"),
                     scope => AssertScope(scope, DebugScopeType.Global));
             });
-        }
+    }
 
-        [Fact]
-        public void HasCorrectScopeChainForNestedBlock()
-        {
-            string script = @"
+    [Fact]
+    public void HasCorrectScopeChainForNestedBlock()
+    {
+        string script = @"
             function add(a, b)
             {
                 if (a > 0)
@@ -386,21 +386,21 @@ namespace Jint.Tests.Runtime.Debugger
             const y = 2;
             const z = add(x, y);";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Block, "x"),
-                    scope => AssertScope(scope, DebugScopeType.Block, "y"),
-                    scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "b"),
-                    scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"), // x, y are shadowed, but still in the scope
-                    scope => AssertScope(scope, DebugScopeType.Global, "add"));
-            });
-        }
-
-        [Fact]
-        public void HasCorrectScopeChainForCatch()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Block, "x"),
+                scope => AssertScope(scope, DebugScopeType.Block, "y"),
+                scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "b"),
+                scope => AssertScope(scope, DebugScopeType.Script, "x", "y", "z"), // x, y are shadowed, but still in the scope
+                scope => AssertScope(scope, DebugScopeType.Global, "add"));
+        });
+    }
+
+    [Fact]
+    public void HasCorrectScopeChainForCatch()
+    {
+        string script = @"
             function func()
             {
                 let a = 1;
@@ -415,20 +415,20 @@ namespace Jint.Tests.Runtime.Debugger
             }
             func();";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Catch, "error"),
-                    scope => AssertScope(scope, DebugScopeType.Block, "a"),
-                    scope => AssertScope(scope, DebugScopeType.Local, "arguments"),
-                    scope => AssertScope(scope, DebugScopeType.Global, "func"));
-            });
-        }
-
-        [Fact]
-        public void HasCorrectScopeChainForWith()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Catch, "error"),
+                scope => AssertScope(scope, DebugScopeType.Block, "a"),
+                scope => AssertScope(scope, DebugScopeType.Local, "arguments"),
+                scope => AssertScope(scope, DebugScopeType.Global, "func"));
+        });
+    }
+
+    [Fact]
+    public void HasCorrectScopeChainForWith()
+    {
+        string script = @"
             const obj = { a: 2, b: 4 };
             with (obj)
             {
@@ -436,20 +436,20 @@ namespace Jint.Tests.Runtime.Debugger
                 debugger;
             };";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Block, "x"),
-                    scope => AssertScope(scope, DebugScopeType.With, "a", "b"),
-                    scope => AssertScope(scope, DebugScopeType.Script, "obj"),
-                    scope => AssertScope(scope, DebugScopeType.Global));
-            });
-        }
-
-        [Fact]
-        public void ScopeChainIncludesNonEmptyScopes()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Block, "x"),
+                scope => AssertScope(scope, DebugScopeType.With, "a", "b"),
+                scope => AssertScope(scope, DebugScopeType.Script, "obj"),
+                scope => AssertScope(scope, DebugScopeType.Global));
+        });
+    }
+
+    [Fact]
+    public void ScopeChainIncludesNonEmptyScopes()
+    {
+        string script = @"
             const x = 2;
             if (x > 0)
             {
@@ -461,20 +461,20 @@ namespace Jint.Tests.Runtime.Debugger
                 }
             }";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Block, "z"),
-                    scope => AssertScope(scope, DebugScopeType.Block, "y"),
-                    scope => AssertScope(scope, DebugScopeType.Script, "x"),
-                    scope => AssertScope(scope, DebugScopeType.Global));
-            });
-        }
-
-        [Fact]
-        public void ScopeChainExcludesEmptyScopes()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Block, "z"),
+                scope => AssertScope(scope, DebugScopeType.Block, "y"),
+                scope => AssertScope(scope, DebugScopeType.Script, "x"),
+                scope => AssertScope(scope, DebugScopeType.Global));
+        });
+    }
+
+    [Fact]
+    public void ScopeChainExcludesEmptyScopes()
+    {
+        string script = @"
             const x = 2;
             if (x > 0)
             {
@@ -485,19 +485,19 @@ namespace Jint.Tests.Runtime.Debugger
                 }
             }";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CurrentScopeChain,
-                    scope => AssertScope(scope, DebugScopeType.Block, "z"),
-                    scope => AssertScope(scope, DebugScopeType.Script, "x"),
-                    scope => AssertScope(scope, DebugScopeType.Global));
-            });
-        }
-
-        [Fact]
-        public void ResolvesScopeChainsUpTheCallStack()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string script = @"
+            Assert.Collection(info.CurrentScopeChain,
+                scope => AssertScope(scope, DebugScopeType.Block, "z"),
+                scope => AssertScope(scope, DebugScopeType.Script, "x"),
+                scope => AssertScope(scope, DebugScopeType.Global));
+        });
+    }
+
+    [Fact]
+    public void ResolvesScopeChainsUpTheCallStack()
+    {
+        string script = @"
             const x = 1;
             function foo(a, c)
             {
@@ -511,35 +511,35 @@ namespace Jint.Tests.Runtime.Debugger
 
             bar(x);";
 
-            TestHelpers.TestAtBreak(script, info =>
-            {
-                Assert.Collection(info.CallStack,
-                    frame => Assert.Collection(frame.ScopeChain,
-                        // in foo()
-                        scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "c"),
-                        scope => AssertScope(scope, DebugScopeType.Script, "x"),
-                        scope => AssertScope(scope, DebugScopeType.Global, "foo", "bar")
-                    ),
-                    frame => Assert.Collection(frame.ScopeChain,
-                        // in bar()
-                        scope => AssertScope(scope, DebugScopeType.Local, "arguments", "b"),
-                        scope => AssertScope(scope, DebugScopeType.Script, "x"),
-                        scope => AssertScope(scope, DebugScopeType.Global, "foo", "bar")
-                    ),
-                    frame => Assert.Collection(frame.ScopeChain,
-                        // in global
-                        scope => AssertScope(scope, DebugScopeType.Script, "x"),
-                        scope => AssertScope(scope, DebugScopeType.Global, "foo", "bar")
-                    )
-                );
-            });
-        }
-
-        [Fact]
-        public void InspectsModuleScopedBindings()
+        TestHelpers.TestAtBreak(script, info =>
         {
-            string main = @"const x = 1; debugger;";
-            TestHelpers.TestAtBreak(engine =>
+            Assert.Collection(info.CallStack,
+                frame => Assert.Collection(frame.ScopeChain,
+                    // in foo()
+                    scope => AssertScope(scope, DebugScopeType.Local, "arguments", "a", "c"),
+                    scope => AssertScope(scope, DebugScopeType.Script, "x"),
+                    scope => AssertScope(scope, DebugScopeType.Global, "foo", "bar")
+                ),
+                frame => Assert.Collection(frame.ScopeChain,
+                    // in bar()
+                    scope => AssertScope(scope, DebugScopeType.Local, "arguments", "b"),
+                    scope => AssertScope(scope, DebugScopeType.Script, "x"),
+                    scope => AssertScope(scope, DebugScopeType.Global, "foo", "bar")
+                ),
+                frame => Assert.Collection(frame.ScopeChain,
+                    // in global
+                    scope => AssertScope(scope, DebugScopeType.Script, "x"),
+                    scope => AssertScope(scope, DebugScopeType.Global, "foo", "bar")
+                )
+            );
+        });
+    }
+
+    [Fact]
+    public void InspectsModuleScopedBindings()
+    {
+        string main = @"const x = 1; debugger;";
+        TestHelpers.TestAtBreak(engine =>
             {
                 engine.Modules.Add("main", main);
                 engine.Modules.Import("main");
@@ -550,6 +550,5 @@ namespace Jint.Tests.Runtime.Debugger
                 var value = AssertOnlyScopeContains(info.CurrentScopeChain, "x", DebugScopeType.Module);
                 Assert.Equal(1, value.AsInteger());
             });
-        }
     }
-}
+}

+ 181 - 182
Jint.Tests/Runtime/Debugger/StepFlowTests.cs

@@ -1,31 +1,31 @@
 using Jint.Runtime.Debugger;
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public class StepFlowTests
 {
-    public class StepFlowTests
+    private List<Node> CollectStepNodes(string script)
     {
-        private List<Node> CollectStepNodes(string script)
-        {
-            var engine = new Engine(options => options
-                .DebugMode()
-                .InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .InitialStepMode(StepMode.Into));
 
-            var nodes = new List<Node>();
-            engine.Debugger.Step += (sender, info) =>
-            {
-                nodes.Add(info.CurrentNode);
-                return StepMode.Into;
-            };
+        var nodes = new List<Node>();
+        engine.Debugger.Step += (sender, info) =>
+        {
+            nodes.Add(info.CurrentNode);
+            return StepMode.Into;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            return nodes;
-        }
+        return nodes;
+    }
 
-        [Fact]
-        public void StepsThroughWhileLoop()
-        {
-            var script = @"
+    [Fact]
+    public void StepsThroughWhileLoop()
+    {
+        var script = @"
                 let x = 0;
                 while (x < 2)
                 {
@@ -33,23 +33,23 @@ namespace Jint.Tests.Runtime.Debugger
                 }
             ";
 
-            var nodes = CollectStepNodes(script);
-
-            Assert.Collection(nodes,
-                node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
-                node => Assert.IsType<WhileStatement>(node),      // while ...
-                node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
-                node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
-                node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
-                node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
-                node => Assert.IsType<NonLogicalBinaryExpression>(node)     // x < 2 (false)
-            );
-        }
+        var nodes = CollectStepNodes(script);
+
+        Assert.Collection(nodes,
+            node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
+            node => Assert.IsType<WhileStatement>(node),      // while ...
+            node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
+            node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
+            node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
+            node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
+            node => Assert.IsType<NonLogicalBinaryExpression>(node)     // x < 2 (false)
+        );
+    }
 
-        [Fact]
-        public void StepsThroughDoWhileLoop()
-        {
-            var script = @"
+    [Fact]
+    public void StepsThroughDoWhileLoop()
+    {
+        var script = @"
                 let x = 0;
                 do
                 {
@@ -58,47 +58,47 @@ namespace Jint.Tests.Runtime.Debugger
                 while (x < 2)
             ";
 
-            var nodes = CollectStepNodes(script);
+        var nodes = CollectStepNodes(script);
 
-            Assert.Collection(nodes,
-                node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
-                node => Assert.IsType<DoWhileStatement>(node),    // do ...
-                node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
-                node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
-                node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
-                node => Assert.IsType<NonLogicalBinaryExpression>(node)     // x < 2 (false)
-            );
-        }
+        Assert.Collection(nodes,
+            node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
+            node => Assert.IsType<DoWhileStatement>(node),    // do ...
+            node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
+            node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
+            node => Assert.IsType<NonSpecialExpressionStatement>(node), // x++;
+            node => Assert.IsType<NonLogicalBinaryExpression>(node)     // x < 2 (false)
+        );
+    }
 
-        [Fact]
-        public void StepsThroughForLoop()
-        {
-            var script = @"
+    [Fact]
+    public void StepsThroughForLoop()
+    {
+        var script = @"
                 for (let x = 0; x < 2; x++)
                 {
                     'dummy';
                 }
             ";
 
-            var nodes = CollectStepNodes(script);
-
-            Assert.Collection(nodes,
-                node => Assert.IsType<ForStatement>(node),        // for ...
-                node => Assert.IsType<VariableDeclaration>(node), // let x = 0
-                node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
-                node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
-                node => Assert.IsType<UpdateExpression>(node),    // x++;
-                node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
-                node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
-                node => Assert.IsType<UpdateExpression>(node),    // x++;
-                node => Assert.IsType<NonLogicalBinaryExpression>(node)     // x < 2 (false)
-            );
-        }
+        var nodes = CollectStepNodes(script);
+
+        Assert.Collection(nodes,
+            node => Assert.IsType<ForStatement>(node),        // for ...
+            node => Assert.IsType<VariableDeclaration>(node), // let x = 0
+            node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
+            node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
+            node => Assert.IsType<UpdateExpression>(node),    // x++;
+            node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
+            node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
+            node => Assert.IsType<UpdateExpression>(node),    // x++;
+            node => Assert.IsType<NonLogicalBinaryExpression>(node)     // x < 2 (false)
+        );
+    }
 
-        [Fact]
-        public void StepsThroughForOfLoop()
-        {
-            var script = @"
+    [Fact]
+    public void StepsThroughForOfLoop()
+    {
+        var script = @"
                 const arr = [1, 2];
                 for (const item of arr)
                 {
@@ -106,22 +106,22 @@ namespace Jint.Tests.Runtime.Debugger
                 }
             ";
 
-            var nodes = CollectStepNodes(script);
+        var nodes = CollectStepNodes(script);
 
-            Assert.Collection(nodes,
-                node => Assert.IsType<VariableDeclaration>(node), // let arr = [1, 2];
-                node => Assert.IsType<ForOfStatement>(node),      // for ...
-                node => Assert.IsType<VariableDeclaration>(node), // item
-                node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
-                node => Assert.IsType<VariableDeclaration>(node), // item
-                node => Assert.True(node.IsLiteral("dummy"))      // 'dummy';
-            );
-        }
+        Assert.Collection(nodes,
+            node => Assert.IsType<VariableDeclaration>(node), // let arr = [1, 2];
+            node => Assert.IsType<ForOfStatement>(node),      // for ...
+            node => Assert.IsType<VariableDeclaration>(node), // item
+            node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
+            node => Assert.IsType<VariableDeclaration>(node), // item
+            node => Assert.True(node.IsLiteral("dummy"))      // 'dummy';
+        );
+    }
 
-        [Fact]
-        public void StepsThroughForInLoop()
-        {
-            var script = @"
+    [Fact]
+    public void StepsThroughForInLoop()
+    {
+        var script = @"
                 const obj = { x: 1, y: 2 };
                 for (const key in obj)
                 {
@@ -129,22 +129,22 @@ namespace Jint.Tests.Runtime.Debugger
                 }
             ";
 
-            var nodes = CollectStepNodes(script);
+        var nodes = CollectStepNodes(script);
 
-            Assert.Collection(nodes,
-                node => Assert.IsType<VariableDeclaration>(node), // let obj = { x: 1, y: 2 };
-                node => Assert.IsType<ForInStatement>(node),      // for ...
-                node => Assert.IsType<VariableDeclaration>(node), // key
-                node => Assert.IsType<NonSpecialExpressionStatement>(node), // 'dummy';
-                node => Assert.IsType<VariableDeclaration>(node), // key
-                node => Assert.IsType<NonSpecialExpressionStatement>(node)  // 'dummy';
-            );
-        }
+        Assert.Collection(nodes,
+            node => Assert.IsType<VariableDeclaration>(node), // let obj = { x: 1, y: 2 };
+            node => Assert.IsType<ForInStatement>(node),      // for ...
+            node => Assert.IsType<VariableDeclaration>(node), // key
+            node => Assert.IsType<NonSpecialExpressionStatement>(node), // 'dummy';
+            node => Assert.IsType<VariableDeclaration>(node), // key
+            node => Assert.IsType<NonSpecialExpressionStatement>(node)  // 'dummy';
+        );
+    }
 
-        [Fact]
-        public void StepsThroughConstructor()
-        {
-            var script = @"
+    [Fact]
+    public void StepsThroughConstructor()
+    {
+        var script = @"
                 class Test
                 {
                     constructor()
@@ -156,21 +156,21 @@ namespace Jint.Tests.Runtime.Debugger
                 'after construction';
             ";
 
-            var nodes = CollectStepNodes(script);
+        var nodes = CollectStepNodes(script);
 
-            Assert.Collection(nodes,
-                node => Assert.IsType<ClassDeclaration>(node),          // class Test
-                node => Assert.IsType<NonSpecialExpressionStatement>(node),       // new Test();
-                node => Assert.True(node.IsLiteral("in constructor")),  // 'in constructor()'
-                node => Assert.Null(node),                              // return point
-                node => Assert.True(node.IsLiteral("after construction"))
-            );
-        }
+        Assert.Collection(nodes,
+            node => Assert.IsType<ClassDeclaration>(node),          // class Test
+            node => Assert.IsType<NonSpecialExpressionStatement>(node),       // new Test();
+            node => Assert.True(node.IsLiteral("in constructor")),  // 'in constructor()'
+            node => Assert.Null(node),                              // return point
+            node => Assert.True(node.IsLiteral("after construction"))
+        );
+    }
 
-        [Fact]
-        public void SkipsFunctionBody()
-        {
-            var script = @"
+    [Fact]
+    public void SkipsFunctionBody()
+    {
+        var script = @"
                 function test()
                 {
                     'dummy';
@@ -178,20 +178,20 @@ namespace Jint.Tests.Runtime.Debugger
                 test();
             ";
 
-            var nodes = CollectStepNodes(script);
+        var nodes = CollectStepNodes(script);
 
-            Assert.Collection(nodes,
-                node => Assert.IsType<FunctionDeclaration>(node), // function(test) ...;
-                node => Assert.IsType<NonSpecialExpressionStatement>(node), // test();
-                node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
-                node => Assert.Null(node)                         // return point
-            );
-        }
+        Assert.Collection(nodes,
+            node => Assert.IsType<FunctionDeclaration>(node), // function(test) ...;
+            node => Assert.IsType<NonSpecialExpressionStatement>(node), // test();
+            node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
+            node => Assert.Null(node)                         // return point
+        );
+    }
 
-        [Fact]
-        public void SkipsReturnPointOfImplicitConstructor()
-        {
-            var script = @"
+    [Fact]
+    public void SkipsReturnPointOfImplicitConstructor()
+    {
+        var script = @"
                 class Test
                 {
                 }
@@ -199,82 +199,81 @@ namespace Jint.Tests.Runtime.Debugger
                 'dummy';
             ";
 
-            var nodes = CollectStepNodes(script);
-            Assert.Collection(nodes,
-                node => Assert.IsType<ClassDeclaration>(node),    // class Test
-                node => Assert.IsType<NonSpecialExpressionStatement>(node), // new Test();
-                node => Assert.True(node.IsLiteral("dummy"))      // 'dummy';
-            );
-        }
+        var nodes = CollectStepNodes(script);
+        Assert.Collection(nodes,
+            node => Assert.IsType<ClassDeclaration>(node),    // class Test
+            node => Assert.IsType<NonSpecialExpressionStatement>(node), // new Test();
+            node => Assert.True(node.IsLiteral("dummy"))      // 'dummy';
+        );
+    }
 
-        [Fact]
-        public void StepIntoNamedFunctionCalls()
-        {
-            var script = @"
+    [Fact]
+    public void StepIntoNamedFunctionCalls()
+    {
+        var script = @"
 function a( ) { return 2; }
 function b(l) { return l + a(); }
 function c( ) { return b(3) + a(); }
 let res = c();
 ";
 
-            var steps = StepIntoScript(script);
-            Assert.Collection(steps,
-                step => Assert.Equal("function c( ) { »return b(3) + a(); }", step),
-                step => Assert.Equal("function b(l) { »return l + a(); }", step),
-                step => Assert.Equal("function a( ) { »return 2; }", step),
-                step => Assert.Equal("function a( ) { return 2; }»", step),
-                step => Assert.Equal("function b(l) { return l + a(); }»", step),
-                step => Assert.Equal("function a( ) { »return 2; }", step),
-                step => Assert.Equal("function a( ) { return 2; }»", step),
-                step => Assert.Equal("function c( ) { return b(3) + a(); }»", step));
-        }
+        var steps = StepIntoScript(script);
+        Assert.Collection(steps,
+            step => Assert.Equal("function c( ) { »return b(3) + a(); }", step),
+            step => Assert.Equal("function b(l) { »return l + a(); }", step),
+            step => Assert.Equal("function a( ) { »return 2; }", step),
+            step => Assert.Equal("function a( ) { return 2; }»", step),
+            step => Assert.Equal("function b(l) { return l + a(); }»", step),
+            step => Assert.Equal("function a( ) { »return 2; }", step),
+            step => Assert.Equal("function a( ) { return 2; }»", step),
+            step => Assert.Equal("function c( ) { return b(3) + a(); }»", step));
+    }
 
-        [Fact]
-        public void StepIntoArrowFunctionCalls()
-        {
-            var script = @"
+    [Fact]
+    public void StepIntoArrowFunctionCalls()
+    {
+        var script = @"
 const a = ( ) => 2;
 const b = (l) => l + a();
 const c = ( ) => b(3) + a();
 let res = c();
 ";
 
-            var steps = StepIntoScript(script);
-            Assert.Collection(steps,
-                step => Assert.Equal("const c = ( ) => »b(3) + a();", step),
-                step => Assert.Equal("const b = (l) => »l + a();", step),
-                step => Assert.Equal("const a = ( ) => »2;", step),
-                step => Assert.Equal("const a = ( ) => 2»;", step),
-                step => Assert.Equal("const b = (l) => l + a()»;", step),
-                step => Assert.Equal("const a = ( ) => »2;", step),
-                step => Assert.Equal("const a = ( ) => 2»;", step),
-                step => Assert.Equal("const c = ( ) => b(3) + a()»;", step));
-        }
+        var steps = StepIntoScript(script);
+        Assert.Collection(steps,
+            step => Assert.Equal("const c = ( ) => »b(3) + a();", step),
+            step => Assert.Equal("const b = (l) => »l + a();", step),
+            step => Assert.Equal("const a = ( ) => »2;", step),
+            step => Assert.Equal("const a = ( ) => 2»;", step),
+            step => Assert.Equal("const b = (l) => l + a()»;", step),
+            step => Assert.Equal("const a = ( ) => »2;", step),
+            step => Assert.Equal("const a = ( ) => 2»;", step),
+            step => Assert.Equal("const c = ( ) => b(3) + a()»;", step));
+    }
+
+    private List<string> StepIntoScript(string script)
+    {
+        var engine = new Engine(options => options
+            .DebugMode()
+            .InitialStepMode(StepMode.Into));
+
+        var stepStatements = new List<string>();
+        var scriptLines = script.Replace("\r\n", "\n").Replace("\r", "\n").Split('\n');
+        engine.Debugger.Step += (sender, information) =>
+        {
+            if (information.CurrentNode is not VariableDeclaration && information.CurrentNode is not FunctionDeclaration)
+                OutputPosition(information.Location);
+            return StepMode.Into;
+        };
+
+        engine.Execute(script);
+        return stepStatements;
 
-        private List<string> StepIntoScript(string script)
+        void OutputPosition(in SourceLocation location)
         {
-            var engine = new Engine(options => options
-                .DebugMode()
-                .InitialStepMode(StepMode.Into));
-
-            var stepStatements = new List<string>();
-            var scriptLines = script.Replace("\r\n", "\n").Replace("\r", "\n").Split('\n');
-            engine.Debugger.Step += (sender, information) =>
-            {
-                if (information.CurrentNode is not VariableDeclaration && information.CurrentNode is not FunctionDeclaration)
-                    OutputPosition(information.Location);
-                return StepMode.Into;
-            };
-
-            engine.Execute(script);
-            return stepStatements;
-
-            void OutputPosition(in SourceLocation location)
-            {
-                var line = scriptLines[location.Start.Line - 1];
-                var withPositionIndicator = string.Concat(line.Substring(0, location.Start.Column), "»", line.Substring(location.Start.Column));
-                stepStatements.Add(withPositionIndicator.TrimEnd());
-            }
+            var line = scriptLines[location.Start.Line - 1];
+            var withPositionIndicator = string.Concat(line.Substring(0, location.Start.Column), "»", line.Substring(location.Start.Column));
+            stepStatements.Add(withPositionIndicator.TrimEnd());
         }
     }
-}
+}

+ 238 - 239
Jint.Tests/Runtime/Debugger/StepModeTests.cs

@@ -1,60 +1,60 @@
 using Jint.Runtime.Debugger;
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public class StepModeTests
 {
-    public class StepModeTests
+    /// <summary>
+    /// Helper method to keep tests independent of line numbers, columns or other arbitrary assertions on
+    /// the current statement. Steps through script with StepMode.Into until it reaches literal statement
+    /// (or directive) 'source'. Then counts the steps needed to reach 'target' using the indicated StepMode.
+    /// </summary>
+    /// <param name="script">Script used as basis for test</param>
+    /// <param name="stepMode">StepMode to use from source to target</param>
+    /// <returns>Number of steps from source to target</returns>
+    private static int StepsFromSourceToTarget(string script, StepMode stepMode)
     {
-        /// <summary>
-        /// Helper method to keep tests independent of line numbers, columns or other arbitrary assertions on
-        /// the current statement. Steps through script with StepMode.Into until it reaches literal statement
-        /// (or directive) 'source'. Then counts the steps needed to reach 'target' using the indicated StepMode.
-        /// </summary>
-        /// <param name="script">Script used as basis for test</param>
-        /// <param name="stepMode">StepMode to use from source to target</param>
-        /// <returns>Number of steps from source to target</returns>
-        private static int StepsFromSourceToTarget(string script, StepMode stepMode)
+        var engine = new Engine(options => options
+            .DebugMode()
+            .InitialStepMode(StepMode.Into)
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script));
+
+        int steps = 0;
+        bool sourceReached = false;
+        bool targetReached = false;
+        engine.Debugger.Step += (sender, info) =>
         {
-            var engine = new Engine(options => options
-                .DebugMode()
-                .InitialStepMode(StepMode.Into)
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script));
-
-            int steps = 0;
-            bool sourceReached = false;
-            bool targetReached = false;
-            engine.Debugger.Step += (sender, info) =>
+            if (sourceReached)
             {
-                if (sourceReached)
-                {
-                    steps++;
-                    if (info.ReachedLiteral("target"))
-                    {
-                        // Stop stepping
-                        targetReached = true;
-                        return StepMode.None;
-                    }
-                    return stepMode;
-                }
-                else if (info.ReachedLiteral("source"))
+                steps++;
+                if (info.ReachedLiteral("target"))
                 {
-                    sourceReached = true;
-                    return stepMode;
+                    // Stop stepping
+                    targetReached = true;
+                    return StepMode.None;
                 }
-                return StepMode.Into;
-            };
+                return stepMode;
+            }
+            else if (info.ReachedLiteral("source"))
+            {
+                sourceReached = true;
+                return stepMode;
+            }
+            return StepMode.Into;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
             
-            // Make sure we actually reached the target
-            Assert.True(targetReached);
+        // Make sure we actually reached the target
+        Assert.True(targetReached);
 
-            return steps;
-        }
+        return steps;
+    }
 
-        [Fact]
-        public void StepsIntoRegularFunctionCall()
-        {
-            var script = @"
+    [Fact]
+    public void StepsIntoRegularFunctionCall()
+    {
+        var script = @"
                 'source';
                 test(); // first step
                 function test()
@@ -62,13 +62,13 @@ namespace Jint.Tests.Runtime.Debugger
                     'target'; // second step
                 }";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
+    }
 
-        [Fact]
-        public void StepsOverRegularFunctionCall()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOverRegularFunctionCall()
+    {
+        var script = @"
                 'source';
                 test();
                 'target';
@@ -77,13 +77,13 @@ namespace Jint.Tests.Runtime.Debugger
                     'dummy';
                 }";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
+    }
 
-        [Fact]
-        public void StepsOutOfRegularFunctionCall()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOutOfRegularFunctionCall()
+    {
+        var script = @"
                 test();
                 'target';
 
@@ -93,13 +93,13 @@ namespace Jint.Tests.Runtime.Debugger
                     'dummy';
                 }";
 
-            Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
-        }
+        Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
+    }
 
-        [Fact]
-        public void StepsIntoMemberFunctionCall()
-        {
-            var script = @"
+    [Fact]
+    public void StepsIntoMemberFunctionCall()
+    {
+        var script = @"
                 const obj = {
                     test()
                     {
@@ -109,13 +109,13 @@ namespace Jint.Tests.Runtime.Debugger
                 'source';
                 obj.test(); // first step";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
+    }
 
-        [Fact]
-        public void StepsOverMemberFunctionCall()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOverMemberFunctionCall()
+    {
+        var script = @"
                 const obj = {
                     test()
                     {
@@ -126,13 +126,13 @@ namespace Jint.Tests.Runtime.Debugger
                 obj.test();
                 'target';";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
+    }
 
-        [Fact]
-        public void StepsOutOfMemberFunctionCall()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOutOfMemberFunctionCall()
+    {
+        var script = @"
                 const obj = {
                     test()
                     {
@@ -143,13 +143,13 @@ namespace Jint.Tests.Runtime.Debugger
                 obj.test();
                 'target';";
 
-            Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
-        }
+        Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
+    }
 
-        [Fact]
-        public void StepsIntoCallExpression()
-        {
-            var script = @"
+    [Fact]
+    public void StepsIntoCallExpression()
+    {
+        var script = @"
                 function test()
                 {
                     'target'; // second step
@@ -158,13 +158,13 @@ namespace Jint.Tests.Runtime.Debugger
                 'source';
                 const x = test(); // first step";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
+    }
 
-        [Fact]
-        public void StepsOverCallExpression()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOverCallExpression()
+    {
+        var script = @"
                 function test()
                 {
                     'dummy';
@@ -174,13 +174,13 @@ namespace Jint.Tests.Runtime.Debugger
                 const x = test();
                 'target';";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
+    }
 
-        [Fact]
-        public void StepsOutOfCallExpression()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOutOfCallExpression()
+    {
+        var script = @"
                 function test()
                 {
                     'source';
@@ -190,13 +190,13 @@ namespace Jint.Tests.Runtime.Debugger
                 const x = test();
                 'target';";
 
-            Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
-        }
+        Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
+    }
 
-        [Fact]
-        public void StepsIntoGetAccessor()
-        {
-            var script = @"
+    [Fact]
+    public void StepsIntoGetAccessor()
+    {
+        var script = @"
                 const obj = {
                     get test()
                     {
@@ -207,13 +207,13 @@ namespace Jint.Tests.Runtime.Debugger
                 'source';
                 const x = obj.test; // first step";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
+    }
 
-        [Fact]
-        public void StepsOverGetAccessor()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOverGetAccessor()
+    {
+        var script = @"
                 const obj = {
                     get test()
                     {
@@ -224,13 +224,13 @@ namespace Jint.Tests.Runtime.Debugger
                 const x = obj.test;
                 'target';";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
+    }
 
-        [Fact]
-        public void StepsOutOfGetAccessor()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOutOfGetAccessor()
+    {
+        var script = @"
                 const obj = {
                     get test()
                     {
@@ -242,13 +242,13 @@ namespace Jint.Tests.Runtime.Debugger
                 const x = obj.test;
                 'target';";
 
-            Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
-        }
+        Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
+    }
 
-        [Fact]
-        public void StepsIntoSetAccessor()
-        {
-            var script = @"
+    [Fact]
+    public void StepsIntoSetAccessor()
+    {
+        var script = @"
                 const obj = {
                     set test(value)
                     {
@@ -259,13 +259,13 @@ namespace Jint.Tests.Runtime.Debugger
                 'source';
                 obj.test = 37; // first step";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
+    }
 
-        [Fact]
-        public void StepsOverSetAccessor()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOverSetAccessor()
+    {
+        var script = @"
                 const obj = {
                     set test(value)
                     {
@@ -276,13 +276,13 @@ namespace Jint.Tests.Runtime.Debugger
                 obj.test = 37;
                 'target';";
 
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
+    }
 
-        [Fact]
-        public void StepsOutOfSetAccessor()
-        {
-            var script = @"
+    [Fact]
+    public void StepsOutOfSetAccessor()
+    {
+        var script = @"
                 const obj = {
                     set test(value)
                     {
@@ -294,26 +294,26 @@ namespace Jint.Tests.Runtime.Debugger
                 obj.test = 37;
                 'target';";
 
-            Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
-        }
+        Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
+    }
 
-        [Fact]
-        public void ReturnPointIsAStep()
-        {
-            var script = @"
+    [Fact]
+    public void ReturnPointIsAStep()
+    {
+        var script = @"
                 function test()
                 {
                     'source';
                 }
                 test();
                 'target';";
-            Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
-        }
+        Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
+    }
 
-        [Fact]
-        public void ReturnStatementIsAStep()
-        {
-            var script = @"
+    [Fact]
+    public void ReturnStatementIsAStep()
+    {
+        var script = @"
                 function test()
                 {
                     'source';
@@ -321,13 +321,13 @@ namespace Jint.Tests.Runtime.Debugger
                 }
                 test();
                 'target';";
-            Assert.Equal(3, StepsFromSourceToTarget(script, StepMode.Over));
-        }
+        Assert.Equal(3, StepsFromSourceToTarget(script, StepMode.Over));
+    }
 
-        [Fact]
-        public void StepOutOnlyStepsOutOneStackLevel()
-        {
-            var script = @"
+    [Fact]
+    public void StepOutOnlyStepsOutOneStackLevel()
+    {
+        var script = @"
                 function test()
                 {
                     'dummy';
@@ -344,34 +344,34 @@ namespace Jint.Tests.Runtime.Debugger
 
                 test();";
 
-            var engine = new Engine(options => options.DebugMode());
-            int step = 0;
-            engine.Debugger.Step += (sender, info) =>
+        var engine = new Engine(options => options.DebugMode());
+        int step = 0;
+        engine.Debugger.Step += (sender, info) =>
+        {
+            switch (step)
             {
-                switch (step)
-                {
-                    case 0:
-                        if (info.ReachedLiteral("source"))
-                        {
-                            step++;
-                            return StepMode.Out;
-                        }
-                        break;
-                    case 1:
-                        Assert.True(info.ReachedLiteral("target"));
+                case 0:
+                    if (info.ReachedLiteral("source"))
+                    {
                         step++;
-                        break;
-                }
-                return StepMode.Into;
-            };
+                        return StepMode.Out;
+                    }
+                    break;
+                case 1:
+                    Assert.True(info.ReachedLiteral("target"));
+                    step++;
+                    break;
+            }
+            return StepMode.Into;
+        };
 
-            engine.Execute(script);
-        }
+        engine.Execute(script);
+    }
 
-        [Fact]
-        public void StepOverDoesSinglestepAfterBreakpoint()
-        {
-            string script = @"
+    [Fact]
+    public void StepOverDoesSinglestepAfterBreakpoint()
+    {
+        string script = @"
                 test();
 
                 function test()
@@ -381,33 +381,33 @@ namespace Jint.Tests.Runtime.Debugger
                     'target';
                 }";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script));
 
-            bool stepping = false;
+        bool stepping = false;
 
-            engine.Debugger.Break += (sender, info) =>
-            {
-                stepping = true;
-                return StepMode.Over;
-            };
-            engine.Debugger.Step += (sender, info) =>
+        engine.Debugger.Break += (sender, info) =>
+        {
+            stepping = true;
+            return StepMode.Over;
+        };
+        engine.Debugger.Step += (sender, info) =>
+        {
+            if (stepping)
             {
-                if (stepping)
-                {
-                    Assert.True(info.ReachedLiteral("target"));
-                }
-                return StepMode.None;
-            };
+                Assert.True(info.ReachedLiteral("target"));
+            }
+            return StepMode.None;
+        };
 
-            engine.Execute(script);
-        }
+        engine.Execute(script);
+    }
 
-        [Fact]
-        public void StepNotTriggeredWhenRunning()
-        {
-            string script = @"
+    [Fact]
+    public void StepNotTriggeredWhenRunning()
+    {
+        string script = @"
                 test();
 
                 function test()
@@ -416,27 +416,27 @@ namespace Jint.Tests.Runtime.Debugger
                     'dummy';
                 }";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .InitialStepMode(StepMode.Into));
 
-            int stepCount = 0;
-            engine.Debugger.Step += (sender, info) =>
-            {
-                stepCount++;
-                // Start running after first step
-                return StepMode.None;
-            };
+        int stepCount = 0;
+        engine.Debugger.Step += (sender, info) =>
+        {
+            stepCount++;
+            // Start running after first step
+            return StepMode.None;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            Assert.Equal(1, stepCount);
-        }
+        Assert.Equal(1, stepCount);
+    }
 
-        [Fact]
-        public void SkipIsTriggeredWhenRunning()
-        {
-            string script = @"
+    [Fact]
+    public void SkipIsTriggeredWhenRunning()
+    {
+        string script = @"
                 'step';
                 'skip';
                 'skip';
@@ -445,39 +445,38 @@ namespace Jint.Tests.Runtime.Debugger
                 'step';
                 ";
 
-            var engine = new Engine(options => options
-                .DebugMode()
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script)
-                .InitialStepMode(StepMode.Into));
+        var engine = new Engine(options => options
+            .DebugMode()
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script)
+            .InitialStepMode(StepMode.Into));
 
-            int stepCount = 0;
-            int skipCount = 0;
+        int stepCount = 0;
+        int skipCount = 0;
 
-            engine.Debugger.Step += (sender, info) =>
-            {
-                Assert.True(TestHelpers.IsLiteral(info.CurrentNode, "step"));
-                stepCount++;
-                // Start running after first step
-                return stepCount == 1 ? StepMode.None : StepMode.Into;
-            };
+        engine.Debugger.Step += (sender, info) =>
+        {
+            Assert.True(TestHelpers.IsLiteral(info.CurrentNode, "step"));
+            stepCount++;
+            // Start running after first step
+            return stepCount == 1 ? StepMode.None : StepMode.Into;
+        };
 
-            engine.Debugger.Skip += (sender, info) =>
-            {
-                Assert.True(TestHelpers.IsLiteral(info.CurrentNode, "skip"));
-                skipCount++;
-                return StepMode.None;
-            };
+        engine.Debugger.Skip += (sender, info) =>
+        {
+            Assert.True(TestHelpers.IsLiteral(info.CurrentNode, "skip"));
+            skipCount++;
+            return StepMode.None;
+        };
 
-            engine.Debugger.Break += (sender, info) =>
-            {
-                // Back to stepping after debugger statement
-                return StepMode.Into;
-            };
+        engine.Debugger.Break += (sender, info) =>
+        {
+            // Back to stepping after debugger statement
+            return StepMode.Into;
+        };
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            Assert.Equal(2, skipCount);
-            Assert.Equal(3, stepCount);
-        }
+        Assert.Equal(2, skipCount);
+        Assert.Equal(3, stepCount);
     }
-}
+}

+ 56 - 57
Jint.Tests/Runtime/Debugger/TestHelpers.cs

@@ -1,71 +1,70 @@
 using Jint.Runtime.Debugger;
 
-namespace Jint.Tests.Runtime.Debugger
+namespace Jint.Tests.Runtime.Debugger;
+
+public static class TestHelpers
 {
-    public static class TestHelpers
+    public static bool IsLiteral(this Node node, string requiredValue = null)
     {
-        public static bool IsLiteral(this Node node, string requiredValue = null)
+        return node switch
         {
-            return node switch
-            {
-                Directive directive => requiredValue == null || directive.Value == requiredValue,
-                NonSpecialExpressionStatement expr => requiredValue == null || (expr.Expression is StringLiteral literal && literal.Value == requiredValue),
-                _ => false
-            };
-        }
+            Directive directive => requiredValue == null || directive.Value == requiredValue,
+            NonSpecialExpressionStatement expr => requiredValue == null || (expr.Expression is StringLiteral literal && literal.Value == requiredValue),
+            _ => false
+        };
+    }
 
-        public static bool ReachedLiteral(this DebugInformation info, string requiredValue)
-        {
-            return info.CurrentNode.IsLiteral(requiredValue);
-        }
+    public static bool ReachedLiteral(this DebugInformation info, string requiredValue)
+    {
+        return info.CurrentNode.IsLiteral(requiredValue);
+    }
 
-        /// <summary>
-        /// Initializes engine in debugmode and executes script until debugger statement,
-        /// before calling stepHandler for assertions. Also asserts that a break was triggered.
-        /// </summary>
-        /// <param name="initialization">Action to initialize and execute scripts</param>
-        /// <param name="breakHandler">Handler for assertions</param>
-        public static void TestAtBreak(Action<Engine> initialization, Action<Engine, DebugInformation> breakHandler)
-        {
-            var engine = new Engine(options => options
-                .DebugMode()
-                .DebuggerStatementHandling(DebuggerStatementHandling.Script)
-            );
+    /// <summary>
+    /// Initializes engine in debugmode and executes script until debugger statement,
+    /// before calling stepHandler for assertions. Also asserts that a break was triggered.
+    /// </summary>
+    /// <param name="initialization">Action to initialize and execute scripts</param>
+    /// <param name="breakHandler">Handler for assertions</param>
+    public static void TestAtBreak(Action<Engine> initialization, Action<Engine, DebugInformation> breakHandler)
+    {
+        var engine = new Engine(options => options
+            .DebugMode()
+            .DebuggerStatementHandling(DebuggerStatementHandling.Script)
+        );
 
-            bool didBreak = false;
-            engine.Debugger.Break += (sender, info) =>
-            {
-                didBreak = true;
-                breakHandler(sender as Engine, info);
-                return StepMode.None;
-            };
+        bool didBreak = false;
+        engine.Debugger.Break += (sender, info) =>
+        {
+            didBreak = true;
+            breakHandler(sender as Engine, info);
+            return StepMode.None;
+        };
 
-            initialization(engine);
+        initialization(engine);
 
-            Assert.True(didBreak, "Test script did not break (e.g. didn't reach debugger statement)");
-        }
+        Assert.True(didBreak, "Test script did not break (e.g. didn't reach debugger statement)");
+    }
 
-        /// <inheritdoc cref="TestAtBreak()"/>
-        public static void TestAtBreak(Action<Engine> initialization, Action<DebugInformation> breakHandler)
-        {
-            TestAtBreak(engine => initialization(engine), (engine, info) => breakHandler(info));
-        }
+    /// <inheritdoc cref="TestAtBreak()"/>
+    public static void TestAtBreak(Action<Engine> initialization, Action<DebugInformation> breakHandler)
+    {
+        TestAtBreak(engine => initialization(engine), (engine, info) => breakHandler(info));
+    }
 
-        /// <summary>
-        /// Initializes engine in debugmode and executes script until debugger statement,
-        /// before calling stepHandler for assertions. Also asserts that a break was triggered.
-        /// </summary>
-        /// <param name="script">Script that is basis for testing</param>
-        /// <param name="breakHandler">Handler for assertions</param>
-        public static void TestAtBreak(string script, Action<Engine, DebugInformation> breakHandler)
-        {
-            TestAtBreak(engine => engine.Execute(script), breakHandler);
-        }
+    /// <summary>
+    /// Initializes engine in debugmode and executes script until debugger statement,
+    /// before calling stepHandler for assertions. Also asserts that a break was triggered.
+    /// </summary>
+    /// <param name="script">Script that is basis for testing</param>
+    /// <param name="breakHandler">Handler for assertions</param>
+    public static void TestAtBreak(string script, Action<Engine, DebugInformation> breakHandler)
+    {
+        TestAtBreak(engine => engine.Execute(script), breakHandler);
+    }
 
-        /// <inheritdoc cref="TestAtBreak()"/>
-        public static void TestAtBreak(string script, Action<DebugInformation> breakHandler)
-        {
-            TestAtBreak(script, (engine, info) => breakHandler(info));
-        }
+    /// <inheritdoc cref="TestAtBreak()"/>
+    public static void TestAtBreak(string script, Action<DebugInformation> breakHandler)
+    {
+        TestAtBreak(script, (engine, info) => breakHandler(info));
     }
-}
+}

+ 123 - 124
Jint.Tests/Runtime/Domain/A.cs

@@ -1,127 +1,126 @@
 using Jint.Native;
 
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class A
 {
-    public class A
-    {
-        public int Call1()
-        {
-            return 0;
-        }
-
-        public int Call1(int x)
-        {
-            return x;
-        }
-
-        public string Call2(string x)
-        {
-            return x;
-        }
-
-        public string Call3(object x)
-        {
-            return x.ToString();
-        }
-
-        public string Call4(IPerson x)
-        {
-            return x.ToString();
-        }
-
-        public string Call5(Delegate callback)
-        {
-            var thisArg = JsValue.Undefined;
-            var arguments = new JsValue[] { 1, "foo" };
-
-            return callback.DynamicInvoke(thisArg, arguments).ToString();
-        }
-
-        public string Call6(Func<JsValue, JsValue[], JsValue> callback)
-        {
-            var thisArg = new JsString("bar");
-            var arguments = new JsValue[] { 1, "foo" };
-
-            return callback(thisArg, arguments).ToString();
-        }
-
-        public bool Call7(string str, Func<string, bool> predicate)
-        {
-            return predicate(str);
-        }
-
-        public string Call8(Func<string> predicate)
-        {
-            return predicate();
-        }
-
-        public void Call9(Action predicate)
-        {
-            predicate();
-        }
-
-        public void Call10(string str, Action<string> predicate)
-        {
-            predicate(str);
-        }
-
-        public void Call11(string str, string str2, Action<string, string> predicate)
-        {
-            predicate(str, str2);
-        }
-
-        public int Call12(int value, Func<int, int> map)
-        {
-            return map(value);
-        }
-
-        public string Call13(params object[] values)
-        {
-            return String.Join(",", values);
-        }
-
-        public string Call14(string firstParam, params object[] values)
-        {
-            return String.Format("{0}:{1}", firstParam, String.Join(",", values));
-        }
-
-        public void Call15(string x)
-        {
-
-        }
-        public string Call16(params JsValue[] values)
-        {
-            return String.Join(",", (System.Collections.Generic.IEnumerable<JsValue>)values);
-        }
-
-        public int Call17(Func<int, int> callback)
-        {
-            return callback(17);
-        }
-
-        public void Call18(Action<int> callback)
-        {
-            callback(18);
-        }
-
-        public int Call19(int a = 0)
-        {
-            return a;
-        }
-
-        public static int Call19Static(int a = 0)
-        {
-            return a;
-        }
-
-        public int Call20(int a, int b = 1, int c = 2)
-        {
-            return a + b + c;
-        }
-
-        public static int Call20Static(int a, int b = 1, int c = 2)
-        {
-            return a + b + c;
-        }
-    }
-}
+    public int Call1()
+    {
+        return 0;
+    }
+
+    public int Call1(int x)
+    {
+        return x;
+    }
+
+    public string Call2(string x)
+    {
+        return x;
+    }
+
+    public string Call3(object x)
+    {
+        return x.ToString();
+    }
+
+    public string Call4(IPerson x)
+    {
+        return x.ToString();
+    }
+
+    public string Call5(Delegate callback)
+    {
+        var thisArg = JsValue.Undefined;
+        var arguments = new JsValue[] { 1, "foo" };
+
+        return callback.DynamicInvoke(thisArg, arguments).ToString();
+    }
+
+    public string Call6(Func<JsValue, JsValue[], JsValue> callback)
+    {
+        var thisArg = new JsString("bar");
+        var arguments = new JsValue[] { 1, "foo" };
+
+        return callback(thisArg, arguments).ToString();
+    }
+
+    public bool Call7(string str, Func<string, bool> predicate)
+    {
+        return predicate(str);
+    }
+
+    public string Call8(Func<string> predicate)
+    {
+        return predicate();
+    }
+
+    public void Call9(Action predicate)
+    {
+        predicate();
+    }
+
+    public void Call10(string str, Action<string> predicate)
+    {
+        predicate(str);
+    }
+
+    public void Call11(string str, string str2, Action<string, string> predicate)
+    {
+        predicate(str, str2);
+    }
+
+    public int Call12(int value, Func<int, int> map)
+    {
+        return map(value);
+    }
+
+    public string Call13(params object[] values)
+    {
+        return String.Join(",", values);
+    }
+
+    public string Call14(string firstParam, params object[] values)
+    {
+        return String.Format("{0}:{1}", firstParam, String.Join(",", values));
+    }
+
+    public void Call15(string x)
+    {
+
+    }
+    public string Call16(params JsValue[] values)
+    {
+        return String.Join(",", (System.Collections.Generic.IEnumerable<JsValue>)values);
+    }
+
+    public int Call17(Func<int, int> callback)
+    {
+        return callback(17);
+    }
+
+    public void Call18(Action<int> callback)
+    {
+        callback(18);
+    }
+
+    public int Call19(int a = 0)
+    {
+        return a;
+    }
+
+    public static int Call19Static(int a = 0)
+    {
+        return a;
+    }
+
+    public int Call20(int a, int b = 1, int c = 2)
+    {
+        return a + b + c;
+    }
+
+    public static int Call20Static(int a, int b = 1, int c = 2)
+    {
+        return a + b + c;
+    }
+}

+ 123 - 124
Jint.Tests/Runtime/Domain/ArrayConverterTestClass.cs

@@ -1,131 +1,130 @@
 using System.Globalization;
 
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class ArrayConverterTestClass
 {
-    public class ArrayConverterTestClass
-    {
-        public string MethodAcceptsArrayOfStrings(string[] arrayOfStrings)
-        {
-            return SerializeToString(arrayOfStrings);
-        }
-
-        public string MethodAcceptsArrayOfInt(int[] arrayOfInt)
-        {
-            return SerializeToString(arrayOfInt);
-        }
-
-        public string MethodAcceptsArrayOfBool(int[] arrayOfBool)
-        {
-            return SerializeToString(arrayOfBool);
-        }
-
-        private static string SerializeToString<T>(IEnumerable<T> array)
-        {
-            return String.Join(",", array);
-        }
-    }
-
-    public class ArrayConverterItem : IConvertible
-    {
-        private readonly int _value;
-
-        public ArrayConverterItem(int value)
-        {
-            _value = value;
-        }
-
-        public override string ToString()
-        {
-            return ToString(CultureInfo.InvariantCulture);
-        }
-
-        public string ToString(IFormatProvider provider)
-        {
-            return _value.ToString(provider);
-        }
-
-        public int ToInt32(IFormatProvider provider)
-        {
-            return Convert.ToInt32(_value, provider);
-        }
-
-        #region NotImplemented
-        public TypeCode GetTypeCode()
-        {
-            return TypeCode.Object;
-        }
-
-        public bool ToBoolean(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public char ToChar(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public sbyte ToSByte(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public byte ToByte(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public short ToInt16(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public ushort ToUInt16(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public uint ToUInt32(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public long ToInt64(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public ulong ToUInt64(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public float ToSingle(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public double ToDouble(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public decimal ToDecimal(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public DateTime ToDateTime(IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-
-        public object ToType(Type conversionType, IFormatProvider provider)
-        {
-            throw new NotImplementedException();
-        }
-        #endregion
+    public string MethodAcceptsArrayOfStrings(string[] arrayOfStrings)
+    {
+        return SerializeToString(arrayOfStrings);
+    }
 
+    public string MethodAcceptsArrayOfInt(int[] arrayOfInt)
+    {
+        return SerializeToString(arrayOfInt);
+    }
 
+    public string MethodAcceptsArrayOfBool(int[] arrayOfBool)
+    {
+        return SerializeToString(arrayOfBool);
+    }
+
+    private static string SerializeToString<T>(IEnumerable<T> array)
+    {
+        return String.Join(",", array);
     }
 }
+
+public class ArrayConverterItem : IConvertible
+{
+    private readonly int _value;
+
+    public ArrayConverterItem(int value)
+    {
+        _value = value;
+    }
+
+    public override string ToString()
+    {
+        return ToString(CultureInfo.InvariantCulture);
+    }
+
+    public string ToString(IFormatProvider provider)
+    {
+        return _value.ToString(provider);
+    }
+
+    public int ToInt32(IFormatProvider provider)
+    {
+        return Convert.ToInt32(_value, provider);
+    }
+
+    #region NotImplemented
+    public TypeCode GetTypeCode()
+    {
+        return TypeCode.Object;
+    }
+
+    public bool ToBoolean(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public char ToChar(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public sbyte ToSByte(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public byte ToByte(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public short ToInt16(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public ushort ToUInt16(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public uint ToUInt32(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public long ToInt64(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public ulong ToUInt64(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public float ToSingle(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public double ToDouble(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public decimal ToDecimal(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public DateTime ToDateTime(IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+
+    public object ToType(Type conversionType, IFormatProvider provider)
+    {
+        throw new NotImplementedException();
+    }
+    #endregion
+
+
+}

+ 5 - 6
Jint.Tests/Runtime/Domain/ClassWithField.cs

@@ -1,7 +1,6 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class ClassWithField
 {
-    public class ClassWithField
-    {
-        public string Field;
-    }
-}
+    public string Field;
+}

+ 38 - 39
Jint.Tests/Runtime/Domain/ClassWithStaticFields.cs

@@ -1,52 +1,51 @@
-namespace Jint.Tests.Runtime.Domain
-{
-    public class ClassWithStaticFields
-    {
-        public static string Get = "Get";
-        public static string Set = "Set";
-
-        public static string Getter { get { return "Getter"; } }
-        public static string Setter { get; set; }
-
-        public static readonly string Readonly = "Readonly";
-
-        static ClassWithStaticFields()
-        {
-            Setter = "Setter";
-        }
+namespace Jint.Tests.Runtime.Domain;
+
+public class ClassWithStaticFields
+{
+    public static string Get = "Get";
+    public static string Set = "Set";
+
+    public static string Getter { get { return "Getter"; } }
+    public static string Setter { get; set; }
+
+    public static readonly string Readonly = "Readonly";
+
+    static ClassWithStaticFields()
+    {
+        Setter = "Setter";
     }
+}
 
-    public class Nested
+public class Nested
+{
+    public class ClassWithStaticFields
     {
-        public class ClassWithStaticFields
+        public static string Get = "Get";
+        public static string Set = "Set";
+
+        public static string Getter
         {
-            public static string Get = "Get";
-            public static string Set = "Set";
+            get { return "Getter"; }
+        }
 
-            public static string Getter
+        public static string Setter
+        {
+            get
             {
-                get { return "Getter"; }
+                return _setter;
             }
-
-            public static string Setter
+            set
             {
-                get
-                {
-                    return _setter;
-                }
-                set
-                {
-                    _setter = value;
-                }
+                _setter = value;
             }
+        }
 
-            public static readonly string Readonly = "Readonly";
-            private static string _setter;
+        public static readonly string Readonly = "Readonly";
+        private static string _setter;
 
-            static ClassWithStaticFields()
-            {
-                Setter = "Setter";
-            }
+        static ClassWithStaticFields()
+        {
+            Setter = "Setter";
         }
     }
-}
+}

+ 8 - 9
Jint.Tests/Runtime/Domain/Colors.cs

@@ -1,10 +1,9 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+[Flags]
+public enum Colors
 {
-    [Flags]
-    public enum Colors
-    {
-        Red,
-        Green,
-        Blue = 10
-    }
-}
+    Red,
+    Green,
+    Blue = 10
+}

+ 32 - 33
Jint.Tests/Runtime/Domain/Company.cs

@@ -1,44 +1,43 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class Company : ICompany, IComparable<ICompany>
 {
-    public class Company : ICompany, IComparable<ICompany>
-    {
-        private string _name;
+    private string _name;
 
-        private readonly Dictionary<string, string> _dictionary = new Dictionary<string, string>()
-        {
-            {"key", "value"}
-        };
+    private readonly Dictionary<string, string> _dictionary = new Dictionary<string, string>()
+    {
+        {"key", "value"}
+    };
 
-        public Company(string name)
-        {
-            _name = name;
-        }
+    public Company(string name)
+    {
+        _name = name;
+    }
 
-        string ICompany.Name
-        {
-            get => _name;
-            set => _name = value;
-        }
+    string ICompany.Name
+    {
+        get => _name;
+        set => _name = value;
+    }
 
-        string ICompany.this[string key]
-        {
-            get => _dictionary[key];
-            set => _dictionary[key] = value;
-        }
+    string ICompany.this[string key]
+    {
+        get => _dictionary[key];
+        set => _dictionary[key] = value;
+    }
 
-        public string Item => "item thingie";
+    public string Item => "item thingie";
 
-        int IComparable<ICompany>.CompareTo(ICompany other)
-        {
-            return string.Compare(_name, other.Name, StringComparison.CurrentCulture);
-        }
+    int IComparable<ICompany>.CompareTo(ICompany other)
+    {
+        return string.Compare(_name, other.Name, StringComparison.CurrentCulture);
+    }
 
-        public IEnumerable<char> GetNameChars()
+    public IEnumerable<char> GetNameChars()
+    {
+        foreach (var c in _name)
         {
-            foreach (var c in _name)
-            {
-                yield return c;
-            }
+            yield return c;
         }
     }
-}
+}

+ 47 - 48
Jint.Tests/Runtime/Domain/CustomNamed.cs

@@ -1,65 +1,64 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
+public class CustomNameAttribute : Attribute
 {
-    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
-    public class CustomNameAttribute : Attribute
+    public CustomNameAttribute(string name)
     {
-        public CustomNameAttribute(string name)
-        {
-            Name = name;
-        }
-
-        public string Name { get; }
+        Name = name;
     }
 
-    public interface ICustomNamed
-    {
-        [CustomName("jsInterfaceStringProperty")]
-        public string InterfaceStringProperty { get; }
+    public string Name { get; }
+}
 
-        [CustomName("jsInterfaceMethod")]
-        public string InterfaceMethod();
-    }
+public interface ICustomNamed
+{
+    [CustomName("jsInterfaceStringProperty")]
+    public string InterfaceStringProperty { get; }
 
-    [CustomName("jsCustomName")]
-    public class CustomNamed : ICustomNamed
-    {
-        [CustomName("jsStringField")]
-        [CustomName("jsStringField2")]
-        public string StringField = "StringField";
+    [CustomName("jsInterfaceMethod")]
+    public string InterfaceMethod();
+}
 
-        [CustomName("jsStaticStringField")]
-        public static string StaticStringField = "StaticStringField";
+[CustomName("jsCustomName")]
+public class CustomNamed : ICustomNamed
+{
+    [CustomName("jsStringField")]
+    [CustomName("jsStringField2")]
+    public string StringField = "StringField";
 
-        [CustomName("jsStringProperty")]
-        public string StringProperty => "StringProperty";
+    [CustomName("jsStaticStringField")]
+    public static string StaticStringField = "StaticStringField";
 
-        [CustomName("jsMethod")]
-        public string Method() => "Method";
+    [CustomName("jsStringProperty")]
+    public string StringProperty => "StringProperty";
 
-        [CustomName("jsStaticMethod")]
-        public static string StaticMethod() => "StaticMethod";
+    [CustomName("jsMethod")]
+    public string Method() => "Method";
 
-        public string InterfaceStringProperty => "InterfaceStringProperty";
+    [CustomName("jsStaticMethod")]
+    public static string StaticMethod() => "StaticMethod";
 
-        public string InterfaceMethod() => "InterfaceMethod";
+    public string InterfaceStringProperty => "InterfaceStringProperty";
 
-        [CustomName("jsEnumProperty")]
-        public CustomNamedEnum EnumProperty { get; set; }
-    }
+    public string InterfaceMethod() => "InterfaceMethod";
 
-    [CustomName("XmlHttpRequest")]
-    public enum CustomNamedEnum
-    {
-        [CustomName("NONE")]
-        None = 0,
+    [CustomName("jsEnumProperty")]
+    public CustomNamedEnum EnumProperty { get; set; }
+}
 
-        [CustomName("HEADERS_RECEIVED")]
-        HeadersReceived = 2
-    }
+[CustomName("XmlHttpRequest")]
+public enum CustomNamedEnum
+{
+    [CustomName("NONE")]
+    None = 0,
 
-    public static class CustomNamedExtensions
-    {
-        [CustomName("jsExtensionMethod")]
-        public static string ExtensionMethod(this CustomNamed customNamed) => "ExtensionMethod";
-    }
+    [CustomName("HEADERS_RECEIVED")]
+    HeadersReceived = 2
 }
+
+public static class CustomNamedExtensions
+{
+    [CustomName("jsExtensionMethod")]
+    public static string ExtensionMethod(this CustomNamed customNamed) => "ExtensionMethod";
+}

+ 82 - 83
Jint.Tests/Runtime/Domain/Dimensional.cs

@@ -1,115 +1,114 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class Dimensional : IComparable<Dimensional>, IEquatable<Dimensional>
 {
-    public class Dimensional : IComparable<Dimensional>, IEquatable<Dimensional>
-    {
-        private readonly MeasureUnit[] PossibleMeasureUnits = new MeasureUnit[] { new MeasureUnit("Mass", "kg", 1.0), new MeasureUnit("Mass", "gr", 0.001), new MeasureUnit("Count", "piece", 1.0) };
+    private readonly MeasureUnit[] PossibleMeasureUnits = new MeasureUnit[] { new MeasureUnit("Mass", "kg", 1.0), new MeasureUnit("Mass", "gr", 0.001), new MeasureUnit("Count", "piece", 1.0) };
 
-        public MeasureUnit MeasureUnit { get; private set; }
+    public MeasureUnit MeasureUnit { get; private set; }
 
-        public double Value { get; private set; }
+    public double Value { get; private set; }
 
-        public double NormalizatedValue
+    public double NormalizatedValue
+    {
+        get
         {
-            get
-            {
-                return Value * MeasureUnit.RelativeValue;
-            }
+            return Value * MeasureUnit.RelativeValue;
         }
+    }
 
-        public Dimensional(string measureUnit, double value)
-        {
-            MeasureUnit = GetMeasureUnitByName(measureUnit);
-            Value = value;
-        }
+    public Dimensional(string measureUnit, double value)
+    {
+        MeasureUnit = GetMeasureUnitByName(measureUnit);
+        Value = value;
+    }
 
-        public static Dimensional operator +(Dimensional left, Dimensional right)
-        {
-            if (left.MeasureUnit.MeasureType != right.MeasureUnit.MeasureType)
-                throw new InvalidOperationException("Dimensionals with different measure types are non-summable");
+    public static Dimensional operator +(Dimensional left, Dimensional right)
+    {
+        if (left.MeasureUnit.MeasureType != right.MeasureUnit.MeasureType)
+            throw new InvalidOperationException("Dimensionals with different measure types are non-summable");
 
-            return new Dimensional(left.MeasureUnit.RelativeValue <= right.MeasureUnit.RelativeValue ? left.MeasureUnit.Name : right.MeasureUnit.Name,
-                                                            left.Value * left.MeasureUnit.RelativeValue + right.Value * right.MeasureUnit.RelativeValue);
-        }
+        return new Dimensional(left.MeasureUnit.RelativeValue <= right.MeasureUnit.RelativeValue ? left.MeasureUnit.Name : right.MeasureUnit.Name,
+            left.Value * left.MeasureUnit.RelativeValue + right.Value * right.MeasureUnit.RelativeValue);
+    }
 
-        private MeasureUnit GetMeasureUnitByName(string name)
-        {
-            return PossibleMeasureUnits.FirstOrDefault(mu => mu.Name == name);
-        }
+    private MeasureUnit GetMeasureUnitByName(string name)
+    {
+        return PossibleMeasureUnits.FirstOrDefault(mu => mu.Name == name);
+    }
 
-        public int CompareTo(Dimensional obj)
-        {
-            if (MeasureUnit.MeasureType != obj.MeasureUnit.MeasureType)
-                throw new InvalidOperationException("Dimensionals with different measure types are non-comparable");
-            return NormalizatedValue.CompareTo(obj.NormalizatedValue);
-        }
+    public int CompareTo(Dimensional obj)
+    {
+        if (MeasureUnit.MeasureType != obj.MeasureUnit.MeasureType)
+            throw new InvalidOperationException("Dimensionals with different measure types are non-comparable");
+        return NormalizatedValue.CompareTo(obj.NormalizatedValue);
+    }
 
-        public override string ToString()
-        {
-            return Value + " " + MeasureUnit.Name;
-        }
+    public override string ToString()
+    {
+        return Value + " " + MeasureUnit.Name;
+    }
 
-        public bool Equals(Dimensional other)
+    public bool Equals(Dimensional other)
+    {
+        if (ReferenceEquals(null, other))
         {
-            if (ReferenceEquals(null, other))
-            {
-                return false;
-            }
-
-            if (ReferenceEquals(this, other))
-            {
-                return true;
-            }
-
-            return Value.Equals(other.Value) && Equals(MeasureUnit, other.MeasureUnit);
+            return false;
         }
 
-        public override bool Equals(object obj)
+        if (ReferenceEquals(this, other))
         {
-            return Equals(obj as Dimensional);
+            return true;
         }
 
-        public override int GetHashCode()
-        {
-            return Value.GetHashCode();
-        }
+        return Value.Equals(other.Value) && Equals(MeasureUnit, other.MeasureUnit);
     }
 
-    public class MeasureUnit : IEquatable<MeasureUnit>
+    public override bool Equals(object obj)
     {
-        public string MeasureType { get; set; }
-        public string Name { get; set; }
-        public double RelativeValue { get; set; }
-
-        public MeasureUnit(string measureType, string name, double relativeValue)
-        {
-            this.MeasureType = measureType;
-            this.Name = name;
-            this.RelativeValue = relativeValue;
-        }
+        return Equals(obj as Dimensional);
+    }
 
-        public bool Equals(MeasureUnit other)
-        {
-            if (ReferenceEquals(null, other))
-            {
-                return false;
-            }
+    public override int GetHashCode()
+    {
+        return Value.GetHashCode();
+    }
+}
 
-            if (ReferenceEquals(this, other))
-            {
-                return true;
-            }
+public class MeasureUnit : IEquatable<MeasureUnit>
+{
+    public string MeasureType { get; set; }
+    public string Name { get; set; }
+    public double RelativeValue { get; set; }
 
-            return MeasureType == other.MeasureType && Name == other.Name && RelativeValue.Equals(other.RelativeValue);
-        }
+    public MeasureUnit(string measureType, string name, double relativeValue)
+    {
+        this.MeasureType = measureType;
+        this.Name = name;
+        this.RelativeValue = relativeValue;
+    }
 
-        public override bool Equals(object obj)
+    public bool Equals(MeasureUnit other)
+    {
+        if (ReferenceEquals(null, other))
         {
-            return Equals(obj as MeasureUnit);
+            return false;
         }
 
-        public override int GetHashCode()
+        if (ReferenceEquals(this, other))
         {
-            return MeasureType.GetHashCode() ^ Name.GetHashCode() ^ RelativeValue.GetHashCode();
+            return true;
         }
+
+        return MeasureType == other.MeasureType && Name == other.Name && RelativeValue.Equals(other.RelativeValue);
     }
-}
+
+    public override bool Equals(object obj)
+    {
+        return Equals(obj as MeasureUnit);
+    }
+
+    public override int GetHashCode()
+    {
+        return MeasureType.GetHashCode() ^ Name.GetHashCode() ^ RelativeValue.GetHashCode();
+    }
+}

+ 10 - 11
Jint.Tests/Runtime/Domain/Enums.cs

@@ -1,14 +1,13 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public enum IntegerEnum
 {
-    public enum IntegerEnum
-    {
-        a,
-        b
-    }   
+    a,
+    b
+}   
     
-    public enum UintEnum : uint
-    {
-        a, 
-        b
-    }
+public enum UintEnum : uint
+{
+    a, 
+    b
 }

+ 5 - 6
Jint.Tests/Runtime/Domain/FloatIndexer.cs

@@ -1,7 +1,6 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class FloatIndexer
 {
-    public class FloatIndexer
-    {
-		public string this[int index] => "";
-    }
-}
+    public string this[int index] => "";
+}

+ 14 - 15
Jint.Tests/Runtime/Domain/HiddenMembers.cs

@@ -1,22 +1,21 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class HiddenMembers
 {
-    public class HiddenMembers
-    {
-        [Obsolete]
-        public string Field1 = "Field1";
+    [Obsolete]
+    public string Field1 = "Field1";
 
-        public string Field2 = "Field2";
+    public string Field2 = "Field2";
 
-        [Obsolete]
-        public string Member1 { get; set; } = "Member1";
+    [Obsolete]
+    public string Member1 { get; set; } = "Member1";
 
-        public string Member2 { get; set; } = "Member2";
+    public string Member2 { get; set; } = "Member2";
 
-        [Obsolete]
-        public string Method1() => "Method1";
+    [Obsolete]
+    public string Method1() => "Method1";
 
-        public string Method2() => "Method2";
+    public string Method2() => "Method2";
 
-        public Type Type => GetType();
-    }
-}
+    public Type Type => GetType();
+}

+ 5 - 6
Jint.Tests/Runtime/Domain/ICompany.cs

@@ -1,8 +1,7 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public interface ICompany
 {
-    public interface ICompany
-    {
-        string Name { get; set; }
-        string this[string key] { get; set; }
-    }
+    string Name { get; set; }
+    string this[string key] { get; set; }
 }

+ 5 - 7
Jint.Tests/Runtime/Domain/IPerson.cs

@@ -1,8 +1,6 @@
-namespace Jint.Tests.Runtime.Domain
-{
-    public interface IPerson
-    {
-        string Name { get; }
-    }
+namespace Jint.Tests.Runtime.Domain;
 
-}
+public interface IPerson
+{
+    string Name { get; }
+}

+ 12 - 13
Jint.Tests/Runtime/Domain/IntegerIndexer.cs

@@ -1,18 +1,17 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class IntegerIndexer
 {
-    public class IntegerIndexer
-    {
-        private readonly int[] data;
+    private readonly int[] data;
 
-        public IntegerIndexer()
-        {
-            data = new[] {123, 0, 0, 0, 0};
-        }
+    public IntegerIndexer()
+    {
+        data = new[] {123, 0, 0, 0, 0};
+    }
 
-        public int this[int i]
-        {
-            get => data[i];
-            set => data[i] = value;
-        }
+    public int this[int i]
+    {
+        get => data[i];
+        set => data[i] = value;
     }
 }

+ 14 - 15
Jint.Tests/Runtime/Domain/JsUuid.cs

@@ -1,26 +1,25 @@
 using Jint.Native;
 
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public sealed class JsUuid : JsValue, IEquatable<JsUuid>
 {
-    public sealed class JsUuid : JsValue, IEquatable<JsUuid>
-    {
-        internal readonly Guid _value;
-        public static readonly JsUuid Empty = new JsUuid(Guid.Empty);
+    internal readonly Guid _value;
+    public static readonly JsUuid Empty = new JsUuid(Guid.Empty);
 
-        public JsUuid(Guid value) : base(Jint.Runtime.Types.String) => _value = value;
+    public JsUuid(Guid value) : base(Jint.Runtime.Types.String) => _value = value;
 
-        public static implicit operator JsUuid(Guid g) => new JsUuid(g);
+    public static implicit operator JsUuid(Guid g) => new JsUuid(g);
 
-        public override bool Equals(JsValue other) => Equals(other as JsUuid);
+    public override bool Equals(JsValue other) => Equals(other as JsUuid);
 
-        public bool Equals(JsUuid other) => other?._value == _value;
+    public bool Equals(JsUuid other) => other?._value == _value;
 
-        public override int GetHashCode() => _value.GetHashCode();
+    public override int GetHashCode() => _value.GetHashCode();
 
-        public override object ToObject() => _value;
+    public override object ToObject() => _value;
 
-        public override string ToString() => _value.ToString();
+    public override string ToString() => _value.ToString();
 
-        public override bool Equals(object obj) => Equals(obj as JsUuid);
-    }
-}
+    public override bool Equals(object obj) => Equals(obj as JsUuid);
+}

+ 21 - 22
Jint.Tests/Runtime/Domain/OverLoading.cs

@@ -1,30 +1,29 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class OverLoading
 {
-    public class OverLoading
+    public string TestFunc(string e)
     {
-        public string TestFunc(string e)
-        {
-            return "string";
-        }
+        return "string";
+    }
 
-        public string TestFunc(IntegerEnum e)
-        {
-            return "integer-enum";
-        }
+    public string TestFunc(IntegerEnum e)
+    {
+        return "integer-enum";
+    }
 
-        public string TestFunc(UintEnum e)
-        {
-            return "uint-enum";
-        }
+    public string TestFunc(UintEnum e)
+    {
+        return "uint-enum";
+    }
 
-        public string TestFunc(float f)
-        {
-            return "float-val";
-        }
+    public string TestFunc(float f)
+    {
+        return "float-val";
+    }
 
-        public string TestFunc(int i)
-        {
-            return "int-val";
-        }
+    public string TestFunc(int i)
+    {
+        return "int-val";
     }
 }

+ 30 - 31
Jint.Tests/Runtime/Domain/Person.cs

@@ -1,45 +1,44 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class Person : IPerson
 {
-    public class Person : IPerson
+    public string Name { get; set; }
+    public int Age { get; set; }
+
+    public Type TypeProperty { get; set; } = typeof(Person);
+
+    public override string ToString()
     {
-        public string Name { get; set; }
-        public int Age { get; set; }
+        return Name;
+    }
 
-        public Type TypeProperty { get; set; } = typeof(Person);
+    protected bool Equals(Person other)
+    {
+        return Name == other.Name;
+    }
 
-        public override string ToString()
+    public override bool Equals(object obj)
+    {
+        if (ReferenceEquals(null, obj))
         {
-            return Name;
+            return false;
         }
 
-        protected bool Equals(Person other)
+        if (ReferenceEquals(this, obj))
         {
-            return Name == other.Name;
+            return true;
         }
 
-        public override bool Equals(object obj)
+        if (obj.GetType() != GetType())
         {
-            if (ReferenceEquals(null, obj))
-            {
-                return false;
-            }
-
-            if (ReferenceEquals(this, obj))
-            {
-                return true;
-            }
-
-            if (obj.GetType() != GetType())
-            {
-                return false;
-            }
-
-            return Equals((Person) obj);
+            return false;
         }
 
-        public override int GetHashCode()
-        {
-            return (Name != null ? Name.GetHashCode() : 0);
-        }
+        return Equals((Person) obj);
+    }
+
+    public override int GetHashCode()
+    {
+        return (Name != null ? Name.GetHashCode() : 0);
     }
-}
+}

+ 18 - 19
Jint.Tests/Runtime/Domain/Thrower.cs

@@ -1,25 +1,24 @@
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class Thrower
 {
-    public class Thrower
+    public void ThrowArgumentNullException()
     {
-        public void ThrowArgumentNullException()
-        {
-            throw new ArgumentNullException();
-        }
+        throw new ArgumentNullException();
+    }
 
-        public void ThrowExceptionWithMessage(string message)
-        {
-            throw new Exception(message);
-        }
+    public void ThrowExceptionWithMessage(string message)
+    {
+        throw new Exception(message);
+    }
 
-        public void ThrowNotSupportedException()
-        {
-            throw new NotSupportedException();
-        }
+    public void ThrowNotSupportedException()
+    {
+        throw new NotSupportedException();
+    }
 
-        public void ThrowNotSupportedExceptionWithMessage(string message)
-        {
-            throw new NotSupportedException(message);
-        }
+    public void ThrowNotSupportedExceptionWithMessage(string message)
+    {
+        throw new NotSupportedException(message);
     }
-}
+}

+ 43 - 44
Jint.Tests/Runtime/Domain/UuidConstructor.cs

@@ -4,65 +4,64 @@ using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+internal sealed class UuidConstructor : Constructor
 {
-    internal sealed class UuidConstructor : Constructor
-    {
-        private static readonly JsString _functionName = new JsString("Uuid");
+    private static readonly JsString _functionName = new JsString("Uuid");
 
-        private UuidConstructor(Engine engine) : base(engine, engine.Realm, _functionName)
-        {
-        }
+    private UuidConstructor(Engine engine) : base(engine, engine.Realm, _functionName)
+    {
+    }
 
-        private JsValue Parse(JsValue @this, JsValue[] arguments)
+    private JsValue Parse(JsValue @this, JsValue[] arguments)
+    {
+        switch (arguments.At(0))
         {
-            switch (arguments.At(0))
-            {
-                case JsUuid uid:
-                    return Construct(uid);
+            case JsUuid uid:
+                return Construct(uid);
 
-                case JsValue js when Guid.TryParse(js.AsString(), out var res):
-                    return Construct(res);
-            }
-
-            return Undefined;
+            case JsValue js when Guid.TryParse(js.AsString(), out var res):
+                return Construct(res);
         }
 
-        protected internal override ObjectInstance GetPrototypeOf() => _prototype;
+        return Undefined;
+    }
+
+    protected internal override ObjectInstance GetPrototypeOf() => _prototype;
 
-        internal new ObjectInstance _prototype;
+    internal new ObjectInstance _prototype;
 
-        public UuidPrototype PrototypeObject { get; private set; }
+    public UuidPrototype PrototypeObject { get; private set; }
 
-        public static UuidConstructor CreateUuidConstructor(Engine engine)
+    public static UuidConstructor CreateUuidConstructor(Engine engine)
+    {
+        var obj = new UuidConstructor(engine)
         {
-            var obj = new UuidConstructor(engine)
-            {
-                // The value of the [[Prototype]] internal property of the Uuid constructor is the Function prototype object
-                _prototype = engine.Realm.Intrinsics.Function.PrototypeObject
-            };
-            obj.PrototypeObject = UuidPrototype.CreatePrototypeObject(engine, obj);
+            // The value of the [[Prototype]] internal property of the Uuid constructor is the Function prototype object
+            _prototype = engine.Realm.Intrinsics.Function.PrototypeObject
+        };
+        obj.PrototypeObject = UuidPrototype.CreatePrototypeObject(engine, obj);
 
-            // The initial value of Uuid.prototype is the Date prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, false, false, false));
+        // The initial value of Uuid.prototype is the Date prototype object
+        obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, false, false, false));
 
-            engine.SetValue("Uuid", obj);
-            obj.Configure();
-            obj.PrototypeObject.Configure();
+        engine.SetValue("Uuid", obj);
+        obj.Configure();
+        obj.PrototypeObject.Configure();
 
-            return obj;
-        }
+        return obj;
+    }
 
-        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments) => Construct(arguments, null);
+    protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments) => Construct(arguments, null);
 
-        public void Configure()
-        {
-            FastSetProperty("parse", new PropertyDescriptor(new ClrFunction(Engine, "parse", Parse), true, false, true));
-            FastSetProperty("Empty", new PropertyDescriptor(JsUuid.Empty, true, false, true));
-        }
+    public void Configure()
+    {
+        FastSetProperty("parse", new PropertyDescriptor(new ClrFunction(Engine, "parse", Parse), true, false, true));
+        FastSetProperty("Empty", new PropertyDescriptor(JsUuid.Empty, true, false, true));
+    }
 
-        public UuidInstance Construct(JsUuid uuid) => new UuidInstance(Engine) { PrimitiveValue = uuid, _prototype = PrototypeObject };
+    public UuidInstance Construct(JsUuid uuid) => new UuidInstance(Engine) { PrimitiveValue = uuid, _prototype = PrototypeObject };
 
-        public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget) => Construct(Guid.NewGuid());
-    }
-}
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget) => Construct(Guid.NewGuid());
+}

+ 15 - 16
Jint.Tests/Runtime/Domain/UuidConverter.cs

@@ -1,25 +1,24 @@
 using Jint.Native;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+public class UuidConverter : IObjectConverter
 {
-    public class UuidConverter : IObjectConverter
+    internal UuidConverter()
     {
-        internal UuidConverter()
-        {
-        }
+    }
 
-        public bool TryConvert(Engine engine, object value, out JsValue result)
+    public bool TryConvert(Engine engine, object value, out JsValue result)
+    {
+        switch (value)
         {
-            switch (value)
-            {
-                case Guid g:
-                    result = new JsUuid(g);
-                    return true;
-            }
-
-            result = JsValue.Undefined;
-            return false;
+            case Guid g:
+                result = new JsUuid(g);
+                return true;
         }
+
+        result = JsValue.Undefined;
+        return false;
     }
-}
+}

+ 10 - 11
Jint.Tests/Runtime/Domain/UuidInstance.cs

@@ -1,20 +1,19 @@
 using Jint.Native.Object;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+internal class UuidInstance : ObjectInstance, IObjectWrapper
 {
-    internal class UuidInstance : ObjectInstance, IObjectWrapper
-    {
-        protected internal override ObjectInstance GetPrototypeOf() => _prototype;
+    protected internal override ObjectInstance GetPrototypeOf() => _prototype;
 
-        internal new ObjectInstance _prototype;
+    internal new ObjectInstance _prototype;
 
-        public JsUuid PrimitiveValue { get; set; }
+    public JsUuid PrimitiveValue { get; set; }
 
-        public object Target => PrimitiveValue?._value;
+    public object Target => PrimitiveValue?._value;
 
-        public UuidInstance(Engine engine) : base(engine)
-        {
-        }
+    public UuidInstance(Engine engine) : base(engine)
+    {
     }
-}
+}

+ 25 - 26
Jint.Tests/Runtime/Domain/UuidPrototype.cs

@@ -3,40 +3,39 @@ using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain;
+
+internal sealed class UuidPrototype : UuidInstance
 {
-    internal sealed class UuidPrototype : UuidInstance
+    private UuidPrototype(Engine engine) : base(engine)
     {
-        private UuidPrototype(Engine engine) : base(engine)
-        {
-        }
+    }
 
-        private UuidInstance EnsureUuidInstance(JsValue thisObject)
-        {
-            return thisObject.TryCast<UuidInstance>(value => throw new JavaScriptException(Engine.Realm.Intrinsics.TypeError, "Invalid Uuid"));
-        }
+    private UuidInstance EnsureUuidInstance(JsValue thisObject)
+    {
+        return thisObject.TryCast<UuidInstance>(value => throw new JavaScriptException(Engine.Realm.Intrinsics.TypeError, "Invalid Uuid"));
+    }
 
-        private JsValue ToGuidString(JsValue thisObject, JsValue[] arguments) => EnsureUuidInstance(thisObject).PrimitiveValue.ToString();
+    private JsValue ToGuidString(JsValue thisObject, JsValue[] arguments) => EnsureUuidInstance(thisObject).PrimitiveValue.ToString();
 
-        private JsValue ValueOf(JsValue thisObject, JsValue[] arguments) => EnsureUuidInstance(thisObject).PrimitiveValue;
+    private JsValue ValueOf(JsValue thisObject, JsValue[] arguments) => EnsureUuidInstance(thisObject).PrimitiveValue;
 
-        public static UuidPrototype CreatePrototypeObject(Engine engine, UuidConstructor ctor)
+    public static UuidPrototype CreatePrototypeObject(Engine engine, UuidConstructor ctor)
+    {
+        var obj = new UuidPrototype(engine)
         {
-            var obj = new UuidPrototype(engine)
-            {
-                PrimitiveValue = JsUuid.Empty,
-                _prototype = engine.Realm.Intrinsics.Object.PrototypeObject,
-            };
+            PrimitiveValue = JsUuid.Empty,
+            _prototype = engine.Realm.Intrinsics.Object.PrototypeObject,
+        };
 
-            obj.FastSetProperty("constructor", new PropertyDescriptor(ctor, false, false, true));
+        obj.FastSetProperty("constructor", new PropertyDescriptor(ctor, false, false, true));
 
-            return obj;
-        }
+        return obj;
+    }
 
-        public void Configure()
-        {
-            FastSetProperty("toString", new PropertyDescriptor(new ClrFunction(Engine, "toString", ToGuidString), true, false, true));
-            FastSetProperty("valueOf", new PropertyDescriptor(new ClrFunction(Engine, "valueOf", ValueOf), true, false, true));
-        }
+    public void Configure()
+    {
+        FastSetProperty("toString", new PropertyDescriptor(new ClrFunction(Engine, "toString", ToGuidString), true, false, true));
+        FastSetProperty("valueOf", new PropertyDescriptor(new ClrFunction(Engine, "valueOf", ValueOf), true, false, true));
     }
-}
+}

文件差异内容过多而无法显示
+ 406 - 406
Jint.Tests/Runtime/EngineTests.cs


+ 268 - 269
Jint.Tests/Runtime/ErrorTests.cs

@@ -3,62 +3,62 @@ using Jint.Native;
 using Jint.Runtime;
 using Jint.Tests.Runtime.TestClasses;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class ErrorTests
 {
-    public class ErrorTests
+    [Fact]
+    public void CanReturnCorrectErrorMessageAndLocation1()
     {
-        [Fact]
-        public void CanReturnCorrectErrorMessageAndLocation1()
-        {
-            const string script = @"
+        const string script = @"
 var a = {};
 
 var b = a.user.name;
 ";
 
-            var engine = new Engine();
-            var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
-            Assert.Equal("Cannot read property 'name' of undefined", e.Message);
-            Assert.Equal(4, e.Location.Start.Line);
-            Assert.Equal(15, e.Location.Start.Column);
-        }
+        var engine = new Engine();
+        var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
+        Assert.Equal("Cannot read property 'name' of undefined", e.Message);
+        Assert.Equal(4, e.Location.Start.Line);
+        Assert.Equal(15, e.Location.Start.Column);
+    }
 
-        [Fact]
-        public void CanReturnCorrectErrorMessageAndLocation1WithoutReferencedName()
-        {
-            const string script = @"
+    [Fact]
+    public void CanReturnCorrectErrorMessageAndLocation1WithoutReferencedName()
+    {
+        const string script = @"
 var c = a(b().Length);
 ";
 
-            var engine = new Engine();
-            engine.SetValue("a", new Action<string>((_) => { }));
-            engine.SetValue("b", new Func<string>(() => null));
-            var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
-            Assert.Equal("Cannot read property 'Length' of null", e.Message);
-            Assert.Equal(2, e.Location.Start.Line);
-            Assert.Equal(14, e.Location.Start.Column);
-        }
+        var engine = new Engine();
+        engine.SetValue("a", new Action<string>((_) => { }));
+        engine.SetValue("b", new Func<string>(() => null));
+        var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
+        Assert.Equal("Cannot read property 'Length' of null", e.Message);
+        Assert.Equal(2, e.Location.Start.Line);
+        Assert.Equal(14, e.Location.Start.Column);
+    }
 
-        [Fact]
-        public void CanReturnCorrectErrorMessageAndLocation2()
-        {
-            const string script = @"
+    [Fact]
+    public void CanReturnCorrectErrorMessageAndLocation2()
+    {
+        const string script = @"
  test();
 ";
 
-            var engine = new Engine();
-            var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
-            Assert.Equal("test is not defined", e.Message);
-            Assert.Equal(2, e.Location.Start.Line);
-            Assert.Equal(1, e.Location.Start.Column);
-        }
+        var engine = new Engine();
+        var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
+        Assert.Equal("test is not defined", e.Message);
+        Assert.Equal(2, e.Location.Start.Line);
+        Assert.Equal(1, e.Location.Start.Column);
+    }
 
-        [Fact]
-        public void CanProduceCorrectStackTraceForInternalError()
-        {
-            var engine = new Engine();
+    [Fact]
+    public void CanProduceCorrectStackTraceForInternalError()
+    {
+        var engine = new Engine();
 
-            engine.Execute(@"
+        engine.Execute(@"
 var a = function(v) {
   return v.xxx.yyy;
 }
@@ -68,24 +68,24 @@ var b = function(v) {
 }
             ", "custom.js");
 
-            var e = Assert.Throws<JavaScriptException>(() => engine.Execute("var x = b(7);", "main.js"));
-            Assert.Equal("Cannot read property 'yyy' of undefined", e.Message);
-            Assert.Equal(3, e.Location.Start.Line);
-            Assert.Equal(15, e.Location.Start.Column);
-            Assert.Equal("custom.js", e.Location.SourceFile);
+        var e = Assert.Throws<JavaScriptException>(() => engine.Execute("var x = b(7);", "main.js"));
+        Assert.Equal("Cannot read property 'yyy' of undefined", e.Message);
+        Assert.Equal(3, e.Location.Start.Line);
+        Assert.Equal(15, e.Location.Start.Column);
+        Assert.Equal("custom.js", e.Location.SourceFile);
 
-            var stack = e.JavaScriptStackTrace;
-            EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:16
+        var stack = e.JavaScriptStackTrace;
+        EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:16
    at b (v) custom.js:7:10
    at main.js:1:9", stack);
-        }
+    }
 
-        [Fact]
-        public void CanProduceCorrectStackTraceForScriptError()
-        {
-            var engine = new Engine();
+    [Fact]
+    public void CanProduceCorrectStackTraceForScriptError()
+    {
+        var engine = new Engine();
 
-            engine.Execute(@"
+        engine.Execute(@"
 var a = function(v) {
   throw new Error('Error thrown from script');
 }
@@ -95,24 +95,24 @@ var b = function(v) {
 }
             ", "custom.js");
 
-            var e = Assert.Throws<JavaScriptException>(() => engine.Execute("var x = b(7);", "main.js"));
-            Assert.Equal("Error thrown from script", e.Message);
-            Assert.Equal(3, e.Location.Start.Line);
-            Assert.Equal(8, e.Location.Start.Column);
-            Assert.Equal("custom.js", e.Location.SourceFile);
+        var e = Assert.Throws<JavaScriptException>(() => engine.Execute("var x = b(7);", "main.js"));
+        Assert.Equal("Error thrown from script", e.Message);
+        Assert.Equal(3, e.Location.Start.Line);
+        Assert.Equal(8, e.Location.Start.Column);
+        Assert.Equal("custom.js", e.Location.SourceFile);
 
-            var stack = e.JavaScriptStackTrace;
-            EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:9
+        var stack = e.JavaScriptStackTrace;
+        EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:9
    at b (v) custom.js:7:10
    at main.js:1:9", stack);
-        }
+    }
 
-        [Fact]
-        public void ErrorObjectHasTheStackTraceImmediately()
-        {
-            var engine = new Engine();
+    [Fact]
+    public void ErrorObjectHasTheStackTraceImmediately()
+    {
+        var engine = new Engine();
 
-            engine.Execute(@"
+        engine.Execute(@"
 var a = function(v) {
   return Error().stack;
 }
@@ -122,20 +122,20 @@ var b = function(v) {
 }
             ", "custom.js");
 
-            var e = engine.Evaluate(@"b(7)", "main.js").AsString();
+        var e = engine.Evaluate(@"b(7)", "main.js").AsString();
 
-            var stack = e;
-            EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:10
+        var stack = e;
+        EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:10
    at b (v) custom.js:7:10
    at main.js:1:1", stack);
-        }
+    }
 
-        [Fact]
-        public void ThrownErrorObjectHasStackTraceInCatch()
-        {
-            var engine = new Engine();
+    [Fact]
+    public void ThrownErrorObjectHasStackTraceInCatch()
+    {
+        var engine = new Engine();
 
-            engine.Execute(@"
+        engine.Execute(@"
 var a = function(v) {
   try {
     throw Error();
@@ -149,21 +149,21 @@ var b = function(v) {
 }
             ", "custom.js");
 
-            var e = engine.Evaluate(@"b(7)", "main.js").AsString();
+        var e = engine.Evaluate(@"b(7)", "main.js").AsString();
 
-            var stack = e;
-            EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:4:11
+        var stack = e;
+        EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:4:11
    at b (v) custom.js:11:10
    at main.js:1:1", stack);
-        }
+    }
 
 
-        [Fact]
-        public void GeneratedErrorHasStackTraceInCatch()
-        {
-            var engine = new Engine();
+    [Fact]
+    public void GeneratedErrorHasStackTraceInCatch()
+    {
+        var engine = new Engine();
 
-            engine.Execute(@"
+        engine.Execute(@"
 var a = function(v) {
   try {
     var a = ''.xyz();
@@ -177,52 +177,52 @@ var b = function(v) {
 }
             ", "custom.js");
 
-            var e = engine.Evaluate(@"b(7)", "main.js").AsString();
+        var e = engine.Evaluate(@"b(7)", "main.js").AsString();
 
-            var stack = e;
-            EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:4:13
+        var stack = e;
+        EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:4:13
    at b (v) custom.js:11:10
    at main.js:1:1", stack);
-        }
+    }
 
-        [Fact]
-        public void ErrorObjectHasOwnPropertyStack()
-        {
-            var res = new Engine().Evaluate(@"Error().hasOwnProperty('stack')").AsBoolean();
-            Assert.True(res);
-        }
+    [Fact]
+    public void ErrorObjectHasOwnPropertyStack()
+    {
+        var res = new Engine().Evaluate(@"Error().hasOwnProperty('stack')").AsBoolean();
+        Assert.True(res);
+    }
 
-        private class Folder
-        {
-            public Folder Parent { get; set; }
-            public string Name { get; set; }
-        }
+    private class Folder
+    {
+        public Folder Parent { get; set; }
+        public string Name { get; set; }
+    }
 
-        [Fact]
-        public void CallStackBuildingShouldSkipResolvingFromEngine()
-        {
-            var engine = new Engine(o => o.LimitRecursion(200));
-            var recordedFolderTraversalOrder = new List<string>();
-            engine.SetValue("log", new Action<object>(o => recordedFolderTraversalOrder.Add(o.ToString())));
+    [Fact]
+    public void CallStackBuildingShouldSkipResolvingFromEngine()
+    {
+        var engine = new Engine(o => o.LimitRecursion(200));
+        var recordedFolderTraversalOrder = new List<string>();
+        engine.SetValue("log", new Action<object>(o => recordedFolderTraversalOrder.Add(o.ToString())));
 
-            var folder = new Folder
+        var folder = new Folder
+        {
+            Name = "SubFolder2",
+            Parent = new Folder
             {
-                Name = "SubFolder2",
+                Name = "SubFolder1",
                 Parent = new Folder
                 {
-                    Name = "SubFolder1",
-                    Parent = new Folder
-                    {
-                        Name = "Root",
-                        Parent = null,
-                    }
+                    Name = "Root",
+                    Parent = null,
                 }
-            };
+            }
+        };
 
-            engine.SetValue("folder", folder);
+        engine.SetValue("folder", folder);
 
-            var javaScriptException = Assert.Throws<JavaScriptException>(() =>
-                engine.Execute(@"
+        var javaScriptException = Assert.Throws<JavaScriptException>(() =>
+            engine.Execute(@"
                 var Test = {
                     recursive: function(folderInstance) {
                         // Enabling the guard here corrects the problem, but hides the hard fault
@@ -234,27 +234,27 @@ var b = function(v) {
                 }
 
                 Test.recursive(folder);"
-                ));
+            ));
 
-            Assert.Equal("Cannot read property 'Name' of null", javaScriptException.Message);
-            EqualIgnoringNewLineDifferences(@"   at recursive (folderInstance) <anonymous>:6:44
+        Assert.Equal("Cannot read property 'Name' of null", javaScriptException.Message);
+        EqualIgnoringNewLineDifferences(@"   at recursive (folderInstance) <anonymous>:6:44
    at recursive (folderInstance) <anonymous>:8:32
    at recursive (folderInstance) <anonymous>:8:32
    at recursive (folderInstance) <anonymous>:8:32
    at <anonymous>:12:17", javaScriptException.JavaScriptStackTrace);
 
-            var expected = new List<string>
-            {
-                "SubFolder2", "SubFolder1", "Root"
-            };
-            Assert.Equal(expected, recordedFolderTraversalOrder);
-        }
-
-        [Fact]
-        public void StackTraceCollectedOnThreeLevels()
+        var expected = new List<string>
         {
-            var engine = new Engine();
-            const string script = @"var a = function(v) {
+            "SubFolder2", "SubFolder1", "Root"
+        };
+        Assert.Equal(expected, recordedFolderTraversalOrder);
+    }
+
+    [Fact]
+    public void StackTraceCollectedOnThreeLevels()
+    {
+        var engine = new Engine();
+        const string script = @"var a = function(v) {
     return v.xxx.yyy;
 }
 
@@ -264,23 +264,23 @@ var b = function(v) {
 
 var x = b(7);";
 
-            var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
+        var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
 
-            const string expected = @"Error: Cannot read property 'yyy' of undefined
+        const string expected = @"Error: Cannot read property 'yyy' of undefined
    at a (v) <anonymous>:2:18
    at b (v) <anonymous>:6:12
    at <anonymous>:9:9";
 
-            EqualIgnoringNewLineDifferences(expected, ex.GetJavaScriptErrorString());
-            Assert.Equal(2, ex.Location.Start.Line);
-            Assert.Equal(17, ex.Location.Start.Column);
-        }
+        EqualIgnoringNewLineDifferences(expected, ex.GetJavaScriptErrorString());
+        Assert.Equal(2, ex.Location.Start.Line);
+        Assert.Equal(17, ex.Location.Start.Column);
+    }
 
-        [Fact]
-        public void StackTraceCollectedForImmediatelyInvokedFunctionExpression()
-        {
-            var engine = new Engine();
-            const string script = @"function getItem(items, itemIndex) {
+    [Fact]
+    public void StackTraceCollectedForImmediatelyInvokedFunctionExpression()
+    {
+        var engine = new Engine();
+        const string script = @"function getItem(items, itemIndex) {
     var item = items[itemIndex];
 
     return item;
@@ -294,32 +294,32 @@ var x = b(7);";
     return item;
 })(getItem);";
 
-            var parsingOptions = new ScriptParsingOptions
-            {
-                CompileRegex = false,
-                Tolerant = true
-            };
-            var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script, "get-item.js", parsingOptions));
+        var parsingOptions = new ScriptParsingOptions
+        {
+            CompileRegex = false,
+            Tolerant = true
+        };
+        var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script, "get-item.js", parsingOptions));
 
-            const string expected = @"Error: Cannot read property '5' of null
+        const string expected = @"Error: Cannot read property '5' of null
    at getItem (items, itemIndex) get-item.js:2:22
    at (anonymous) (getItem) get-item.js:9:16
    at get-item.js:13:2";
 
-            EqualIgnoringNewLineDifferences(expected, ex.GetJavaScriptErrorString());
+        EqualIgnoringNewLineDifferences(expected, ex.GetJavaScriptErrorString());
 
-            Assert.Equal(2, ex.Location.Start.Line);
-            Assert.Equal(21, ex.Location.Start.Column);
-        }
+        Assert.Equal(2, ex.Location.Start.Line);
+        Assert.Equal(21, ex.Location.Start.Column);
+    }
 
-        // Verify #1202
-        [Fact]
-        public void StackIsUnwoundWhenExceptionHandledByInteropCode()
-        {
-            var engine = new Engine()
-                .SetValue("handle", new Action<Action>(Handler));
+    // Verify #1202
+    [Fact]
+    public void StackIsUnwoundWhenExceptionHandledByInteropCode()
+    {
+        var engine = new Engine()
+            .SetValue("handle", new Action<Action>(Handler));
 
-            const string Script = @"
+        const string Script = @"
 function throwIt(message) {
     throw new Error(message);
 }
@@ -334,135 +334,135 @@ try {
     x.stack; // return stack trace string
 }
 ";
-            var stack = engine.Evaluate(Script).AsString();
-            EqualIgnoringNewLineDifferences(@"   at throwIt (message) <anonymous>:3:11
+        var stack = engine.Evaluate(Script).AsString();
+        EqualIgnoringNewLineDifferences(@"   at throwIt (message) <anonymous>:3:11
    at <anonymous>:11:5", stack);
 
-            static void Handler(Action callback)
+        static void Handler(Action callback)
+        {
+            try
             {
-                try
-                {
-                    callback();
-                }
-                catch (JavaScriptException)
-                {
-                    // handle JS error
-                }
+                callback();
+            }
+            catch (JavaScriptException)
+            {
+                // handle JS error
             }
         }
+    }
 
-        [Fact]
-        public void StackTraceIsForOriginalException()
-        {
-            var engine = new Engine();
-            engine.SetValue("HelloWorld", new HelloWorld());
-            const string script = @"HelloWorld.ThrowException();";
+    [Fact]
+    public void StackTraceIsForOriginalException()
+    {
+        var engine = new Engine();
+        engine.SetValue("HelloWorld", new HelloWorld());
+        const string script = @"HelloWorld.ThrowException();";
 
-            var ex = Assert.Throws<DivideByZeroException>(() => engine.Execute(script));
+        var ex = Assert.Throws<DivideByZeroException>(() => engine.Execute(script));
 
-            const string expected = "HelloWorld";
+        const string expected = "HelloWorld";
 
-            ContainsIgnoringNewLineDifferences(expected, ex.ToString());
-        }
+        ContainsIgnoringNewLineDifferences(expected, ex.ToString());
+    }
+
+    [Theory]
+    [InlineData("Error")]
+    [InlineData("EvalError")]
+    [InlineData("RangeError")]
+    [InlineData("SyntaxError")]
+    [InlineData("TypeError")]
+    [InlineData("ReferenceError")]
+    public void ErrorsHaveCorrectConstructor(string type)
+    {
+        var engine = new Engine();
+        engine.Execute($"const o = new {type}();");
+        Assert.True(engine.Evaluate($"o.constructor === {type}").AsBoolean());
+        Assert.Equal(type, engine.Evaluate("o.constructor.name").AsString());
+    }
 
-        [Theory]
-        [InlineData("Error")]
-        [InlineData("EvalError")]
-        [InlineData("RangeError")]
-        [InlineData("SyntaxError")]
-        [InlineData("TypeError")]
-        [InlineData("ReferenceError")]
-        public void ErrorsHaveCorrectConstructor(string type)
+    [Fact]
+    public void CallStackWorksWithRecursiveCalls()
+    {
+        static ScriptParsingOptions CreateParsingOptions()
         {
-            var engine = new Engine();
-            engine.Execute($"const o = new {type}();");
-            Assert.True(engine.Evaluate($"o.constructor === {type}").AsBoolean());
-            Assert.Equal(type, engine.Evaluate("o.constructor.name").AsString());
+            return new ScriptParsingOptions
+            {
+                CompileRegex = false,
+                Tolerant = true
+            };
         }
 
-        [Fact]
-        public void CallStackWorksWithRecursiveCalls()
+        var e = Assert.Throws<JavaScriptException>(() =>
         {
-            static ScriptParsingOptions CreateParsingOptions()
-            {
-                return new ScriptParsingOptions
-                {
-                    CompileRegex = false,
-                    Tolerant = true
-                };
-            }
+            var engine = new Engine();
 
-            var e = Assert.Throws<JavaScriptException>(() =>
+            engine.SetValue("executeFile", (Action<string>) (path =>
             {
-                var engine = new Engine();
-
-                engine.SetValue("executeFile", (Action<string>) (path =>
+                var content = path switch
                 {
-                    var content = path switch
-                    {
-                        "first-file.js" => @"num = num * 3;
+                    "first-file.js" => @"num = num * 3;
 executeFile(""second-file.js"");",
-                        "second-file.js" => @"// Intentionally making a mistake in the variable name
+                    "second-file.js" => @"// Intentionally making a mistake in the variable name
 nuм -= 3;",
-                        _ => throw new FileNotFoundException($"File '{path}' not exist.", path)
-                    };
-                    engine.Execute(content, path, CreateParsingOptions());
-                }));
-                engine.Execute(
-                    @"var num = 5;
+                    _ => throw new FileNotFoundException($"File '{path}' not exist.", path)
+                };
+                engine.Execute(content, path, CreateParsingOptions());
+            }));
+            engine.Execute(
+                @"var num = 5;
 executeFile(""first-file.js"");",
-                    "main-file.js",
-                    CreateParsingOptions()
-                );
-            });
+                "main-file.js",
+                CreateParsingOptions()
+            );
+        });
 
-            Assert.Equal("nuм is not defined", e.Message);
+        Assert.Equal("nuм is not defined", e.Message);
 
-            const string Expected = @"   at delegate second-file.js:2:1
+        const string Expected = @"   at delegate second-file.js:2:1
    at delegate first-file.js:2:1
    at main-file.js:2:1";
-            EqualIgnoringNewLineDifferences(Expected, e.JavaScriptStackTrace);
-        }
+        EqualIgnoringNewLineDifferences(Expected, e.JavaScriptStackTrace);
+    }
 
-        [Fact]
-        public void ShouldReportCorrectColumn()
+    [Fact]
+    public void ShouldReportCorrectColumn()
+    {
+        var e = Assert.Throws<JavaScriptException>(() =>
         {
-            var e = Assert.Throws<JavaScriptException>(() =>
-            {
-                var engine = new Engine();
-                engine.Execute(@"var $variable1 = 611;
+            var engine = new Engine();
+            engine.Execute(@"var $variable1 = 611;
 var _variable2 = 711;
 var variable3 = 678;
 
 $variable1 + -variable2 - variable3;");
-            });
+        });
 
-            Assert.Equal(5, e.Location.Start.Line);
-            Assert.Equal(14, e.Location.Start.Column);
-            Assert.Equal("   at <anonymous>:5:15", e.JavaScriptStackTrace);
-        }
+        Assert.Equal(5, e.Location.Start.Line);
+        Assert.Equal(14, e.Location.Start.Column);
+        Assert.Equal("   at <anonymous>:5:15", e.JavaScriptStackTrace);
+    }
 
-        [Fact]
-        public void InvokingDelegateShouldContainJavascriptExceptionAsInnerException()
-        {
-            Delegate func = null;
-            void SetFuncValue(Delegate scriptFunc) => func = scriptFunc;
+    [Fact]
+    public void InvokingDelegateShouldContainJavascriptExceptionAsInnerException()
+    {
+        Delegate func = null;
+        void SetFuncValue(Delegate scriptFunc) => func = scriptFunc;
 
-            var engine = new Engine();
-            engine.SetValue("SetFuncValue", SetFuncValue);
-            engine.Execute("SetFuncValue(() => { foo.bar });");
+        var engine = new Engine();
+        engine.SetValue("SetFuncValue", SetFuncValue);
+        engine.Execute("SetFuncValue(() => { foo.bar });");
 
-            var ex = Assert.Throws<TargetInvocationException>(() => func?.DynamicInvoke(JsValue.Undefined, Array.Empty<JsValue>()));
+        var ex = Assert.Throws<TargetInvocationException>(() => func?.DynamicInvoke(JsValue.Undefined, Array.Empty<JsValue>()));
 
-            var exception = Assert.IsType<JavaScriptException>(ex.InnerException);
-            Assert.Equal("foo is not defined", exception.Message);
-        }
+        var exception = Assert.IsType<JavaScriptException>(ex.InnerException);
+        Assert.Equal("foo is not defined", exception.Message);
+    }
 
-        [Fact]
-        public void JavaScriptExceptionLocationOnModuleShouldBeRight()
-        {
-            var engine = new Engine();
-            engine.Modules.Add("my_module", @"
+    [Fact]
+    public void JavaScriptExceptionLocationOnModuleShouldBeRight()
+    {
+        var engine = new Engine();
+        engine.Modules.Add("my_module", @"
 function throw_error(){
     throw Error(""custom error"")
 }
@@ -470,23 +470,22 @@ function throw_error(){
 throw_error();
             ");
 
-            var ex= Assert.Throws<JavaScriptException>(() => engine.Modules.Import("my_module"));
-            Assert.Equal(ex.Location.Start.Line, 3);
-            Assert.Equal(ex.Location.Start.Column, 10);
-        }
+        var ex= Assert.Throws<JavaScriptException>(() => engine.Modules.Import("my_module"));
+        Assert.Equal(ex.Location.Start.Line, 3);
+        Assert.Equal(ex.Location.Start.Column, 10);
+    }
 
-        private static void EqualIgnoringNewLineDifferences(string expected, string actual)
-        {
-            expected = expected.Replace("\r\n", "\n");
-            actual = actual.Replace("\r\n", "\n");
-            Assert.Equal(expected, actual);
-        }
+    private static void EqualIgnoringNewLineDifferences(string expected, string actual)
+    {
+        expected = expected.Replace("\r\n", "\n");
+        actual = actual.Replace("\r\n", "\n");
+        Assert.Equal(expected, actual);
+    }
 
-        private static void ContainsIgnoringNewLineDifferences(string expectedSubstring, string actualString)
-        {
-            expectedSubstring = expectedSubstring.Replace("\r\n", "\n");
-            actualString = actualString.Replace("\r\n", "\n");
-            Assert.Contains(expectedSubstring, actualString);
-        }
+    private static void ContainsIgnoringNewLineDifferences(string expectedSubstring, string actualString)
+    {
+        expectedSubstring = expectedSubstring.Replace("\r\n", "\n");
+        actualString = actualString.Replace("\r\n", "\n");
+        Assert.Contains(expectedSubstring, actualString);
     }
-}
+}

+ 213 - 214
Jint.Tests/Runtime/ExecutionConstraintTests.cs

@@ -1,53 +1,53 @@
 using Jint.Native.Function;
 using Jint.Runtime;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class ExecutionConstraintTests
 {
-    public class ExecutionConstraintTests
+    [Fact]
+    public void ShouldThrowStatementCountOverflow()
     {
-        [Fact]
-        public void ShouldThrowStatementCountOverflow()
-        {
-            Assert.Throws<StatementsCountOverflowException>(
-                () => new Engine(cfg => cfg.MaxStatements(100)).Evaluate("while(true);")
-            );
-        }
+        Assert.Throws<StatementsCountOverflowException>(
+            () => new Engine(cfg => cfg.MaxStatements(100)).Evaluate("while(true);")
+        );
+    }
 
-        [Fact]
-        public void ShouldThrowMemoryLimitExceeded()
-        {
-            Assert.Throws<MemoryLimitExceededException>(
-                () => new Engine(cfg => cfg.LimitMemory(2048)).Evaluate("a=[]; while(true){ a.push(0); }")
-            );
-        }
+    [Fact]
+    public void ShouldThrowMemoryLimitExceeded()
+    {
+        Assert.Throws<MemoryLimitExceededException>(
+            () => new Engine(cfg => cfg.LimitMemory(2048)).Evaluate("a=[]; while(true){ a.push(0); }")
+        );
+    }
 
-        [Fact]
-        public void ShouldThrowTimeout()
-        {
-            Assert.Throws<TimeoutException>(
-                () => new Engine(cfg => cfg.TimeoutInterval(new TimeSpan(0, 0, 0, 0, 500))).Evaluate("while(true);")
-            );
-        }
+    [Fact]
+    public void ShouldThrowTimeout()
+    {
+        Assert.Throws<TimeoutException>(
+            () => new Engine(cfg => cfg.TimeoutInterval(new TimeSpan(0, 0, 0, 0, 500))).Evaluate("while(true);")
+        );
+    }
 
-        [Fact]
-        public void ShouldThrowExecutionCanceled()
-        {
-            Assert.Throws<ExecutionCanceledException>(
-                () =>
+    [Fact]
+    public void ShouldThrowExecutionCanceled()
+    {
+        Assert.Throws<ExecutionCanceledException>(
+            () =>
+            {
+                using (var tcs = new CancellationTokenSource())
+                using (var waitHandle = new ManualResetEvent(false))
                 {
-                    using (var tcs = new CancellationTokenSource())
-                    using (var waitHandle = new ManualResetEvent(false))
-                    {
-                        var engine = new Engine(cfg => cfg.CancellationToken(tcs.Token));
+                    var engine = new Engine(cfg => cfg.CancellationToken(tcs.Token));
 
-                        ThreadPool.QueueUserWorkItem(state =>
-                        {
-                            waitHandle.WaitOne();
-                            tcs.Cancel();
-                        });
+                    ThreadPool.QueueUserWorkItem(state =>
+                    {
+                        waitHandle.WaitOne();
+                        tcs.Cancel();
+                    });
 
-                        engine.SetValue("waitHandle", waitHandle);
-                        engine.Evaluate(@"
+                    engine.SetValue("waitHandle", waitHandle);
+                    engine.Evaluate(@"
                             function sleep(millisecondsTimeout) {
                                 var totalMilliseconds = new Date().getTime() + millisecondsTimeout;
 
@@ -62,15 +62,15 @@ namespace Jint.Tests.Runtime
                             sleep(1000);
                             sleep(1000);
                         ");
-                    }
                 }
-            );
-        }
+            }
+        );
+    }
 
-        [Fact]
-        public void CanDiscardRecursion()
-        {
-            var script = @"var factorial = function(n) {
+    [Fact]
+    public void CanDiscardRecursion()
+    {
+        var script = @"var factorial = function(n) {
                 if (n>1) {
                     return n * factorial(n - 1);
                 }
@@ -79,15 +79,15 @@ namespace Jint.Tests.Runtime
             var result = factorial(500);
             ";
 
-            Assert.Throws<RecursionDepthOverflowException>(
-                () => new Engine(cfg => cfg.LimitRecursion()).Execute(script)
-            );
-        }
+        Assert.Throws<RecursionDepthOverflowException>(
+            () => new Engine(cfg => cfg.LimitRecursion()).Execute(script)
+        );
+    }
 
-        [Fact]
-        public void ShouldDiscardHiddenRecursion()
-        {
-            var script = @"var renamedFunc;
+    [Fact]
+    public void ShouldDiscardHiddenRecursion()
+    {
+        var script = @"var renamedFunc;
             var exec = function(callback) {
                 renamedFunc = callback;
                 callback();
@@ -98,15 +98,15 @@ namespace Jint.Tests.Runtime
             });
             ";
 
-            Assert.Throws<RecursionDepthOverflowException>(
-                () => new Engine(cfg => cfg.LimitRecursion()).Execute(script)
-            );
-        }
+        Assert.Throws<RecursionDepthOverflowException>(
+            () => new Engine(cfg => cfg.LimitRecursion()).Execute(script)
+        );
+    }
 
-        [Fact]
-        public void ShouldRecognizeAndDiscardChainedRecursion()
-        {
-            var script = @" var funcRoot, funcA, funcB, funcC, funcD;
+    [Fact]
+    public void ShouldRecognizeAndDiscardChainedRecursion()
+    {
+        var script = @" var funcRoot, funcA, funcB, funcC, funcD;
 
             var funcRoot = function() {
                 funcA();
@@ -131,15 +131,15 @@ namespace Jint.Tests.Runtime
             funcRoot();
             ";
 
-            Assert.Throws<RecursionDepthOverflowException>(
-                () => new Engine(cfg => cfg.LimitRecursion()).Execute(script)
-            );
-        }
+        Assert.Throws<RecursionDepthOverflowException>(
+            () => new Engine(cfg => cfg.LimitRecursion()).Execute(script)
+        );
+    }
 
-        [Fact]
-        public void ShouldProvideCallChainWhenDiscardRecursion()
-        {
-            var script = @" var funcRoot, funcA, funcB, funcC, funcD;
+    [Fact]
+    public void ShouldProvideCallChainWhenDiscardRecursion()
+    {
+        var script = @" var funcRoot, funcA, funcB, funcC, funcD;
 
             var funcRoot = function() {
                 funcA();
@@ -164,26 +164,26 @@ namespace Jint.Tests.Runtime
             funcRoot();
             ";
 
-            RecursionDepthOverflowException exception = null;
+        RecursionDepthOverflowException exception = null;
 
-            try
-            {
-                new Engine(cfg => cfg.LimitRecursion()).Execute(script);
-            }
-            catch (RecursionDepthOverflowException ex)
-            {
-                exception = ex;
-            }
-
-            Assert.NotNull(exception);
-            Assert.Equal("funcRoot->funcA->funcB->funcC->funcD", exception.CallChain);
-            Assert.Equal("funcRoot", exception.CallExpressionReference);
+        try
+        {
+            new Engine(cfg => cfg.LimitRecursion()).Execute(script);
         }
-
-        [Fact]
-        public void ShouldAllowShallowRecursion()
+        catch (RecursionDepthOverflowException ex)
         {
-            var script = @"var factorial = function(n) {
+            exception = ex;
+        }
+
+        Assert.NotNull(exception);
+        Assert.Equal("funcRoot->funcA->funcB->funcC->funcD", exception.CallChain);
+        Assert.Equal("funcRoot", exception.CallExpressionReference);
+    }
+
+    [Fact]
+    public void ShouldAllowShallowRecursion()
+    {
+        var script = @"var factorial = function(n) {
                 if (n>1) {
                     return n * factorial(n - 1);
                 }
@@ -192,13 +192,13 @@ namespace Jint.Tests.Runtime
             var result = factorial(8);
             ";
 
-            new Engine(cfg => cfg.LimitRecursion(20)).Execute(script);
-        }
+        new Engine(cfg => cfg.LimitRecursion(20)).Execute(script);
+    }
 
-        [Fact]
-        public void ShouldDiscardDeepRecursion()
-        {
-            var script = @"var factorial = function(n) {
+    [Fact]
+    public void ShouldDiscardDeepRecursion()
+    {
+        var script = @"var factorial = function(n) {
                 if (n>1) {
                     return n * factorial(n - 1);
                 }
@@ -207,15 +207,15 @@ namespace Jint.Tests.Runtime
             var result = factorial(38);
             ";
 
-            Assert.Throws<RecursionDepthOverflowException>(
-                () => new Engine(cfg => cfg.LimitRecursion(20)).Execute(script)
-            );
-        }
+        Assert.Throws<RecursionDepthOverflowException>(
+            () => new Engine(cfg => cfg.LimitRecursion(20)).Execute(script)
+        );
+    }
 
-        [Fact]
-        public void ShouldAllowRecursionLimitWithoutReferencedName()
-        {
-            const string input = @"(function () {
+    [Fact]
+    public void ShouldAllowRecursionLimitWithoutReferencedName()
+    {
+        const string input = @"(function () {
                 var factorial = function(n) {
                     if (n>1) {
                         return n * factorial(n - 1);
@@ -226,21 +226,21 @@ namespace Jint.Tests.Runtime
             })();
             ";
 
-            var engine = new Engine(o => o.LimitRecursion(20));
-            Assert.Throws<RecursionDepthOverflowException>(() => engine.Execute(input));
-        }
+        var engine = new Engine(o => o.LimitRecursion(20));
+        Assert.Throws<RecursionDepthOverflowException>(() => engine.Execute(input));
+    }
 
-        [Fact]
-        public void ShouldLimitRecursionWithAllFunctionInstances()
+    [Fact]
+    public void ShouldLimitRecursionWithAllFunctionInstances()
+    {
+        var engine = new Engine(cfg =>
         {
-            var engine = new Engine(cfg =>
-            {
-                // Limit recursion to 5 invocations
-                cfg.LimitRecursion(5);
-                cfg.Strict();
-            });
+            // Limit recursion to 5 invocations
+            cfg.LimitRecursion(5);
+            cfg.Strict();
+        });
 
-            var ex = Assert.Throws<RecursionDepthOverflowException>(() => engine.Evaluate(@"
+        var ex = Assert.Throws<RecursionDepthOverflowException>(() => engine.Evaluate(@"
 var myarr = new Array(5000);
 for (var i = 0; i < myarr.length; i++) {
     myarr[i] = function(i) {
@@ -250,131 +250,130 @@ for (var i = 0; i < myarr.length; i++) {
 
 myarr[0](0);
 "));
-        }
+    }
 
-        [Fact]
-        public void ShouldLimitRecursionWithGetters()
-        {
-            const string code = @"var obj = { get test() { return this.test + '2';  } }; obj.test;";
-            var engine = new Engine(cfg => cfg.LimitRecursion(10));
+    [Fact]
+    public void ShouldLimitRecursionWithGetters()
+    {
+        const string code = @"var obj = { get test() { return this.test + '2';  } }; obj.test;";
+        var engine = new Engine(cfg => cfg.LimitRecursion(10));
 
-            Assert.Throws<RecursionDepthOverflowException>(() => engine.Evaluate(code));
-        }
+        Assert.Throws<RecursionDepthOverflowException>(() => engine.Evaluate(code));
+    }
 
-        [Fact]
-        public void ShouldLimitArraySizeForConcat()
-        {
-            var engine = new Engine(o => o.MaxStatements(1_000).MaxArraySize(1_000_000));
-            Assert.Throws<MemoryLimitExceededException>(() => engine.Evaluate("for (let a = [1, 2, 3];; a = a.concat(a)) ;"));
-        }
+    [Fact]
+    public void ShouldLimitArraySizeForConcat()
+    {
+        var engine = new Engine(o => o.MaxStatements(1_000).MaxArraySize(1_000_000));
+        Assert.Throws<MemoryLimitExceededException>(() => engine.Evaluate("for (let a = [1, 2, 3];; a = a.concat(a)) ;"));
+    }
 
-        [Fact]
-        public void ShouldLimitArraySizeForFill()
-        {
-            var engine = new Engine(o => o.MaxStatements(1_000).MaxArraySize(1_000_000));
-            Assert.Throws<MemoryLimitExceededException>(() => engine.Evaluate("var arr = Array(1000000000).fill(new Array(1000000000));"));
-        }
+    [Fact]
+    public void ShouldLimitArraySizeForFill()
+    {
+        var engine = new Engine(o => o.MaxStatements(1_000).MaxArraySize(1_000_000));
+        Assert.Throws<MemoryLimitExceededException>(() => engine.Evaluate("var arr = Array(1000000000).fill(new Array(1000000000));"));
+    }
 
-        [Fact]
-        public void ShouldLimitArraySizeForJoin()
-        {
-            var engine = new Engine(o => o.MaxStatements(1_000).MaxArraySize(1_000_000));
-            Assert.Throws<MemoryLimitExceededException>(() => engine.Evaluate("new Array(2147483647).join('*')"));
-        }
+    [Fact]
+    public void ShouldLimitArraySizeForJoin()
+    {
+        var engine = new Engine(o => o.MaxStatements(1_000).MaxArraySize(1_000_000));
+        Assert.Throws<MemoryLimitExceededException>(() => engine.Evaluate("new Array(2147483647).join('*')"));
+    }
 
-        [Fact]
-        public void ShouldConsiderConstraintsWhenCallingInvoke()
+    [Fact]
+    public void ShouldConsiderConstraintsWhenCallingInvoke()
+    {
+        var engine = new Engine(options =>
         {
-            var engine = new Engine(options =>
-            {
-                options.TimeoutInterval(TimeSpan.FromMilliseconds(100));
-            });
-            var myApi = new MyApi();
+            options.TimeoutInterval(TimeSpan.FromMilliseconds(100));
+        });
+        var myApi = new MyApi();
 
-            engine.SetValue("myApi", myApi);
-            engine.Execute("myApi.addEventListener('DataReceived', (data) => { myApi.log(data) })");
+        engine.SetValue("myApi", myApi);
+        engine.Execute("myApi.addEventListener('DataReceived', (data) => { myApi.log(data) })");
 
-            var dataReceivedCallbacks = myApi.Callbacks.Where(kvp => kvp.Key == "DataReceived");
-            foreach (var callback in dataReceivedCallbacks)
-            {
-                engine.Invoke(callback.Value, "Data Received #1");
-                Thread.Sleep(101);
-                engine.Invoke(callback.Value, "Data Received #2");
-            }
+        var dataReceivedCallbacks = myApi.Callbacks.Where(kvp => kvp.Key == "DataReceived");
+        foreach (var callback in dataReceivedCallbacks)
+        {
+            engine.Invoke(callback.Value, "Data Received #1");
+            Thread.Sleep(101);
+            engine.Invoke(callback.Value, "Data Received #2");
         }
+    }
 
-        [Fact]
-        public void ResetConstraints()
-        {
-            void ExecuteAction(Engine engine) => engine.Execute("recursion()");
-            void InvokeAction(Engine engine) => engine.Invoke("recursion");
+    [Fact]
+    public void ResetConstraints()
+    {
+        void ExecuteAction(Engine engine) => engine.Execute("recursion()");
+        void InvokeAction(Engine engine) => engine.Invoke("recursion");
 
-            List<int> expected = [6, 6, 6, 6, 6];
-            Assert.Equal(expected, RunLoop(CreateEngine(), ExecuteAction));
-            Assert.Equal(expected, RunLoop(CreateEngine(), InvokeAction));
+        List<int> expected = [6, 6, 6, 6, 6];
+        Assert.Equal(expected, RunLoop(CreateEngine(), ExecuteAction));
+        Assert.Equal(expected, RunLoop(CreateEngine(), InvokeAction));
 
-            var e1 = CreateEngine();
-            Assert.Equal(expected, RunLoop(e1, ExecuteAction));
-            Assert.Equal(expected, RunLoop(e1, InvokeAction));
+        var e1 = CreateEngine();
+        Assert.Equal(expected, RunLoop(e1, ExecuteAction));
+        Assert.Equal(expected, RunLoop(e1, InvokeAction));
 
-            var e2 = CreateEngine();
-            Assert.Equal(expected, RunLoop(e2, InvokeAction));
-            Assert.Equal(expected, RunLoop(e2, ExecuteAction));
+        var e2 = CreateEngine();
+        Assert.Equal(expected, RunLoop(e2, InvokeAction));
+        Assert.Equal(expected, RunLoop(e2, ExecuteAction));
 
-            var e3 = CreateEngine();
-            Assert.Equal(expected, RunLoop(e3, InvokeAction));
-            Assert.Equal(expected, RunLoop(e3, ExecuteAction));
-            Assert.Equal(expected, RunLoop(e3, InvokeAction));
+        var e3 = CreateEngine();
+        Assert.Equal(expected, RunLoop(e3, InvokeAction));
+        Assert.Equal(expected, RunLoop(e3, ExecuteAction));
+        Assert.Equal(expected, RunLoop(e3, InvokeAction));
 
-            var e4 = CreateEngine();
-            Assert.Equal(expected, RunLoop(e4, InvokeAction));
-            Assert.Equal(expected, RunLoop(e4, InvokeAction));
-        }
+        var e4 = CreateEngine();
+        Assert.Equal(expected, RunLoop(e4, InvokeAction));
+        Assert.Equal(expected, RunLoop(e4, InvokeAction));
+    }
 
-        private static Engine CreateEngine()
-        {
-            Engine engine = new(options => options.LimitRecursion(5));
-            return engine.Execute("""
-                  var num = 0;
-                  function recursion() {
-                      num++;
-                      recursion(num);
-                  }
-              """);
-        }
+    private static Engine CreateEngine()
+    {
+        Engine engine = new(options => options.LimitRecursion(5));
+        return engine.Execute("""
+                                  var num = 0;
+                                  function recursion() {
+                                      num++;
+                                      recursion(num);
+                                  }
+                              """);
+    }
 
-        private static List<int> RunLoop(Engine engine, Action<Engine> engineAction)
+    private static List<int> RunLoop(Engine engine, Action<Engine> engineAction)
+    {
+        List<int> results = new();
+        for (var i = 0; i < 5; i++)
         {
-            List<int> results = new();
-            for (var i = 0; i < 5; i++)
+            try
             {
-                try
-                {
-                    engine.SetValue("num", 0);
-                    engineAction.Invoke(engine);
-                }
-                catch (RecursionDepthOverflowException)
-                {
-                    results.Add((int) engine.GetValue("num").AsNumber());
-                }
+                engine.SetValue("num", 0);
+                engineAction.Invoke(engine);
+            }
+            catch (RecursionDepthOverflowException)
+            {
+                results.Add((int) engine.GetValue("num").AsNumber());
             }
-
-            return results;
         }
 
-        private class MyApi
-        {
-            public readonly Dictionary<string, ScriptFunction> Callbacks = new Dictionary<string, ScriptFunction>();
+        return results;
+    }
 
-            public void AddEventListener(string eventName, ScriptFunction callback)
-            {
-                Callbacks.Add(eventName, callback);
-            }
+    private class MyApi
+    {
+        public readonly Dictionary<string, ScriptFunction> Callbacks = new Dictionary<string, ScriptFunction>();
 
-            public void Log(string logMessage)
-            {
-                Console.WriteLine(logMessage);
-            }
+        public void AddEventListener(string eventName, ScriptFunction callback)
+        {
+            Callbacks.Add(eventName, callback);
+        }
+
+        public void Log(string logMessage)
+        {
+            Console.WriteLine(logMessage);
         }
     }
-}
+}

+ 24 - 25
Jint.Tests/Runtime/ExtensionMethods/CustomStringExtensions.cs

@@ -1,35 +1,34 @@
 using System.Dynamic;
 using Newtonsoft.Json;
 
-namespace Jint.Tests.Runtime.ExtensionMethods
+namespace Jint.Tests.Runtime.ExtensionMethods;
+
+public static class CustomStringExtensions
 {
-    public static class CustomStringExtensions
+    public static string Backwards(this string value)
     {
-        public static string Backwards(this string value)
-        {
-            return new string(value.Reverse().ToArray());
-        }
+        return new string(value.Reverse().ToArray());
+    }
 
-        public static T DeserializeObject<T>(this string json)
-        {
-            return JsonConvert.DeserializeObject<T>(json);
-        }
+    public static T DeserializeObject<T>(this string json)
+    {
+        return JsonConvert.DeserializeObject<T>(json);
+    }
 
-        public static ExpandoObject DeserializeObject(this string json)
-        {
-            return DeserializeObject<ExpandoObject>(json);
-        }
+    public static ExpandoObject DeserializeObject(this string json)
+    {
+        return DeserializeObject<ExpandoObject>(json);
+    }
 
-        public static string[] Split(this string value, string split, StringSplitOptions options)
-        {
-            return Array.Empty<string>();
-        }
+    public static string[] Split(this string value, string split, StringSplitOptions options)
+    {
+        return Array.Empty<string>();
+    }
 
-        public static string[] Split(this string value, int position)
-        {
-            var first = value.Substring(0, position);
-            var second = value.Substring(position);
-            return new string[] { first, second };
-        }
+    public static string[] Split(this string value, int position)
+    {
+        var first = value.Substring(0, position);
+        var second = value.Substring(position);
+        return new string[] { first, second };
     }
-}
+}

+ 6 - 7
Jint.Tests/Runtime/ExtensionMethods/DoubleExtensions.cs

@@ -1,10 +1,9 @@
-namespace Jint.Tests.Runtime.ExtensionMethods
+namespace Jint.Tests.Runtime.ExtensionMethods;
+
+public static class DoubleExtensions
 {
-    public static class DoubleExtensions
+    public static double Add(this double integer, int add)
     {
-        public static double Add(this double integer, int add)
-        {
-            return integer + add;
-        }
+        return integer + add;
     }
-}
+}

+ 208 - 209
Jint.Tests/Runtime/ExtensionMethods/ExtensionMethodsTest.cs

@@ -1,134 +1,134 @@
 using Jint.Native;
 using Jint.Tests.Runtime.Domain;
 
-namespace Jint.Tests.Runtime.ExtensionMethods
+namespace Jint.Tests.Runtime.ExtensionMethods;
+
+public class ExtensionMethodsTest
 {
-    public class ExtensionMethodsTest
+    [Fact]
+    public void ShouldInvokeObjectExtensionMethod()
     {
-        [Fact]
-        public void ShouldInvokeObjectExtensionMethod()
-        {
-            var person = new Person();
-            person.Name = "Mickey Mouse";
-            person.Age = 35;
+        var person = new Person();
+        person.Name = "Mickey Mouse";
+        person.Age = 35;
 
-            var options = new Options();
-            options.AddExtensionMethods(typeof(PersonExtensions));
+        var options = new Options();
+        options.AddExtensionMethods(typeof(PersonExtensions));
 
-            var engine = new Engine(options);
-            engine.SetValue("person", person);
-            var age = engine.Evaluate("person.MultiplyAge(2)").AsInteger();
+        var engine = new Engine(options);
+        engine.SetValue("person", person);
+        var age = engine.Evaluate("person.MultiplyAge(2)").AsInteger();
 
-            Assert.Equal(70, age);
-        }
+        Assert.Equal(70, age);
+    }
 
-        [Fact]
-        public void ShouldInvokeStringExtensionMethod()
-        {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(CustomStringExtensions));
+    [Fact]
+    public void ShouldInvokeStringExtensionMethod()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(CustomStringExtensions));
 
-            var engine = new Engine(options);
-            var result = engine.Evaluate("\"Hello World!\".Backwards()").AsString();
+        var engine = new Engine(options);
+        var result = engine.Evaluate("\"Hello World!\".Backwards()").AsString();
 
-            Assert.Equal("!dlroW olleH", result);
-        }
+        Assert.Equal("!dlroW olleH", result);
+    }
 
-        [Fact]
-        public void ShouldInvokeNumberExtensionMethod()
-        {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(DoubleExtensions));
+    [Fact]
+    public void ShouldInvokeNumberExtensionMethod()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(DoubleExtensions));
 
-            var engine = new Engine(options);
-            var result = engine.Evaluate("let numb = 27; numb.Add(13)").AsInteger();
+        var engine = new Engine(options);
+        var result = engine.Evaluate("let numb = 27; numb.Add(13)").AsInteger();
 
-            Assert.Equal(40, result);
-        }
+        Assert.Equal(40, result);
+    }
 
-        [Fact]
-        public void ShouldPrioritizingNonGenericMethod()
-        {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(CustomStringExtensions));
+    [Fact]
+    public void ShouldPrioritizingNonGenericMethod()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(CustomStringExtensions));
 
-            var engine = new Engine(options);
-            var result = engine.Evaluate("\"{'name':'Mickey'}\".DeserializeObject()").ToObject() as dynamic;
+        var engine = new Engine(options);
+        var result = engine.Evaluate("\"{'name':'Mickey'}\".DeserializeObject()").ToObject() as dynamic;
 
-            Assert.Equal("Mickey", result.name);
-        }
+        Assert.Equal("Mickey", result.name);
+    }
 
-        [Fact]
-        public void PrototypeFunctionsShouldNotBeOverridden()
+    [Fact]
+    public void PrototypeFunctionsShouldNotBeOverridden()
+    {
+        var engine = new Engine(opts =>
         {
-            var engine = new Engine(opts =>
-            {
-                opts.AddExtensionMethods(typeof(CustomStringExtensions));
-            });
-
-            //uses split function from StringPrototype
-            var arr = engine.Evaluate("'yes,no'.split(',')").AsArray();
-            Assert.Equal("yes", arr[0]);
-            Assert.Equal("no", arr[1]);
-
-            //uses split function from CustomStringExtensions
-            var arr2 = engine.Evaluate("'yes,no'.split(2)").AsArray();
-            Assert.Equal("ye", arr2[0]);
-            Assert.Equal("s,no", arr2[1]);
-        }
+            opts.AddExtensionMethods(typeof(CustomStringExtensions));
+        });
+
+        //uses split function from StringPrototype
+        var arr = engine.Evaluate("'yes,no'.split(',')").AsArray();
+        Assert.Equal("yes", arr[0]);
+        Assert.Equal("no", arr[1]);
+
+        //uses split function from CustomStringExtensions
+        var arr2 = engine.Evaluate("'yes,no'.split(2)").AsArray();
+        Assert.Equal("ye", arr2[0]);
+        Assert.Equal("s,no", arr2[1]);
+    }
 
-        [Fact]
-        public void OverridePrototypeFunctions()
+    [Fact]
+    public void OverridePrototypeFunctions()
+    {
+        var engine = new Engine(opts =>
         {
-            var engine = new Engine(opts =>
-            {
-                opts.AddExtensionMethods(typeof(OverrideStringPrototypeExtensions));
-            });
-
-            //uses the overridden split function from OverrideStringPrototypeExtensions
-            var arr = engine.Evaluate("'yes,no'.split(',')").AsArray();
-            Assert.Equal("YES", arr[0]);
-            Assert.Equal("NO", arr[1]);
-        }
+            opts.AddExtensionMethods(typeof(OverrideStringPrototypeExtensions));
+        });
 
-        [Fact]
-        public void HasOwnPropertyShouldWorkCorrectlyInPresenceOfExtensionMethods()
-        {
-            var person = new Person();
+        //uses the overridden split function from OverrideStringPrototypeExtensions
+        var arr = engine.Evaluate("'yes,no'.split(',')").AsArray();
+        Assert.Equal("YES", arr[0]);
+        Assert.Equal("NO", arr[1]);
+    }
 
-            var options = new Options();
-            options.AddExtensionMethods(typeof(PersonExtensions));
+    [Fact]
+    public void HasOwnPropertyShouldWorkCorrectlyInPresenceOfExtensionMethods()
+    {
+        var person = new Person();
 
-            var engine = new Engine(options);
-            engine.SetValue("person", person);
+        var options = new Options();
+        options.AddExtensionMethods(typeof(PersonExtensions));
 
-            var isBogusInPerson = engine.Evaluate("'bogus' in person").AsBoolean();
-            Assert.False(isBogusInPerson);
+        var engine = new Engine(options);
+        engine.SetValue("person", person);
 
-            var propertyValue = engine.Evaluate("person.bogus");
-            Assert.Equal(JsValue.Undefined, propertyValue);
-        }
+        var isBogusInPerson = engine.Evaluate("'bogus' in person").AsBoolean();
+        Assert.False(isBogusInPerson);
 
-        private Engine GetLinqEngine()
-        {
-            return new Engine(opts =>
-            {
-                opts.AddExtensionMethods(typeof(Enumerable));
-            });
-        }
+        var propertyValue = engine.Evaluate("person.bogus");
+        Assert.Equal(JsValue.Undefined, propertyValue);
+    }
 
-        [Fact]
-        public void LinqExtensionMethodWithoutGenericParameter()
+    private Engine GetLinqEngine()
+    {
+        return new Engine(opts =>
         {
-            var engine = GetLinqEngine();
-            var intList = new List<int>() { 0, 1, 2, 3 };
+            opts.AddExtensionMethods(typeof(Enumerable));
+        });
+    }
 
-            engine.SetValue("intList", intList);
-            var intSumRes = engine.Evaluate("intList.Sum()").AsNumber();
-            Assert.Equal(6, intSumRes);
-        }
+    [Fact]
+    public void LinqExtensionMethodWithoutGenericParameter()
+    {
+        var engine = GetLinqEngine();
+        var intList = new List<int>() { 0, 1, 2, 3 };
 
-        // TODO this fails due to double -> long assignment on FW
+        engine.SetValue("intList", intList);
+        var intSumRes = engine.Evaluate("intList.Sum()").AsNumber();
+        Assert.Equal(6, intSumRes);
+    }
+
+    // TODO this fails due to double -> long assignment on FW
 #if !NETFRAMEWORK
         [Fact]
         public void LinqExtensionMethodWithSingleGenericParameter()
@@ -142,35 +142,35 @@ namespace Jint.Tests.Runtime.ExtensionMethods
         }
 #endif
 
-        [Fact]
-        public void LinqExtensionMethodWithMultipleGenericParameters()
-        {
-            var engine = GetLinqEngine();
-            var stringList = new List<string>() { "working", "linq" };
-            engine.SetValue("stringList", stringList);
+    [Fact]
+    public void LinqExtensionMethodWithMultipleGenericParameters()
+    {
+        var engine = GetLinqEngine();
+        var stringList = new List<string>() { "working", "linq" };
+        engine.SetValue("stringList", stringList);
 
-            var stringRes = engine.Evaluate("stringList.Select((x) => x + 'a').ToArray().join()").AsString();
-            Assert.Equal("workinga,linqa", stringRes);
+        var stringRes = engine.Evaluate("stringList.Select((x) => x + 'a').ToArray().join()").AsString();
+        Assert.Equal("workinga,linqa", stringRes);
 
-            // The method ambiguity resolver is not so smart to choose the Select method with the correct number of parameters
-            // Thus, the following script will not work as expected.
-            // stringList.Select((x, i) => x + i).ToArray().join()
-        }
+        // The method ambiguity resolver is not so smart to choose the Select method with the correct number of parameters
+        // Thus, the following script will not work as expected.
+        // stringList.Select((x, i) => x + i).ToArray().join()
+    }
 
-        [Fact]
-        public void GenericTypeExtension()
-        {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(ObservableExtensions));
+    [Fact]
+    public void GenericTypeExtension()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(ObservableExtensions));
 
-            var engine = new Engine(options);
+        var engine = new Engine(options);
 
-            engine.SetValue("log", new System.Action<object>(System.Console.WriteLine));
+        engine.SetValue("log", new System.Action<object>(System.Console.WriteLine));
 
-            NameObservable observable = new NameObservable();
+        NameObservable observable = new NameObservable();
 
-            engine.SetValue("observable", observable);
-            engine.Evaluate(@"
+        engine.SetValue("observable", observable);
+        engine.Evaluate(@"
                 log('before');
                 observable.Subscribe((name) =>{
                     log('observable: subscribe: name: ' + name);
@@ -180,49 +180,49 @@ namespace Jint.Tests.Runtime.ExtensionMethods
                 log('after');
             ");
 
-            Assert.Equal("foobar", observable.Last);
-        }
+        Assert.Equal("foobar", observable.Last);
+    }
 
-        [Fact]
-        public void GenericExtensionMethodOnClosedGenericType()
-        {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(ObservableExtensions));
+    [Fact]
+    public void GenericExtensionMethodOnClosedGenericType()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(ObservableExtensions));
 
-            var engine = new Engine(options);
+        var engine = new Engine(options);
 
-            engine.SetValue("log", new System.Action<object>(System.Console.WriteLine));
+        engine.SetValue("log", new System.Action<object>(System.Console.WriteLine));
 
-            NameObservable observable = new NameObservable();
-            engine.SetValue("observable", observable);
-            var result = engine.Evaluate(@"
+        NameObservable observable = new NameObservable();
+        engine.SetValue("observable", observable);
+        var result = engine.Evaluate(@"
                 log('before calling Select');
                 var result = observable.Select('some text');
                 log('result: ' + result);
                 return result;
             ");
 
-            //System.Console.WriteLine("GenericExtensionMethodOnGenericType: result: " + result + " result.ToString(): " + result.ToString());
+        //System.Console.WriteLine("GenericExtensionMethodOnGenericType: result: " + result + " result.ToString(): " + result.ToString());
 
-            Assert.Equal("some text", result);
-        }
+        Assert.Equal("some text", result);
+    }
 
-        [Fact]
-        public void GenericExtensionMethodOnClosedGenericType2()
+    [Fact]
+    public void GenericExtensionMethodOnClosedGenericType2()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(ObservableExtensions));
+
+        var engine = new Engine(options);
+
+        NameObservable observable = new NameObservable();
+        observable.Where((text) =>
         {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(ObservableExtensions));
-
-            var engine = new Engine(options);
-
-            NameObservable observable = new NameObservable();
-            observable.Where((text) =>
-            {
-                System.Console.WriteLine("GenericExtensionMethodOnClosedGenericType2: NameObservable: Where: text: " + text);
-                return true;
-            });
-            engine.SetValue("observable", observable);
-            var result = engine.Evaluate(@"
+            System.Console.WriteLine("GenericExtensionMethodOnClosedGenericType2: NameObservable: Where: text: " + text);
+            return true;
+        });
+        engine.SetValue("observable", observable);
+        var result = engine.Evaluate(@"
                 var result = observable.Where(function(text){
                     return true;
                 });
@@ -232,27 +232,27 @@ namespace Jint.Tests.Runtime.ExtensionMethods
                 return result;
             ");
 
-            var nameObservableResult = result.ToObject() as NameObservable;
-            Assert.NotNull(nameObservableResult);
-            Assert.Equal("testing yo", nameObservableResult.Last);
-        }
+        var nameObservableResult = result.ToObject() as NameObservable;
+        Assert.NotNull(nameObservableResult);
+        Assert.Equal("testing yo", nameObservableResult.Last);
+    }
 
-        [Fact]
-        public void GenericExtensionMethodOnOpenGenericType()
+    [Fact]
+    public void GenericExtensionMethodOnOpenGenericType()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(ObservableExtensions));
+
+        var engine = new Engine(options);
+
+        BaseObservable<string> observable = new BaseObservable<string>();
+        observable.Where((text) =>
         {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(ObservableExtensions));
-
-            var engine = new Engine(options);
-
-            BaseObservable<string> observable = new BaseObservable<string>();
-            observable.Where((text) =>
-            {
-                System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: BaseObservable: Where: text: " + text);
-                return true;
-            });
-            engine.SetValue("observable", observable);
-            var result = engine.Evaluate(@"
+            System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: BaseObservable: Where: text: " + text);
+            return true;
+        });
+        engine.SetValue("observable", observable);
+        var result = engine.Evaluate(@"
                 var result = observable.Where(function(text){
                     return true;
                 });
@@ -263,26 +263,26 @@ namespace Jint.Tests.Runtime.ExtensionMethods
                 return result;
             ");
 
-            System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: result: " + result + " result.ToString(): " + result.ToString());
-            var baseObservableResult = result.ToObject() as BaseObservable<string>;
+        System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: result: " + result + " result.ToString(): " + result.ToString());
+        var baseObservableResult = result.ToObject() as BaseObservable<string>;
 
-            System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: baseObservableResult: " + baseObservableResult);
-            Assert.NotNull(baseObservableResult);
-            Assert.Equal("testing yo", baseObservableResult.Last);
-        }
+        System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: baseObservableResult: " + baseObservableResult);
+        Assert.NotNull(baseObservableResult);
+        Assert.Equal("testing yo", baseObservableResult.Last);
+    }
 
-        [Fact]
-        public void GenericExtensionMethodOnGenericTypeInstantiatedInJs()
-        {
-            var options = new Options();
-            options.AddExtensionMethods(typeof(ObservableExtensions));
+    [Fact]
+    public void GenericExtensionMethodOnGenericTypeInstantiatedInJs()
+    {
+        var options = new Options();
+        options.AddExtensionMethods(typeof(ObservableExtensions));
 
-            var engine = new Engine(options);
+        var engine = new Engine(options);
 
-            engine.SetValue("BaseObservable", typeof(BaseObservable<>));
-            engine.SetValue("ObservableFactory", typeof(ObservableFactory));
+        engine.SetValue("BaseObservable", typeof(BaseObservable<>));
+        engine.SetValue("ObservableFactory", typeof(ObservableFactory));
 
-            var result = engine.Evaluate(@"
+        var result = engine.Evaluate(@"
 
                 // you can't instantiate generic types in JS (without providing the types as arguments to the constructor) - i.e. not compatible with transpiled typescript
                 //const observable = new BaseObservable();
@@ -298,30 +298,29 @@ namespace Jint.Tests.Runtime.ExtensionMethods
                 return result;
             ");
 
-            var baseObservableResult = result.ToObject() as BaseObservable<bool>;
+        var baseObservableResult = result.ToObject() as BaseObservable<bool>;
 
-            System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: baseObservableResult: " + baseObservableResult);
-            Assert.NotNull(baseObservableResult);
-            Assert.Equal(false, baseObservableResult.Last);
-        }
+        System.Console.WriteLine("GenericExtensionMethodOnOpenGenericType: baseObservableResult: " + baseObservableResult);
+        Assert.NotNull(baseObservableResult);
+        Assert.Equal(false, baseObservableResult.Last);
+    }
 
-        [Fact]
-        public void CanProjectAndGroupWhenExpandoObjectWrappingDisabled()
+    [Fact]
+    public void CanProjectAndGroupWhenExpandoObjectWrappingDisabled()
+    {
+        var engine = new Engine(options =>
         {
-            var engine = new Engine(options =>
-            {
-                options.AllowClr().AddExtensionMethods(typeof(Enumerable));
-                // prevent ExpandoObject wrapping
-                options.Interop.CreateClrObject = null;
-            });
-            engine.Execute("var a = [ 2, 4 ];");
-
-            var selected = engine.Evaluate("JSON.stringify(a.Select(m => ({a:m,b:m})).ToArray());").AsString();
-            Assert.Equal("""[{"a":2,"b":2},{"a":4,"b":4}]""", selected);
-
-            var grouped1 = engine.Evaluate("a.GroupBy(m => ({a:m,b:m})).ToArray()").AsArray();
-            var grouped = engine.Evaluate("JSON.stringify(a.GroupBy(m => ({a:m,b:m})).Select(x => x.Key).ToArray());").AsString();
-            Assert.Equal("""[{"a":2,"b":2},{"a":4,"b":4}]""", grouped);
-        }
+            options.AllowClr().AddExtensionMethods(typeof(Enumerable));
+            // prevent ExpandoObject wrapping
+            options.Interop.CreateClrObject = null;
+        });
+        engine.Execute("var a = [ 2, 4 ];");
+
+        var selected = engine.Evaluate("JSON.stringify(a.Select(m => ({a:m,b:m})).ToArray());").AsString();
+        Assert.Equal("""[{"a":2,"b":2},{"a":4,"b":4}]""", selected);
+
+        var grouped1 = engine.Evaluate("a.GroupBy(m => ({a:m,b:m})).ToArray()").AsArray();
+        var grouped = engine.Evaluate("JSON.stringify(a.GroupBy(m => ({a:m,b:m})).Select(x => x.Key).ToArray());").AsString();
+        Assert.Equal("""[{"a":2,"b":2},{"a":4,"b":4}]""", grouped);
     }
-}
+}

+ 13 - 14
Jint.Tests/Runtime/ExtensionMethods/FlurlExtensionTest.cs

@@ -1,20 +1,20 @@
 using Flurl.Http;
 
-namespace Jint.Tests.Runtime.ExtensionMethods
+namespace Jint.Tests.Runtime.ExtensionMethods;
+
+public class FlurlExtensionTest
 {
-    public class FlurlExtensionTest
+    [RunnableInDebugOnlyAttribute]
+    public void CanUseFlurlExtensionMethods()
     {
-        [RunnableInDebugOnlyAttribute]
-        public void CanUseFlurlExtensionMethods()
+        var engine = new Engine(options =>
         {
-            var engine = new Engine(options =>
-            {
-                options.AddExtensionMethods(
-                    typeof(GeneratedExtensions),
-                    typeof(Flurl.GeneratedExtensions));
-            });
+            options.AddExtensionMethods(
+                typeof(GeneratedExtensions),
+                typeof(Flurl.GeneratedExtensions));
+        });
 
-            const string script = @"
+        const string script = @"
 var result = 'https://httpbin.org/anything'
         .AppendPathSegment('person')
         .SetQueryParams({ a: 1, b: 2 })
@@ -25,9 +25,8 @@ var result = 'https://httpbin.org/anything'
          }).GetAwaiter().GetResult();
 ";
 
-            engine.Execute(script);
+        engine.Execute(script);
 
-            var result = engine.GetValue("result").ToObject();
-        }
+        var result = engine.GetValue("result").ToObject();
     }
 }

+ 100 - 101
Jint.Tests/Runtime/ExtensionMethods/ObservableExtensions.cs

@@ -1,141 +1,140 @@
-namespace Jint.Tests.Runtime.ExtensionMethods
+namespace Jint.Tests.Runtime.ExtensionMethods;
+
+internal class Subscribe<T> : IObserver<T>
 {
-    internal class Subscribe<T> : IObserver<T>
-    {
-        private readonly Action<T> onNext;
-        private readonly Action<Exception> onError;
-        private readonly Action onCompleted;
+    private readonly Action<T> onNext;
+    private readonly Action<Exception> onError;
+    private readonly Action onCompleted;
 
-        readonly int isStopped = 0;
+    readonly int isStopped = 0;
 
-        public Subscribe(Action<T> onNext, Action<Exception> onError, Action onCompleted)
-        {
-            this.onNext = onNext;
-            this.onError = onError;
-            this.onCompleted = onCompleted;
-        }
+    public Subscribe(Action<T> onNext, Action<Exception> onError, Action onCompleted)
+    {
+        this.onNext = onNext;
+        this.onError = onError;
+        this.onCompleted = onCompleted;
+    }
 
-        public void OnNext(T value)
+    public void OnNext(T value)
+    {
+        if (isStopped == 0)
         {
-            if (isStopped == 0)
-            {
-                onNext(value);
-            }
+            onNext(value);
         }
+    }
 
-        public void OnError(Exception error)
-        {
-            onError(error);
-        }
+    public void OnError(Exception error)
+    {
+        onError(error);
+    }
 
 
-        public void OnCompleted()
-        {
-            onCompleted();
-        }
+    public void OnCompleted()
+    {
+        onCompleted();
     }
+}
 
-    public static partial class ObservableExtensions
+public static partial class ObservableExtensions
+{
+    public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext)
     {
-        public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext)
-        {
-            var subs = new Subscribe<T>(onNext, null, null);
-            source.Subscribe(subs);
-        }
-
-        public static TResult Select<T, TResult>(this IObservable<T> source, TResult result)
-        {
-            return result;
-        }
+        var subs = new Subscribe<T>(onNext, null, null);
+        source.Subscribe(subs);
+    }
 
-        public static IObservable<T> Where<T>(this IObservable<T> source, Func<T, bool> predicate)
-        {
-            T t = default;
-            predicate(t);
-            return source;
-        }
+    public static TResult Select<T, TResult>(this IObservable<T> source, TResult result)
+    {
+        return result;
+    }
 
-        public static IObservable<T> Where<T>(this IObservable<T> source, Func<T, int, bool> predicate)
-        {
-            T t = default;
-            bool result = predicate(t, 42);
-            return source;
-        }
+    public static IObservable<T> Where<T>(this IObservable<T> source, Func<T, bool> predicate)
+    {
+        T t = default;
+        predicate(t);
+        return source;
     }
 
-    public class BaseObservable<T> : IObservable<T>
+    public static IObservable<T> Where<T>(this IObservable<T> source, Func<T, int, bool> predicate)
     {
-        private readonly List<IObserver<T>> observers = new List<IObserver<T>>();
+        T t = default;
+        bool result = predicate(t, 42);
+        return source;
+    }
+}
 
-        public T Last { get; private set; }
+public class BaseObservable<T> : IObservable<T>
+{
+    private readonly List<IObserver<T>> observers = new List<IObserver<T>>();
 
-        public IDisposable Subscribe(IObserver<T> observer)
-        {
-            if (!observers.Contains(observer))
-                observers.Add(observer);
-            return new Unsubscriber(observers, observer);
-        }
+    public T Last { get; private set; }
 
-        private class Unsubscriber : IDisposable
-        {
-            private readonly List<IObserver<T>> _observers;
-            private readonly IObserver<T> _observer;
-
-            public Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer)
-            {
-                this._observers = observers;
-                this._observer = observer;
-            }
-
-            public void Dispose()
-            {
-                if (_observer != null && _observers.Contains(_observer))
-                    _observers.Remove(_observer);
-            }
-        }
+    public IDisposable Subscribe(IObserver<T> observer)
+    {
+        if (!observers.Contains(observer))
+            observers.Add(observer);
+        return new Unsubscriber(observers, observer);
+    }
 
-        protected void BroadcastUpdate(T t)
-        {
-            foreach (var observer in observers)
-            {
-                observer.OnNext(t);
-            }
-        }
+    private class Unsubscriber : IDisposable
+    {
+        private readonly List<IObserver<T>> _observers;
+        private readonly IObserver<T> _observer;
 
-        public void Update(T t)
+        public Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer)
         {
-            Last = t;
-            BroadcastUpdate(t);
+            this._observers = observers;
+            this._observer = observer;
         }
 
-        public void BroadcastCompleted()
+        public void Dispose()
         {
-            foreach (var observer in observers.ToArray())
-            {
-                observer.OnCompleted();
-            }
-            observers.Clear();
+            if (_observer != null && _observers.Contains(_observer))
+                _observers.Remove(_observer);
         }
     }
 
-    public class ObservableFactory
+    protected void BroadcastUpdate(T t)
     {
-        public static BaseObservable<bool> GetBoolBaseObservable()
+        foreach (var observer in observers)
         {
-            return new BaseObservable<bool>();
+            observer.OnNext(t);
         }
     }
 
-    public class NameObservable : BaseObservable<string>
+    public void Update(T t)
     {
-        public void UpdateName(string name)
-        {
-            Update(name);
-        }
+        Last = t;
+        BroadcastUpdate(t);
+    }
 
-        public void CommitName()
+    public void BroadcastCompleted()
+    {
+        foreach (var observer in observers.ToArray())
         {
-            BroadcastCompleted();
+            observer.OnCompleted();
         }
+        observers.Clear();
+    }
+}
+
+public class ObservableFactory
+{
+    public static BaseObservable<bool> GetBoolBaseObservable()
+    {
+        return new BaseObservable<bool>();
     }
 }
+
+public class NameObservable : BaseObservable<string>
+{
+    public void UpdateName(string name)
+    {
+        Update(name);
+    }
+
+    public void CommitName()
+    {
+        BroadcastCompleted();
+    }
+}

+ 6 - 7
Jint.Tests/Runtime/ExtensionMethods/OverrideStringPrototypeExtensions.cs

@@ -1,10 +1,9 @@
-namespace Jint.Tests.Runtime.ExtensionMethods
+namespace Jint.Tests.Runtime.ExtensionMethods;
+
+public static class OverrideStringPrototypeExtensions
 {
-    public static class OverrideStringPrototypeExtensions
+    public static string[] Split(this string value, string delimiter)
     {
-        public static string[] Split(this string value, string delimiter)
-        {
-            return value.Split(delimiter.ToCharArray()).Select(v => v.ToUpper()).ToArray();
-        }
+        return value.Split(delimiter.ToCharArray()).Select(v => v.ToUpper()).ToArray();
     }
-}
+}

+ 5 - 6
Jint.Tests/Runtime/ExtensionMethods/PersonExtensions.cs

@@ -1,12 +1,11 @@
 using Jint.Tests.Runtime.Domain;
 
-namespace Jint.Tests.Runtime.ExtensionMethods
+namespace Jint.Tests.Runtime.ExtensionMethods;
+
+public static class PersonExtensions
 {
-    public static class PersonExtensions
+    public static int MultiplyAge(this Person person, int factor)
     {
-        public static int MultiplyAge(this Person person, int factor)
-        {
-            return person.Age * factor;
-        }
+        return person.Age * factor;
     }
 }

+ 12 - 13
Jint.Tests/Runtime/GlobalTests.cs

@@ -1,17 +1,16 @@
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class GlobalTests
 {
-    public class GlobalTests
+    [Fact]
+    public void UnescapeAtEndOfString()
     {
-        [Fact]
-        public void UnescapeAtEndOfString()
-        {
-            var e = new Engine();
+        var e = new Engine();
 
-            Assert.Equal("@", e.Evaluate("unescape('%40');").AsString());
-            Assert.Equal("@_", e.Evaluate("unescape('%40_');").AsString());
-            Assert.Equal("@@", e.Evaluate("unescape('%40%40');").AsString());
-            Assert.Equal("@", e.Evaluate("unescape('%u0040');").AsString());
-            Assert.Equal("@@", e.Evaluate("unescape('%u0040%u0040');").AsString());
-        }
+        Assert.Equal("@", e.Evaluate("unescape('%40');").AsString());
+        Assert.Equal("@_", e.Evaluate("unescape('%40_');").AsString());
+        Assert.Equal("@@", e.Evaluate("unescape('%40%40');").AsString());
+        Assert.Equal("@", e.Evaluate("unescape('%u0040');").AsString());
+        Assert.Equal("@@", e.Evaluate("unescape('%u0040%u0040');").AsString());
     }
-}
+}

+ 207 - 208
Jint.Tests/Runtime/InteropTests.MemberAccess.cs

@@ -5,280 +5,279 @@ using Jint.Runtime;
 using Jint.Runtime.Interop;
 using Jint.Tests.Runtime.Domain;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public partial class InteropTests
 {
-    public partial class InteropTests
+    [Fact]
+    public void ShouldHideSpecificMembers()
     {
-        [Fact]
-        public void ShouldHideSpecificMembers()
+        var engine = new Engine(options => options.SetMemberAccessor((e, target, member) =>
         {
-            var engine = new Engine(options => options.SetMemberAccessor((e, target, member) =>
+            if (target is HiddenMembers)
             {
-                if (target is HiddenMembers)
+                if (member == nameof(HiddenMembers.Member2) || member == nameof(HiddenMembers.Method2))
                 {
-                    if (member == nameof(HiddenMembers.Member2) || member == nameof(HiddenMembers.Method2))
-                    {
-                        return JsValue.Undefined;
-                    }
+                    return JsValue.Undefined;
                 }
+            }
 
-                return null;
-            }));
+            return null;
+        }));
 
-            engine.SetValue("m", new HiddenMembers());
+        engine.SetValue("m", new HiddenMembers());
 
-            Assert.Equal("Member1", engine.Evaluate("m.Member1").ToString());
-            Assert.Equal("undefined", engine.Evaluate("m.Member2").ToString());
-            Assert.Equal("Method1", engine.Evaluate("m.Method1()").ToString());
-            // check the method itself, not its invokation as it would mean invoking "undefined"
-            Assert.Equal("undefined", engine.Evaluate("m.Method2").ToString());
-        }
+        Assert.Equal("Member1", engine.Evaluate("m.Member1").ToString());
+        Assert.Equal("undefined", engine.Evaluate("m.Member2").ToString());
+        Assert.Equal("Method1", engine.Evaluate("m.Method1()").ToString());
+        // check the method itself, not its invokation as it would mean invoking "undefined"
+        Assert.Equal("undefined", engine.Evaluate("m.Method2").ToString());
+    }
 
-        [Fact]
-        public void ShouldOverrideMembers()
+    [Fact]
+    public void ShouldOverrideMembers()
+    {
+        var engine = new Engine(options => options.SetMemberAccessor((e, target, member) =>
         {
-            var engine = new Engine(options => options.SetMemberAccessor((e, target, member) =>
+            if (target is HiddenMembers && member == nameof(HiddenMembers.Member1))
             {
-                if (target is HiddenMembers && member == nameof(HiddenMembers.Member1))
-                {
-                    return "Orange";
-                }
+                return "Orange";
+            }
 
-                return null;
-            }));
+            return null;
+        }));
 
-            engine.SetValue("m", new HiddenMembers());
+        engine.SetValue("m", new HiddenMembers());
 
-            Assert.Equal("Orange", engine.Evaluate("m.Member1").ToString());
-        }
+        Assert.Equal("Orange", engine.Evaluate("m.Member1").ToString());
+    }
 
-        [Fact]
-        public void ShouldBeAbleToFilterMembers()
-        {
-            var engine = new Engine(options => options
-                .SetTypeResolver(new TypeResolver
-                {
-                    MemberFilter = member => !Attribute.IsDefined(member, typeof(ObsoleteAttribute))
-                })
-            );
+    [Fact]
+    public void ShouldBeAbleToFilterMembers()
+    {
+        var engine = new Engine(options => options
+            .SetTypeResolver(new TypeResolver
+            {
+                MemberFilter = member => !Attribute.IsDefined(member, typeof(ObsoleteAttribute))
+            })
+        );
 
-            engine.SetValue("m", new HiddenMembers());
+        engine.SetValue("m", new HiddenMembers());
 
-            Assert.True(engine.Evaluate("m.Field1").IsUndefined());
-            Assert.True(engine.Evaluate("m.Member1").IsUndefined());
-            Assert.True(engine.Evaluate("m.Method1").IsUndefined());
+        Assert.True(engine.Evaluate("m.Field1").IsUndefined());
+        Assert.True(engine.Evaluate("m.Member1").IsUndefined());
+        Assert.True(engine.Evaluate("m.Method1").IsUndefined());
 
-            Assert.True(engine.Evaluate("m.Field2").IsString());
-            Assert.True(engine.Evaluate("m.Member2").IsString());
-            Assert.True(engine.Evaluate("m.Method2()").IsString());
+        Assert.True(engine.Evaluate("m.Field2").IsString());
+        Assert.True(engine.Evaluate("m.Member2").IsString());
+        Assert.True(engine.Evaluate("m.Method2()").IsString());
 
-            // we forbid GetType by default
-            Assert.True(engine.Evaluate("m.GetType").IsUndefined());
-        }
+        // we forbid GetType by default
+        Assert.True(engine.Evaluate("m.GetType").IsUndefined());
+    }
 
-        [Fact]
-        public void ShouldBeAbleToExposeGetType()
+    [Fact]
+    public void ShouldBeAbleToExposeGetType()
+    {
+        var engine = new Engine(options =>
         {
-            var engine = new Engine(options =>
-            {
-                options.Interop.AllowGetType = true;
-                options.Interop.AllowSystemReflection = true;
-            });
-            engine.SetValue("m", new HiddenMembers());
-            Assert.True(engine.Evaluate("m.GetType").IsCallable);
-
-            // reflection could bypass some safeguards
-            Assert.Equal("Method1", engine.Evaluate("m.GetType().GetMethod('Method1').Invoke(m, [])").AsString());
-        }
+            options.Interop.AllowGetType = true;
+            options.Interop.AllowSystemReflection = true;
+        });
+        engine.SetValue("m", new HiddenMembers());
+        Assert.True(engine.Evaluate("m.GetType").IsCallable);
+
+        // reflection could bypass some safeguards
+        Assert.Equal("Method1", engine.Evaluate("m.GetType().GetMethod('Method1').Invoke(m, [])").AsString());
+    }
 
-        [Fact]
-        public void ShouldBeAbleToVaryGetTypeConfigurationBetweenEngines()
+    [Fact]
+    public void ShouldBeAbleToVaryGetTypeConfigurationBetweenEngines()
+    {
+        static string TestAllowGetTypeOption(bool allowGetType)
         {
-            static string TestAllowGetTypeOption(bool allowGetType)
-            {
-                var uri = new Uri("https://github.com/sebastienros/jint");
-                const string Input = nameof(uri) + ".GetType();";
+            var uri = new Uri("https://github.com/sebastienros/jint");
+            const string Input = nameof(uri) + ".GetType();";
 
-                using var engine = new Engine(options => options.Interop.AllowGetType = allowGetType);
-                engine.SetValue(nameof(uri), JsValue.FromObject(engine, uri));
-                var result = engine.Evaluate(Input).ToString();
-                return result;
-            }
+            using var engine = new Engine(options => options.Interop.AllowGetType = allowGetType);
+            engine.SetValue(nameof(uri), JsValue.FromObject(engine, uri));
+            var result = engine.Evaluate(Input).ToString();
+            return result;
+        }
 
-            Assert.Equal("System.Uri", TestAllowGetTypeOption(allowGetType: true));
+        Assert.Equal("System.Uri", TestAllowGetTypeOption(allowGetType: true));
 
-            var ex = Assert.Throws<JavaScriptException>(() => TestAllowGetTypeOption(allowGetType: false));
-            Assert.Equal("Property 'GetType' of object is not a function", ex.Message);
-        }
+        var ex = Assert.Throws<JavaScriptException>(() => TestAllowGetTypeOption(allowGetType: false));
+        Assert.Equal("Property 'GetType' of object is not a function", ex.Message);
+    }
 
-        [Fact]
-        public void ShouldProtectFromReflectionServiceUsage()
-        {
-            var engine = new Engine();
-            engine.SetValue("m", new HiddenMembers());
+    [Fact]
+    public void ShouldProtectFromReflectionServiceUsage()
+    {
+        var engine = new Engine();
+        engine.SetValue("m", new HiddenMembers());
 
-            // we can get a type reference if it's exposed via property, bypassing GetType
-            var type = engine.Evaluate("m.Type");
-            Assert.IsType<ObjectWrapper>(type);
+        // we can get a type reference if it's exposed via property, bypassing GetType
+        var type = engine.Evaluate("m.Type");
+        Assert.IsType<ObjectWrapper>(type);
 
-            var ex = Assert.Throws<InvalidOperationException>(() => engine.Evaluate("m.Type.Module.GetType().Module.GetType('System.DateTime')"));
-            Assert.Equal("Cannot access System.Reflection namespace, check Engine's interop options", ex.Message);
-        }
+        var ex = Assert.Throws<InvalidOperationException>(() => engine.Evaluate("m.Type.Module.GetType().Module.GetType('System.DateTime')"));
+        Assert.Equal("Cannot access System.Reflection namespace, check Engine's interop options", ex.Message);
+    }
 
-        [Fact]
-        public void TypeReferenceShouldUseTypeResolverConfiguration()
+    [Fact]
+    public void TypeReferenceShouldUseTypeResolverConfiguration()
+    {
+        var engine = new Engine(options =>
         {
-            var engine = new Engine(options =>
+            options.SetTypeResolver(new TypeResolver
             {
-                options.SetTypeResolver(new TypeResolver
-                {
-                    MemberFilter = member => !Attribute.IsDefined(member, typeof(ObsoleteAttribute))
-                });
+                MemberFilter = member => !Attribute.IsDefined(member, typeof(ObsoleteAttribute))
             });
-            engine.SetValue("EchoService", TypeReference.CreateTypeReference(engine, typeof(EchoService)));
-            Assert.Equal("anyone there", engine.Evaluate("EchoService.Echo('anyone there')").AsString());
-            Assert.Equal("anyone there", engine.Evaluate("EchoService.echo('anyone there')").AsString());
-            Assert.True(engine.Evaluate("EchoService.ECHO").IsUndefined());
+        });
+        engine.SetValue("EchoService", TypeReference.CreateTypeReference(engine, typeof(EchoService)));
+        Assert.Equal("anyone there", engine.Evaluate("EchoService.Echo('anyone there')").AsString());
+        Assert.Equal("anyone there", engine.Evaluate("EchoService.echo('anyone there')").AsString());
+        Assert.True(engine.Evaluate("EchoService.ECHO").IsUndefined());
 
-            Assert.True(engine.Evaluate("EchoService.Hidden").IsUndefined());
-        }
+        Assert.True(engine.Evaluate("EchoService.Hidden").IsUndefined());
+    }
 
-        [Fact]
-        public void CustomDictionaryPropertyAccessTests()
+    [Fact]
+    public void CustomDictionaryPropertyAccessTests()
+    {
+        var engine = new Engine(options =>
         {
-            var engine = new Engine(options =>
-            {
-                options.AllowClr();
-            });
+            options.AllowClr();
+        });
 
-            var dc = new CustomDictionary<float>();
-            dc["a"] = 1;
+        var dc = new CustomDictionary<float>();
+        dc["a"] = 1;
 
-            engine.SetValue("dc", dc);
+        engine.SetValue("dc", dc);
 
-            Assert.Equal(1, engine.Evaluate("dc.a"));
-            Assert.Equal(1, engine.Evaluate("dc['a']"));
-            Assert.NotEqual(JsValue.Undefined, engine.Evaluate("dc.Add"));
-            Assert.NotEqual(0, engine.Evaluate("dc.Add"));
-            Assert.Equal(JsValue.Undefined, engine.Evaluate("dc.b"));
+        Assert.Equal(1, engine.Evaluate("dc.a"));
+        Assert.Equal(1, engine.Evaluate("dc['a']"));
+        Assert.NotEqual(JsValue.Undefined, engine.Evaluate("dc.Add"));
+        Assert.NotEqual(0, engine.Evaluate("dc.Add"));
+        Assert.Equal(JsValue.Undefined, engine.Evaluate("dc.b"));
 
-            engine.Execute("dc.b = 5");
-            engine.Execute("dc.Add('c', 10)");
-            Assert.Equal(5, engine.Evaluate("dc.b"));
-            Assert.Equal(10, engine.Evaluate("dc.c"));
-        }
+        engine.Execute("dc.b = 5");
+        engine.Execute("dc.Add('c', 10)");
+        Assert.Equal(5, engine.Evaluate("dc.b"));
+        Assert.Equal(10, engine.Evaluate("dc.c"));
+    }
 
-        [Fact]
-        public void CanAccessBaseClassStaticFields()
+    [Fact]
+    public void CanAccessBaseClassStaticFields()
+    {
+        var engine = new Engine(options =>
         {
-            var engine = new Engine(options =>
-            {
-                options.AllowClr();
-            });
+            options.AllowClr();
+        });
 
-            engine.SetValue("B", TypeReference.CreateTypeReference(engine, typeof(InheritingFromClassWithStatics)));
-            Assert.Equal(42, engine.Evaluate("B.a").AsNumber());
-            Assert.Equal(24, engine.Evaluate("B.a = 24; B.a").AsNumber());
-        }
+        engine.SetValue("B", TypeReference.CreateTypeReference(engine, typeof(InheritingFromClassWithStatics)));
+        Assert.Equal(42, engine.Evaluate("B.a").AsNumber());
+        Assert.Equal(24, engine.Evaluate("B.a = 24; B.a").AsNumber());
+    }
 
-        private class BaseClassWithStatics
-        {
+    private class BaseClassWithStatics
+    {
 #pragma warning disable CS0414 // Field is assigned but its value is never used
-            public static int a = 42;
+        public static int a = 42;
 #pragma warning restore CS0414 // Field is assigned but its value is never used
-        }
+    }
 
-        private class InheritingFromClassWithStatics : BaseClassWithStatics
-        {
-        }
+    private class InheritingFromClassWithStatics : BaseClassWithStatics
+    {
+    }
 
-        private static class EchoService
-        {
-            public static string Echo(string message) => message;
+    private static class EchoService
+    {
+        public static string Echo(string message) => message;
 
-            [Obsolete]
-            public static string Hidden(string message) => message;
-        }
+        [Obsolete]
+        public static string Hidden(string message) => message;
+    }
 
-        private class CustomDictionary<TValue> : IDictionary<string, TValue>
-        {
-            readonly Dictionary<string, TValue> _dictionary = new Dictionary<string, TValue>();
+    private class CustomDictionary<TValue> : IDictionary<string, TValue>
+    {
+        readonly Dictionary<string, TValue> _dictionary = new Dictionary<string, TValue>();
 
-            public TValue this[string key]
+        public TValue this[string key]
+        {
+            get
             {
-                get
-                {
-                    if (TryGetValue(key, out var val)) return val;
+                if (TryGetValue(key, out var val)) return val;
 
-                    // Normally, dictionary Item accessor throws an error when key does not exist
-                    // But this is a custom implementation
-                    return default;
-                }
-                set
-                {
-                    _dictionary[key] = value;
-                }
+                // Normally, dictionary Item accessor throws an error when key does not exist
+                // But this is a custom implementation
+                return default;
+            }
+            set
+            {
+                _dictionary[key] = value;
             }
-
-            public ICollection<string> Keys => _dictionary.Keys;
-            public ICollection<TValue> Values => _dictionary.Values;
-            public int Count => _dictionary.Count;
-            public bool IsReadOnly => false;
-            public void Add(string key, TValue value) => _dictionary.Add(key, value);
-            public void Add(KeyValuePair<string, TValue> item) => _dictionary.Add(item.Key, item.Value);
-            public void Clear() => _dictionary.Clear();
-            public bool Contains(KeyValuePair<string, TValue> item) => _dictionary.ContainsKey(item.Key);
-            public bool ContainsKey(string key) => _dictionary.ContainsKey(key);
-            public void CopyTo(KeyValuePair<string, TValue>[] array, int arrayIndex) => throw new NotImplementedException();
-            public IEnumerator<KeyValuePair<string, TValue>> GetEnumerator() => _dictionary.GetEnumerator();
-            public bool Remove(string key) => _dictionary.Remove(key);
-            public bool Remove(KeyValuePair<string, TValue> item) => _dictionary.Remove(item.Key);
-            public bool TryGetValue(string key, [MaybeNullWhen(false)] out TValue value) => _dictionary.TryGetValue(key, out value);
-            IEnumerator IEnumerable.GetEnumerator() => _dictionary.GetEnumerator();
         }
 
-        public class ClassWithData
-        {
-            public int Age => 42;
+        public ICollection<string> Keys => _dictionary.Keys;
+        public ICollection<TValue> Values => _dictionary.Values;
+        public int Count => _dictionary.Count;
+        public bool IsReadOnly => false;
+        public void Add(string key, TValue value) => _dictionary.Add(key, value);
+        public void Add(KeyValuePair<string, TValue> item) => _dictionary.Add(item.Key, item.Value);
+        public void Clear() => _dictionary.Clear();
+        public bool Contains(KeyValuePair<string, TValue> item) => _dictionary.ContainsKey(item.Key);
+        public bool ContainsKey(string key) => _dictionary.ContainsKey(key);
+        public void CopyTo(KeyValuePair<string, TValue>[] array, int arrayIndex) => throw new NotImplementedException();
+        public IEnumerator<KeyValuePair<string, TValue>> GetEnumerator() => _dictionary.GetEnumerator();
+        public bool Remove(string key) => _dictionary.Remove(key);
+        public bool Remove(KeyValuePair<string, TValue> item) => _dictionary.Remove(item.Key);
+        public bool TryGetValue(string key, [MaybeNullWhen(false)] out TValue value) => _dictionary.TryGetValue(key, out value);
+        IEnumerator IEnumerable.GetEnumerator() => _dictionary.GetEnumerator();
+    }
 
-            public DataType Data { get; set; }
+    public class ClassWithData
+    {
+        public int Age => 42;
 
-            public class DataType
-            {
-                public string Value { get; set; }
-            }
-        }
+        public DataType Data { get; set; }
 
-        [Fact]
-        public void NewTypedObjectFromUntypedInitializerShouldBeMapped()
+        public class DataType
         {
-            var engine = new Engine();
+            public string Value { get; set; }
+        }
+    }
 
-            engine.SetValue("obj", new ClassWithData());
-            engine.Execute("obj.Data = { Value: '123' };");
-            var obj = engine.Evaluate("obj").ToObject() as ClassWithData;
+    [Fact]
+    public void NewTypedObjectFromUntypedInitializerShouldBeMapped()
+    {
+        var engine = new Engine();
 
-            Assert.Equal("123", obj?.Data.Value);
-        }
+        engine.SetValue("obj", new ClassWithData());
+        engine.Execute("obj.Data = { Value: '123' };");
+        var obj = engine.Evaluate("obj").ToObject() as ClassWithData;
 
-        [Fact]
-        public void CanConfigureStrictAccess()
-        {
-            var engine = new Engine();
+        Assert.Equal("123", obj?.Data.Value);
+    }
+
+    [Fact]
+    public void CanConfigureStrictAccess()
+    {
+        var engine = new Engine();
 
-            engine.SetValue("obj", new ClassWithData());
-            engine.Evaluate("obj.Age").AsNumber().Should().Be(42);
-            engine.Evaluate("obj.AgeMissing").Should().Be(JsValue.Undefined);
+        engine.SetValue("obj", new ClassWithData());
+        engine.Evaluate("obj.Age").AsNumber().Should().Be(42);
+        engine.Evaluate("obj.AgeMissing").Should().Be(JsValue.Undefined);
 
-            engine = new Engine(options =>
-            {
-                options.Interop.ThrowOnUnresolvedMember = true;
-            });
+        engine = new Engine(options =>
+        {
+            options.Interop.ThrowOnUnresolvedMember = true;
+        });
 
-            engine.SetValue("obj", new ClassWithData());
-            engine.Evaluate("obj.Age").AsNumber().Should().Be(42);
+        engine.SetValue("obj", new ClassWithData());
+        engine.Evaluate("obj.Age").AsNumber().Should().Be(42);
 
-            engine.Invoking(e => e.Evaluate("obj.AgeMissing")).Should().Throw<MissingMemberException>();
-        }
+        engine.Invoking(e => e.Evaluate("obj.AgeMissing")).Should().Throw<MissingMemberException>();
     }
-}
+}

文件差异内容过多而无法显示
+ 504 - 504
Jint.Tests/Runtime/InteropTests.cs


+ 195 - 196
Jint.Tests/Runtime/JsValueConversionTests.cs

@@ -1,202 +1,201 @@
 using Jint.Native;
 using Jint.Runtime;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class JsValueConversionTests
 {
-    public class JsValueConversionTests
+    private readonly Engine _engine;
+
+    public JsValueConversionTests()
+    {
+        _engine = new Engine();
+    }
+
+    [Fact]
+    public void ShouldBeAnArray()
+    {
+        var value = new JsArray(_engine);
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(true, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(true, value.IsObject());
+        Assert.Equal(false, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(false, value.IsUndefined());
+
+        Assert.Equal(true, value.AsArray() != null);
+    }
+
+    [Fact]
+    public void ShouldBeABoolean()
+    {
+        var value = JsBoolean.True;
+        Assert.Equal(true, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(false, value.IsObject());
+        Assert.Equal(true, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(false, value.IsUndefined());
+
+        Assert.Equal(true, value.AsBoolean());
+    }
+
+    [Fact]
+    public void ShouldBeADate()
+    {
+        var value = new JsDate(_engine, double.NaN);
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(true, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(true, value.IsObject());
+        Assert.Equal(false, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(false, value.IsUndefined());
+
+        Assert.Equal(true, value.AsDate() != null);
+    }
+
+    [Fact]
+    public void ShouldBeNull()
+    {
+        var value = JsValue.Null;
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(true, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(false, value.IsObject());
+        Assert.Equal(true, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(false, value.IsUndefined());
+    }
+
+    [Fact]
+    public void ShouldBeANumber()
+    {
+        var value = new JsNumber(2);
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(true, value.IsNumber());
+        Assert.Equal(2, value.AsNumber());
+        Assert.Equal(false, value.IsObject());
+        Assert.Equal(true, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(false, value.IsUndefined());
+    }
+
+    [Fact]
+    public void ShouldBeAnObject()
     {
-        private readonly Engine _engine;
-
-        public JsValueConversionTests()
-        {
-            _engine = new Engine();
-        }
-
-        [Fact]
-        public void ShouldBeAnArray()
-        {
-            var value = new JsArray(_engine);
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(true, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(true, value.IsObject());
-            Assert.Equal(false, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(false, value.IsUndefined());
-
-            Assert.Equal(true, value.AsArray() != null);
-        }
-
-        [Fact]
-        public void ShouldBeABoolean()
-        {
-            var value = JsBoolean.True;
-            Assert.Equal(true, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(false, value.IsObject());
-            Assert.Equal(true, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(false, value.IsUndefined());
-
-            Assert.Equal(true, value.AsBoolean());
-        }
-
-        [Fact]
-        public void ShouldBeADate()
-        {
-            var value = new JsDate(_engine, double.NaN);
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(true, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(true, value.IsObject());
-            Assert.Equal(false, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(false, value.IsUndefined());
-
-            Assert.Equal(true, value.AsDate() != null);
-        }
-
-        [Fact]
-        public void ShouldBeNull()
-        {
-            var value = JsValue.Null;
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(true, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(false, value.IsObject());
-            Assert.Equal(true, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(false, value.IsUndefined());
-        }
-
-        [Fact]
-        public void ShouldBeANumber()
-        {
-            var value = new JsNumber(2);
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(true, value.IsNumber());
-            Assert.Equal(2, value.AsNumber());
-            Assert.Equal(false, value.IsObject());
-            Assert.Equal(true, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(false, value.IsUndefined());
-        }
-
-        [Fact]
-        public void ShouldBeAnObject()
-        {
-            var value = new JsObject(_engine);
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(true, value.IsObject());
-            Assert.Equal(true, value.AsObject() != null);
-            Assert.Equal(false, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(false, value.IsUndefined());
-        }
-
-        [Fact]
-        public void ShouldBeARegExp()
-        {
-            var value = new JsRegExp(_engine);
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(true, value.IsObject());
-            Assert.Equal(false, value.IsPrimitive());
-            Assert.Equal(true, value.IsRegExp());
-            Assert.Equal(true, value.AsRegExp() != null);
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(false, value.IsUndefined());
-        }
-
-        [Fact]
-        public void ShouldBeAString()
-        {
-            var value = new JsString("a");
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(false, value.IsObject());
-            Assert.Equal(true, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(true, value.IsString());
-            Assert.Equal("a", value.AsString());
-            Assert.Equal(false, value.IsUndefined());
-        }
-
-        [Fact]
-        public void ShouldBeUndefined()
-        {
-            var value = JsValue.Undefined;
-            Assert.Equal(false, value.IsBoolean());
-            Assert.Equal(false, value.IsArray());
-            Assert.Equal(false, value.IsDate());
-            Assert.Equal(false, value.IsNull());
-            Assert.Equal(false, value.IsNumber());
-            Assert.Equal(false, value.IsObject());
-            Assert.Equal(true, value.IsPrimitive());
-            Assert.Equal(false, value.IsRegExp());
-            Assert.Equal(false, value.IsString());
-            Assert.Equal(true, value.IsUndefined());
-        }
-
-        [Fact]
-        public void ShouldConvertArrayBuffer()
-        {
-            var value = _engine.Evaluate("new Uint8Array([102, 111, 111]).buffer");
-            Assert.Equal(true, value.IsArrayBuffer());
-            Assert.Equal([102, 111, 111], value.AsArrayBuffer());
-            Assert.Equal([102, 111, 111], value.ToObject() as byte[]);
-
-            (value as JsArrayBuffer).DetachArrayBuffer();
-
-            Assert.Equal(true, value.IsArrayBuffer());
-            Assert.Equal(null, value.AsArrayBuffer());
-            Assert.Throws<JavaScriptException>(value.ToObject);
-            Assert.Throws<ArgumentException>(JsValue.Undefined.AsArrayBuffer);
-        }
-
-        [Fact]
-        public void ShouldConvertDataView()
-        {
-            var value = _engine.Evaluate("new DataView(new Uint8Array([102, 102, 111, 111, 111]).buffer, 1, 3)");
-
-            Assert.Equal(true, value.IsDataView());
-            Assert.Equal([102, 111, 111], value.AsDataView());
-            Assert.Equal([102, 111, 111], value.ToObject() as byte[]);
-
-            (value as JsDataView)._viewedArrayBuffer.DetachArrayBuffer();
-
-            Assert.Equal(true, value.IsDataView());
-            Assert.Equal(null, value.AsDataView());
-            Assert.Throws<JavaScriptException>(value.ToObject);
-            Assert.Throws<ArgumentException>(JsValue.Undefined.AsDataView);
-        }
+        var value = new JsObject(_engine);
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(true, value.IsObject());
+        Assert.Equal(true, value.AsObject() != null);
+        Assert.Equal(false, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(false, value.IsUndefined());
+    }
+
+    [Fact]
+    public void ShouldBeARegExp()
+    {
+        var value = new JsRegExp(_engine);
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(true, value.IsObject());
+        Assert.Equal(false, value.IsPrimitive());
+        Assert.Equal(true, value.IsRegExp());
+        Assert.Equal(true, value.AsRegExp() != null);
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(false, value.IsUndefined());
+    }
+
+    [Fact]
+    public void ShouldBeAString()
+    {
+        var value = new JsString("a");
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(false, value.IsObject());
+        Assert.Equal(true, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(true, value.IsString());
+        Assert.Equal("a", value.AsString());
+        Assert.Equal(false, value.IsUndefined());
+    }
+
+    [Fact]
+    public void ShouldBeUndefined()
+    {
+        var value = JsValue.Undefined;
+        Assert.Equal(false, value.IsBoolean());
+        Assert.Equal(false, value.IsArray());
+        Assert.Equal(false, value.IsDate());
+        Assert.Equal(false, value.IsNull());
+        Assert.Equal(false, value.IsNumber());
+        Assert.Equal(false, value.IsObject());
+        Assert.Equal(true, value.IsPrimitive());
+        Assert.Equal(false, value.IsRegExp());
+        Assert.Equal(false, value.IsString());
+        Assert.Equal(true, value.IsUndefined());
+    }
+
+    [Fact]
+    public void ShouldConvertArrayBuffer()
+    {
+        var value = _engine.Evaluate("new Uint8Array([102, 111, 111]).buffer");
+        Assert.Equal(true, value.IsArrayBuffer());
+        Assert.Equal([102, 111, 111], value.AsArrayBuffer());
+        Assert.Equal([102, 111, 111], value.ToObject() as byte[]);
+
+        (value as JsArrayBuffer).DetachArrayBuffer();
+
+        Assert.Equal(true, value.IsArrayBuffer());
+        Assert.Equal(null, value.AsArrayBuffer());
+        Assert.Throws<JavaScriptException>(value.ToObject);
+        Assert.Throws<ArgumentException>(JsValue.Undefined.AsArrayBuffer);
+    }
+
+    [Fact]
+    public void ShouldConvertDataView()
+    {
+        var value = _engine.Evaluate("new DataView(new Uint8Array([102, 102, 111, 111, 111]).buffer, 1, 3)");
+
+        Assert.Equal(true, value.IsDataView());
+        Assert.Equal([102, 111, 111], value.AsDataView());
+        Assert.Equal([102, 111, 111], value.ToObject() as byte[]);
+
+        (value as JsDataView)._viewedArrayBuffer.DetachArrayBuffer();
+
+        Assert.Equal(true, value.IsDataView());
+        Assert.Equal(null, value.AsDataView());
+        Assert.Throws<JavaScriptException>(value.ToObject);
+        Assert.Throws<ArgumentException>(JsValue.Undefined.AsDataView);
     }
-}
+}

+ 156 - 157
Jint.Tests/Runtime/JsonSerializerTests.cs

@@ -1,163 +1,162 @@
 using Jint.Native;
 using Jint.Native.Json;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class JsonSerializerTests
 {
-    public class JsonSerializerTests
+    [Fact]
+    public void CanStringifyBasicTypes()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        Assert.Equal("null", serializer.Serialize(JsValue.Null).ToString());
+        Assert.Equal("true", serializer.Serialize(JsBoolean.True).ToString());
+        Assert.Equal("false", serializer.Serialize(JsBoolean.False).ToString());
+        Assert.Equal("\"\"", serializer.Serialize(new JsString("")).ToString());
+        Assert.Equal("\"abc\"", serializer.Serialize(new JsString("abc")).ToString());
+        Assert.Equal("1", serializer.Serialize(new JsNumber(1)).ToString());
+        Assert.Equal("0.5", serializer.Serialize(new JsNumber(0.5)).ToString());
+        Assert.Equal("{}", serializer.Serialize(new JsObject(engine)).ToString());
+        Assert.Equal("[]", serializer.Serialize(new JsArray(engine)).ToString());
+
+        Assert.Same(JsValue.Undefined, serializer.Serialize(JsValue.Undefined));
+    }
+
+    [Fact]
+    public void EmptyObjectHasNoLineBreakWithSpaceDefined()
     {
-        [Fact]
-        public void CanStringifyBasicTypes()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            Assert.Equal("null", serializer.Serialize(JsValue.Null).ToString());
-            Assert.Equal("true", serializer.Serialize(JsBoolean.True).ToString());
-            Assert.Equal("false", serializer.Serialize(JsBoolean.False).ToString());
-            Assert.Equal("\"\"", serializer.Serialize(new JsString("")).ToString());
-            Assert.Equal("\"abc\"", serializer.Serialize(new JsString("abc")).ToString());
-            Assert.Equal("1", serializer.Serialize(new JsNumber(1)).ToString());
-            Assert.Equal("0.5", serializer.Serialize(new JsNumber(0.5)).ToString());
-            Assert.Equal("{}", serializer.Serialize(new JsObject(engine)).ToString());
-            Assert.Equal("[]", serializer.Serialize(new JsArray(engine)).ToString());
-
-            Assert.Same(JsValue.Undefined, serializer.Serialize(JsValue.Undefined));
-        }
-
-        [Fact]
-        public void EmptyObjectHasNoLineBreakWithSpaceDefined()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-            Assert.Equal("{}", serializer.Serialize(new JsObject(engine), JsValue.Undefined, new JsString("  ")).ToString());
-        }
-
-        [Fact]
-        public void EmptyArrayHasNoLineBreakWithSpaceDefined()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-            Assert.Equal("[]", serializer.Serialize(new JsArray(engine), JsValue.Undefined, new JsString("  ")).ToString());
-        }
-
-        [Fact]
-        public void StringCharactersGetEscaped()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            string actual = serializer.Serialize(new JsString("\"\\\t\r\n\f\r\b\ud834")).ToString();
-            Assert.Equal("\"\\\"\\\\\\t\\r\\n\\f\\r\\b\\ud834\"", actual);
-        }
-
-        [Fact]
-        public void JsonStringOutputIsIndentedWhenSpacerDefined()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            JsObject instance = new JsObject(engine);
-            instance["a"] = "b";
-            instance["b"] = 2;
-            instance["c"] = new JsArray(engine, new JsValue[] { new JsNumber(4), new JsNumber(5), new JsNumber(6) });
-            instance["d"] = true;
-
-            string actual = serializer.Serialize(instance, JsValue.Undefined, new JsNumber(2)).ToString();
-            Assert.Equal("{\n  \"a\": \"b\",\n  \"b\": 2,\n  \"c\": [\n    4,\n    5,\n    6\n  ],\n  \"d\": true\n}", actual);
-        }
-
-        [Fact]
-        public void JsonStringOutputIsCompactWithoutSpacer()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            JsObject instance = new JsObject(engine);
-            instance["a"] = "b";
-            instance["b"] = 2;
-            instance["c"] = new JsArray(engine, new JsValue[] { new JsNumber(4), new JsNumber(5), new JsNumber(6) });
-            instance["d"] = true;
-
-            string actual = serializer.Serialize(instance, JsValue.Undefined, JsValue.Undefined).ToString();
-            Assert.Equal("{\"a\":\"b\",\"b\":2,\"c\":[4,5,6],\"d\":true}", actual);
-        }
-
-        [Fact]
-        public void ArrayWithUndefinedWillBeNull()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            JsArray array = new JsArray(engine, new JsValue[] { JsValue.Undefined, new JsNumber(42) });
-            string actual = serializer.Serialize(array, JsValue.Undefined, JsValue.Undefined).ToString();
-            Assert.Equal("[null,42]", actual);
-        }
-
-        [Fact]
-        public void ObjectPropertyWithUndefinedWillBeSkipped()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            JsObject instance = new JsObject(engine);
-            instance["a"] = JsValue.Undefined;
-            instance["b"] = 42;
-            string actual = serializer.Serialize(instance, JsValue.Undefined, JsValue.Undefined).ToString();
-            Assert.Equal("{\"b\":42}", actual);
-        }
-
-        [Fact]
-        public void NonStringObjectKeyWillSerializedAsString()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            JsObject instance = new JsObject(engine);
-            instance[JsValue.Undefined] = 10;
-            instance[JsValue.Null] = 21;
-            instance[new JsNumber(10)] = 42;
-            string actual = serializer.Serialize(instance, JsValue.Undefined, JsValue.Undefined).ToString();
-            Assert.Equal("{\"10\":42,\"undefined\":10,\"null\":21}", actual);
-        }
-
-        [Fact]
-        public void InfinityAndNaNGetsSerializedAsNull()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-            JsArray array = new JsArray(engine, new JsValue[] { JsNumber.DoubleNegativeInfinity, JsNumber.DoublePositiveInfinity, JsNumber.DoubleNaN });
-            string actual = serializer.Serialize(array, JsValue.Undefined, JsValue.Undefined).ToString();
-            Assert.Equal("[null,null,null]", actual);
-        }
-
-        [Fact]
-        public void ArrayAsReplacedDictatesPropertiesToSerializer()
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            JsObject instance = new JsObject(engine);
-            instance["a"] = 21;
-            instance["b"] = 42;
-            JsValue replacer = new JsArray(engine, new JsValue[] { new JsString("b"), new JsString("z") });
-            string actual = serializer.Serialize(instance, replacer, JsValue.Undefined).ToString();
-            Assert.Equal("{\"b\":42}", actual);
-        }
-
-        [Theory]
-        [InlineData("test123\n456", "\"test123\\n456\"")]
-        [InlineData("test123456\n", "\"test123456\\n\"")]
-        [InlineData("\u0002test\u0002", "\"\\u0002test\\u0002\"")]
-        [InlineData("\u0002tes\tt\u0002", "\"\\u0002tes\\tt\\u0002\"")]
-        [InlineData("t\u0002est\u0002", "\"t\\u0002est\\u0002\"")]
-        [InlineData("test😀123456\n", "\"test😀123456\\n\"")]
-        public void JsonStringEncodingFormatsContentCorrectly(string inputString, string expectedOutput)
-        {
-            using var engine = new Engine();
-            var serializer = new JsonSerializer(engine);
-
-            string actual = serializer.Serialize(new JsString(inputString)).ToString();
-            Assert.Equal(expectedOutput, actual);
-        }
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+        Assert.Equal("{}", serializer.Serialize(new JsObject(engine), JsValue.Undefined, new JsString("  ")).ToString());
+    }
+
+    [Fact]
+    public void EmptyArrayHasNoLineBreakWithSpaceDefined()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+        Assert.Equal("[]", serializer.Serialize(new JsArray(engine), JsValue.Undefined, new JsString("  ")).ToString());
+    }
+
+    [Fact]
+    public void StringCharactersGetEscaped()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        string actual = serializer.Serialize(new JsString("\"\\\t\r\n\f\r\b\ud834")).ToString();
+        Assert.Equal("\"\\\"\\\\\\t\\r\\n\\f\\r\\b\\ud834\"", actual);
+    }
+
+    [Fact]
+    public void JsonStringOutputIsIndentedWhenSpacerDefined()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        JsObject instance = new JsObject(engine);
+        instance["a"] = "b";
+        instance["b"] = 2;
+        instance["c"] = new JsArray(engine, new JsValue[] { new JsNumber(4), new JsNumber(5), new JsNumber(6) });
+        instance["d"] = true;
+
+        string actual = serializer.Serialize(instance, JsValue.Undefined, new JsNumber(2)).ToString();
+        Assert.Equal("{\n  \"a\": \"b\",\n  \"b\": 2,\n  \"c\": [\n    4,\n    5,\n    6\n  ],\n  \"d\": true\n}", actual);
+    }
+
+    [Fact]
+    public void JsonStringOutputIsCompactWithoutSpacer()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        JsObject instance = new JsObject(engine);
+        instance["a"] = "b";
+        instance["b"] = 2;
+        instance["c"] = new JsArray(engine, new JsValue[] { new JsNumber(4), new JsNumber(5), new JsNumber(6) });
+        instance["d"] = true;
+
+        string actual = serializer.Serialize(instance, JsValue.Undefined, JsValue.Undefined).ToString();
+        Assert.Equal("{\"a\":\"b\",\"b\":2,\"c\":[4,5,6],\"d\":true}", actual);
+    }
+
+    [Fact]
+    public void ArrayWithUndefinedWillBeNull()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        JsArray array = new JsArray(engine, new JsValue[] { JsValue.Undefined, new JsNumber(42) });
+        string actual = serializer.Serialize(array, JsValue.Undefined, JsValue.Undefined).ToString();
+        Assert.Equal("[null,42]", actual);
+    }
+
+    [Fact]
+    public void ObjectPropertyWithUndefinedWillBeSkipped()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        JsObject instance = new JsObject(engine);
+        instance["a"] = JsValue.Undefined;
+        instance["b"] = 42;
+        string actual = serializer.Serialize(instance, JsValue.Undefined, JsValue.Undefined).ToString();
+        Assert.Equal("{\"b\":42}", actual);
+    }
+
+    [Fact]
+    public void NonStringObjectKeyWillSerializedAsString()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        JsObject instance = new JsObject(engine);
+        instance[JsValue.Undefined] = 10;
+        instance[JsValue.Null] = 21;
+        instance[new JsNumber(10)] = 42;
+        string actual = serializer.Serialize(instance, JsValue.Undefined, JsValue.Undefined).ToString();
+        Assert.Equal("{\"10\":42,\"undefined\":10,\"null\":21}", actual);
+    }
+
+    [Fact]
+    public void InfinityAndNaNGetsSerializedAsNull()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+        JsArray array = new JsArray(engine, new JsValue[] { JsNumber.DoubleNegativeInfinity, JsNumber.DoublePositiveInfinity, JsNumber.DoubleNaN });
+        string actual = serializer.Serialize(array, JsValue.Undefined, JsValue.Undefined).ToString();
+        Assert.Equal("[null,null,null]", actual);
+    }
+
+    [Fact]
+    public void ArrayAsReplacedDictatesPropertiesToSerializer()
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        JsObject instance = new JsObject(engine);
+        instance["a"] = 21;
+        instance["b"] = 42;
+        JsValue replacer = new JsArray(engine, new JsValue[] { new JsString("b"), new JsString("z") });
+        string actual = serializer.Serialize(instance, replacer, JsValue.Undefined).ToString();
+        Assert.Equal("{\"b\":42}", actual);
+    }
+
+    [Theory]
+    [InlineData("test123\n456", "\"test123\\n456\"")]
+    [InlineData("test123456\n", "\"test123456\\n\"")]
+    [InlineData("\u0002test\u0002", "\"\\u0002test\\u0002\"")]
+    [InlineData("\u0002tes\tt\u0002", "\"\\u0002tes\\tt\\u0002\"")]
+    [InlineData("t\u0002est\u0002", "\"t\\u0002est\\u0002\"")]
+    [InlineData("test😀123456\n", "\"test😀123456\\n\"")]
+    public void JsonStringEncodingFormatsContentCorrectly(string inputString, string expectedOutput)
+    {
+        using var engine = new Engine();
+        var serializer = new JsonSerializer(engine);
+
+        string actual = serializer.Serialize(new JsString(inputString)).ToString();
+        Assert.Equal(expectedOutput, actual);
     }
-}
+}

+ 261 - 262
Jint.Tests/Runtime/JsonTests.cs

@@ -3,316 +3,315 @@ using Jint.Native.Json;
 using Jint.Native.Object;
 using Jint.Runtime;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class JsonTests
 {
-    public class JsonTests
+    [Fact]
+    public void CanParseTabsInProperties()
     {
-        [Fact]
-        public void CanParseTabsInProperties()
-        {
-             var engine = new Engine();
-             const string script = @"JSON.parse(""{\""abc\\tdef\"": \""42\""}"");";
-             var obj = engine.Evaluate(script).AsObject();
-             Assert.True(obj.HasOwnProperty("abc\tdef"));
-        }
+        var engine = new Engine();
+        const string script = @"JSON.parse(""{\""abc\\tdef\"": \""42\""}"");";
+        var obj = engine.Evaluate(script).AsObject();
+        Assert.True(obj.HasOwnProperty("abc\tdef"));
+    }
 
-        [Theory]
-        [InlineData("{\"a\":\"\\\"\"}", "\"")] // " quotation mark
-        [InlineData("{\"a\":\"\\\\\"}", "\\")] // \ reverse solidus
-        [InlineData("{\"a\":\"\\/\"}", "/")] // / solidus
-        [InlineData("{\"a\":\"\\b\"}", "\b")] // backspace
-        [InlineData("{\"a\":\"\\f\"}", "\f")] // formfeed
-        [InlineData("{\"a\":\"\\n\"}", "\n")] // linefeed
-        [InlineData("{\"a\":\"\\r\"}", "\r")] // carriage return
-        [InlineData("{\"a\":\"\\t\"}", "\t")] // horizontal tab
-        [InlineData("{\"a\":\"\\u0000\"}", "\0")]
-        [InlineData("{\"a\":\"\\u0001\"}", "\x01")]
-        [InlineData("{\"a\":\"\\u0061\"}", "a")]
-        [InlineData("{\"a\":\"\\u003C\"}", "<")]
-        [InlineData("{\"a\":\"\\u003E\"}", ">")]
-        [InlineData("{\"a\":\"\\u003c\"}", "<")]
-        [InlineData("{\"a\":\"\\u003e\"}", ">")]
-        public void ShouldParseEscapedCharactersCorrectly(string json, string expectedCharacter)
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+    [Theory]
+    [InlineData("{\"a\":\"\\\"\"}", "\"")] // " quotation mark
+    [InlineData("{\"a\":\"\\\\\"}", "\\")] // \ reverse solidus
+    [InlineData("{\"a\":\"\\/\"}", "/")] // / solidus
+    [InlineData("{\"a\":\"\\b\"}", "\b")] // backspace
+    [InlineData("{\"a\":\"\\f\"}", "\f")] // formfeed
+    [InlineData("{\"a\":\"\\n\"}", "\n")] // linefeed
+    [InlineData("{\"a\":\"\\r\"}", "\r")] // carriage return
+    [InlineData("{\"a\":\"\\t\"}", "\t")] // horizontal tab
+    [InlineData("{\"a\":\"\\u0000\"}", "\0")]
+    [InlineData("{\"a\":\"\\u0001\"}", "\x01")]
+    [InlineData("{\"a\":\"\\u0061\"}", "a")]
+    [InlineData("{\"a\":\"\\u003C\"}", "<")]
+    [InlineData("{\"a\":\"\\u003E\"}", ">")]
+    [InlineData("{\"a\":\"\\u003c\"}", "<")]
+    [InlineData("{\"a\":\"\\u003e\"}", ">")]
+    public void ShouldParseEscapedCharactersCorrectly(string json, string expectedCharacter)
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            var parsedCharacter = parser.Parse(json).AsObject().Get("a").AsString();
+        var parsedCharacter = parser.Parse(json).AsObject().Get("a").AsString();
 
-            Assert.Equal(expectedCharacter, parsedCharacter);
-        }
+        Assert.Equal(expectedCharacter, parsedCharacter);
+    }
 
-        [Theory]
-        [InlineData("{\"a\":1", "Unexpected end of JSON input at position 6")]
-        [InlineData("{\"a\":1},", "Unexpected token ',' in JSON at position 7")]
-        [InlineData("{1}", "Unexpected number in JSON at position 1")]
-        [InlineData("{\"a\" \"a\"}", "Unexpected string in JSON at position 5")]
-        [InlineData("{true}", "Unexpected token 'true' in JSON at position 1")]
-        [InlineData("{null}", "Unexpected token 'null' in JSON at position 1")]
-        [InlineData("{:}", "Unexpected token ':' in JSON at position 1")]
-        [InlineData("\"\\uah\"", "Expected hexadecimal digit in JSON at position 4")]
-        [InlineData("0123", "Unexpected token '1' in JSON at position 1")]  // leading 0 (octal number) not allowed
-        [InlineData("1e+A", "Unexpected token 'A' in JSON at position 3")]
-        [InlineData("truE", "Unexpected token ILLEGAL in JSON at position 0")]
-        [InlineData("nul", "Unexpected token ILLEGAL in JSON at position 0")]
-        [InlineData("\"ab\t\"", "Invalid character in JSON at position 3")] // invalid char in string literal
-        [InlineData("\"ab", "Unexpected end of JSON input at position 3")] // unterminated string literal
-        [InlineData("alpha", "Unexpected token 'a' in JSON at position 0")]
-        [InlineData("[1,\na]", "Unexpected token 'a' in JSON at position 4")] // multiline
-        [InlineData("\x06", "Unexpected token '\x06' in JSON at position 0")] // control char
-        [InlineData("{\"\\v\":1}", "Unexpected token 'v' in JSON at position 3")] // invalid escape sequence
-        [InlineData("[,]", "Unexpected token ',' in JSON at position 1")]
-        [InlineData("{\"key\": ()}", "Unexpected token '(' in JSON at position 8")]
-        [InlineData(".1", "Unexpected token '.' in JSON at position 0")]
-        public void ShouldReportHelpfulSyntaxErrorForInvalidJson(string json, string expectedMessage)
+    [Theory]
+    [InlineData("{\"a\":1", "Unexpected end of JSON input at position 6")]
+    [InlineData("{\"a\":1},", "Unexpected token ',' in JSON at position 7")]
+    [InlineData("{1}", "Unexpected number in JSON at position 1")]
+    [InlineData("{\"a\" \"a\"}", "Unexpected string in JSON at position 5")]
+    [InlineData("{true}", "Unexpected token 'true' in JSON at position 1")]
+    [InlineData("{null}", "Unexpected token 'null' in JSON at position 1")]
+    [InlineData("{:}", "Unexpected token ':' in JSON at position 1")]
+    [InlineData("\"\\uah\"", "Expected hexadecimal digit in JSON at position 4")]
+    [InlineData("0123", "Unexpected token '1' in JSON at position 1")]  // leading 0 (octal number) not allowed
+    [InlineData("1e+A", "Unexpected token 'A' in JSON at position 3")]
+    [InlineData("truE", "Unexpected token ILLEGAL in JSON at position 0")]
+    [InlineData("nul", "Unexpected token ILLEGAL in JSON at position 0")]
+    [InlineData("\"ab\t\"", "Invalid character in JSON at position 3")] // invalid char in string literal
+    [InlineData("\"ab", "Unexpected end of JSON input at position 3")] // unterminated string literal
+    [InlineData("alpha", "Unexpected token 'a' in JSON at position 0")]
+    [InlineData("[1,\na]", "Unexpected token 'a' in JSON at position 4")] // multiline
+    [InlineData("\x06", "Unexpected token '\x06' in JSON at position 0")] // control char
+    [InlineData("{\"\\v\":1}", "Unexpected token 'v' in JSON at position 3")] // invalid escape sequence
+    [InlineData("[,]", "Unexpected token ',' in JSON at position 1")]
+    [InlineData("{\"key\": ()}", "Unexpected token '(' in JSON at position 8")]
+    [InlineData(".1", "Unexpected token '.' in JSON at position 0")]
+    public void ShouldReportHelpfulSyntaxErrorForInvalidJson(string json, string expectedMessage)
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
+        var ex = Assert.ThrowsAny<JavaScriptException>(() =>
         {
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
-            var ex = Assert.ThrowsAny<JavaScriptException>(() =>
-            {
-                parser.Parse(json);
-            });
-
-            Assert.Equal(expectedMessage, ex.Message);
-
-            var error = ex.Error as Native.Error.ErrorInstance;
-            Assert.NotNull(error);
-            Assert.Equal("SyntaxError", error.Get("name"));
-        }
+            parser.Parse(json);
+        });
 
-        [Theory]
-        [InlineData("[[]]", "[\n  []\n]")]
-        [InlineData("[ { a: [{ x: 0 }], b:[]} ]",
-            "[\n  {\n    \"a\": [\n      {\n        \"x\": 0\n      }\n    ],\n    \"b\": []\n  }\n]")]
-        public void ShouldSerializeWithCorrectIndentation(string script, string expectedJson)
-        {
-            var engine = new Engine();
-            engine.SetValue("x", engine.Evaluate(script));
+        Assert.Equal(expectedMessage, ex.Message);
 
-            var result = engine.Evaluate("JSON.stringify(x, null, 2);").AsString();
+        var error = ex.Error as Native.Error.ErrorInstance;
+        Assert.NotNull(error);
+        Assert.Equal("SyntaxError", error.Get("name"));
+    }
 
-            Assert.Equal(expectedJson, result);
-        }
+    [Theory]
+    [InlineData("[[]]", "[\n  []\n]")]
+    [InlineData("[ { a: [{ x: 0 }], b:[]} ]",
+        "[\n  {\n    \"a\": [\n      {\n        \"x\": 0\n      }\n    ],\n    \"b\": []\n  }\n]")]
+    public void ShouldSerializeWithCorrectIndentation(string script, string expectedJson)
+    {
+        var engine = new Engine();
+        engine.SetValue("x", engine.Evaluate(script));
+
+        var result = engine.Evaluate("JSON.stringify(x, null, 2);").AsString();
 
-        [Theory]
-        [InlineData(0)]
-        [InlineData(1)]
-        [InlineData(10)]
-        [InlineData(100)]
-        public void ShouldParseArrayIndependentOfLengthInSameOrder(int numberOfElements)
+        Assert.Equal(expectedJson, result);
+    }
+
+    [Theory]
+    [InlineData(0)]
+    [InlineData(1)]
+    [InlineData(10)]
+    [InlineData(100)]
+    public void ShouldParseArrayIndependentOfLengthInSameOrder(int numberOfElements)
+    {
+        string json = $"[{string.Join(",", Enumerable.Range(0, numberOfElements))}]";
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
+
+        JsValue result = parser.Parse(json);
+        JsArray array = Assert.IsType<JsArray>(result);
+        Assert.Equal((uint)numberOfElements, array.Length);
+        for (int i = 0; i < numberOfElements; i++)
         {
-            string json = $"[{string.Join(",", Enumerable.Range(0, numberOfElements))}]";
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
-
-            JsValue result = parser.Parse(json);
-            JsArray array = Assert.IsType<JsArray>(result);
-            Assert.Equal((uint)numberOfElements, array.Length);
-            for (int i = 0; i < numberOfElements; i++)
-            {
-                Assert.Equal(i, (int)array[i].AsNumber());
-            }
+            Assert.Equal(i, (int)array[i].AsNumber());
         }
+    }
 
-        [Theory]
-        [InlineData(0)]
-        [InlineData(1)]
-        [InlineData(10)]
-        [InlineData(20)]
-        public void ShouldParseStringIndependentOfLength(int stringLength)
-        {
-            string generatedString = string.Join("", Enumerable.Range(0, stringLength).Select(index => 'A' + index));
-            string json = $"\"{generatedString}\"";
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+    [Theory]
+    [InlineData(0)]
+    [InlineData(1)]
+    [InlineData(10)]
+    [InlineData(20)]
+    public void ShouldParseStringIndependentOfLength(int stringLength)
+    {
+        string generatedString = string.Join("", Enumerable.Range(0, stringLength).Select(index => 'A' + index));
+        string json = $"\"{generatedString}\"";
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            string value = parser.Parse(json).AsString();
-            Assert.Equal(generatedString, value, StringComparer.Ordinal);
-        }
+        string value = parser.Parse(json).AsString();
+        Assert.Equal(generatedString, value, StringComparer.Ordinal);
+    }
 
-        [Fact]
-        public void CanParsePrimitivesCorrectly()
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+    [Fact]
+    public void CanParsePrimitivesCorrectly()
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            Assert.Same(JsBoolean.True, parser.Parse("true"));
-            Assert.Same(JsBoolean.False, parser.Parse("false"));
-            Assert.Same(JsValue.Null, parser.Parse("null"));
-        }
+        Assert.Same(JsBoolean.True, parser.Parse("true"));
+        Assert.Same(JsBoolean.False, parser.Parse("false"));
+        Assert.Same(JsValue.Null, parser.Parse("null"));
+    }
 
-        [Fact]
-        public void CanParseNumbersWithAndWithoutSign()
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+    [Fact]
+    public void CanParseNumbersWithAndWithoutSign()
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            Assert.Equal(-1, (int)parser.Parse("-1").AsNumber());
-            Assert.Equal(0, (int)parser.Parse("-0").AsNumber());
-            Assert.Equal(0, (int)parser.Parse("0").AsNumber());
-            Assert.Equal(1, (int)parser.Parse("1").AsNumber());
-        }
+        Assert.Equal(-1, (int)parser.Parse("-1").AsNumber());
+        Assert.Equal(0, (int)parser.Parse("-0").AsNumber());
+        Assert.Equal(0, (int)parser.Parse("0").AsNumber());
+        Assert.Equal(1, (int)parser.Parse("1").AsNumber());
+    }
 
-        [Fact]
-        public void DoesPreservesNumberToMaxSafeInteger()
-        {
-            // see https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-number.max_safe_integer
-            long maxSafeInteger = 9007199254740991;
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+    [Fact]
+    public void DoesPreservesNumberToMaxSafeInteger()
+    {
+        // see https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-number.max_safe_integer
+        long maxSafeInteger = 9007199254740991;
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            Assert.Equal(maxSafeInteger, (long)parser.Parse("9007199254740991").AsNumber());
-        }
+        Assert.Equal(maxSafeInteger, (long)parser.Parse("9007199254740991").AsNumber());
+    }
 
-        [Fact]
-        public void DoesSupportFractionalNumbers()
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+    [Fact]
+    public void DoesSupportFractionalNumbers()
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            Assert.Equal(0.1d, parser.Parse("0.1").AsNumber());
-            Assert.Equal(1.1d, parser.Parse("1.1").AsNumber());
-            Assert.Equal(-1.1d, parser.Parse("-1.1").AsNumber());
-        }
+        Assert.Equal(0.1d, parser.Parse("0.1").AsNumber());
+        Assert.Equal(1.1d, parser.Parse("1.1").AsNumber());
+        Assert.Equal(-1.1d, parser.Parse("-1.1").AsNumber());
+    }
 
-        [Fact]
-        public void DoesSupportScientificNotation()
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+    [Fact]
+    public void DoesSupportScientificNotation()
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            Assert.Equal(100d, parser.Parse("1E2").AsNumber());
-            Assert.Equal(0.01d, parser.Parse("1E-2").AsNumber());
-        }
+        Assert.Equal(100d, parser.Parse("1E2").AsNumber());
+        Assert.Equal(0.01d, parser.Parse("1E-2").AsNumber());
+    }
 
-        [Fact]
-        public void ThrowsExceptionWhenDepthLimitReachedArrays()
-        {
-            string json = GenerateDeepNestedArray(65);
+    [Fact]
+    public void ThrowsExceptionWhenDepthLimitReachedArrays()
+    {
+        string json = GenerateDeepNestedArray(65);
 
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse(json));
-            Assert.Equal("Max. depth level of JSON reached at position 64", ex.Message);
-        }
+        JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse(json));
+        Assert.Equal("Max. depth level of JSON reached at position 64", ex.Message);
+    }
 
-        [Fact]
-        public void ThrowsExceptionWhenDepthLimitReachedObjects()
-        {
-            string json = GenerateDeepNestedObject(65);
+    [Fact]
+    public void ThrowsExceptionWhenDepthLimitReachedObjects()
+    {
+        string json = GenerateDeepNestedObject(65);
 
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse(json));
-            Assert.Equal("Max. depth level of JSON reached at position 320", ex.Message);
-        }
+        JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse(json));
+        Assert.Equal("Max. depth level of JSON reached at position 320", ex.Message);
+    }
 
-        [Fact]
-        public void CanParseMultipleNestedObjects()
-        {
-            string objectA = GenerateDeepNestedObject(63);
-            string objectB = GenerateDeepNestedObject(63);
-            string json = $"{{\"a\":{objectA},\"b\":{objectB} }}";
+    [Fact]
+    public void CanParseMultipleNestedObjects()
+    {
+        string objectA = GenerateDeepNestedObject(63);
+        string objectB = GenerateDeepNestedObject(63);
+        string json = $"{{\"a\":{objectA},\"b\":{objectB} }}";
 
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            ObjectInstance parsed = parser.Parse(json).AsObject();
-            Assert.True(parsed["a"].IsObject());
-            Assert.True(parsed["b"].IsObject());
-        }
+        ObjectInstance parsed = parser.Parse(json).AsObject();
+        Assert.True(parsed["a"].IsObject());
+        Assert.True(parsed["b"].IsObject());
+    }
 
-        [Fact]
-        public void CanParseMultipleNestedArrays()
-        {
-            string arrayA = GenerateDeepNestedArray(63);
-            string arrayB = GenerateDeepNestedArray(63);
-            string json = $"{{\"a\":{arrayA},\"b\":{arrayB} }}";
+    [Fact]
+    public void CanParseMultipleNestedArrays()
+    {
+        string arrayA = GenerateDeepNestedArray(63);
+        string arrayB = GenerateDeepNestedArray(63);
+        string json = $"{{\"a\":{arrayA},\"b\":{arrayB} }}";
 
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            ObjectInstance parsed = parser.Parse(json).AsObject();
-            Assert.True(parsed["a"].IsArray());
-            Assert.True(parsed["b"].IsArray());
-        }
+        ObjectInstance parsed = parser.Parse(json).AsObject();
+        Assert.True(parsed["a"].IsArray());
+        Assert.True(parsed["b"].IsArray());
+    }
 
-        [Fact]
-        public void ArrayAndObjectDepthNotCountedSeparately()
-        {
-            // individual depth is below the default limit, but combined
-            // a max. depth level is reached.
-            string innerArray = GenerateDeepNestedArray(40);
-            string json = GenerateDeepNestedObject(40, innerArray);
+    [Fact]
+    public void ArrayAndObjectDepthNotCountedSeparately()
+    {
+        // individual depth is below the default limit, but combined
+        // a max. depth level is reached.
+        string innerArray = GenerateDeepNestedArray(40);
+        string json = GenerateDeepNestedObject(40, innerArray);
 
-            var engine = new Engine();
-            var parser = new JsonParser(engine);
+        var engine = new Engine();
+        var parser = new JsonParser(engine);
 
-            JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse(json));
-            Assert.Equal("Max. depth level of JSON reached at position 224", ex.Message);
-        }
+        JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse(json));
+        Assert.Equal("Max. depth level of JSON reached at position 224", ex.Message);
+    }
 
-        [Fact]
-        public void CustomMaxDepthOfZeroDisallowsObjects()
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine, maxDepth: 0);
+    [Fact]
+    public void CustomMaxDepthOfZeroDisallowsObjects()
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine, maxDepth: 0);
 
-            JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse("{}"));
-            Assert.Equal("Max. depth level of JSON reached at position 0", ex.Message);
-        }
+        JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse("{}"));
+        Assert.Equal("Max. depth level of JSON reached at position 0", ex.Message);
+    }
 
-        [Fact]
-        public void CustomMaxDepthOfZeroDisallowsArrays()
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine, maxDepth: 0);
+    [Fact]
+    public void CustomMaxDepthOfZeroDisallowsArrays()
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine, maxDepth: 0);
 
-            JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse("[]"));
-            Assert.Equal("Max. depth level of JSON reached at position 0", ex.Message);
-        }
+        JavaScriptException ex = Assert.Throws<JavaScriptException>(() => parser.Parse("[]"));
+        Assert.Equal("Max. depth level of JSON reached at position 0", ex.Message);
+    }
 
-        [Fact]
-        public void MaxDepthDoesNotInfluencePrimitiveValues()
-        {
-            var engine = new Engine();
-            var parser = new JsonParser(engine, maxDepth: 1);
-
-            ObjectInstance parsed = parser.Parse("{\"a\": 2, \"b\": true, \"c\": null, \"d\": \"test\"}").AsObject();
-            Assert.True(parsed["a"].IsNumber());
-            Assert.True(parsed["b"].IsBoolean());
-            Assert.True(parsed["c"].IsNull());
-            Assert.True(parsed["d"].IsString());
-        }
+    [Fact]
+    public void MaxDepthDoesNotInfluencePrimitiveValues()
+    {
+        var engine = new Engine();
+        var parser = new JsonParser(engine, maxDepth: 1);
+
+        ObjectInstance parsed = parser.Parse("{\"a\": 2, \"b\": true, \"c\": null, \"d\": \"test\"}").AsObject();
+        Assert.True(parsed["a"].IsNumber());
+        Assert.True(parsed["b"].IsBoolean());
+        Assert.True(parsed["c"].IsNull());
+        Assert.True(parsed["d"].IsString());
+    }
 
-        [Fact]
-        public void MaxDepthGetsUsedFromEngineOptionsConstraints()
-        {
-            var engine = new Engine(options => options.MaxJsonParseDepth(0));
-            var parser = new JsonParser(engine);
+    [Fact]
+    public void MaxDepthGetsUsedFromEngineOptionsConstraints()
+    {
+        var engine = new Engine(options => options.MaxJsonParseDepth(0));
+        var parser = new JsonParser(engine);
 
-            Assert.Throws<JavaScriptException>(() => parser.Parse("[]"));
-        }
+        Assert.Throws<JavaScriptException>(() => parser.Parse("[]"));
+    }
 
-        private static string GenerateDeepNestedArray(int depth)
-        {
-            string arrayOpen = new string('[', depth);
-            string arrayClose = new string(']', depth);
-            return $"{arrayOpen}{arrayClose}";
-        }
+    private static string GenerateDeepNestedArray(int depth)
+    {
+        string arrayOpen = new string('[', depth);
+        string arrayClose = new string(']', depth);
+        return $"{arrayOpen}{arrayClose}";
+    }
 
-        private static string GenerateDeepNestedObject(int depth)
-        {
-            return GenerateDeepNestedObject(depth, mostInnerValue: "1");
-        }
+    private static string GenerateDeepNestedObject(int depth)
+    {
+        return GenerateDeepNestedObject(depth, mostInnerValue: "1");
+    }
 
-        private static string GenerateDeepNestedObject(int depth, string mostInnerValue)
-        {
-            string objectOpen = string.Concat(Enumerable.Repeat("{\"A\":", depth));
-            string objectClose = new string('}', depth);
-            return $"{objectOpen}{mostInnerValue}{objectClose}";
-        }
+    private static string GenerateDeepNestedObject(int depth, string mostInnerValue)
+    {
+        string objectOpen = string.Concat(Enumerable.Repeat("{\"A\":", depth));
+        string objectClose = new string('}', depth);
+        return $"{objectOpen}{mostInnerValue}{objectClose}";
     }
-}
+}

+ 95 - 96
Jint.Tests/Runtime/MethodAmbiguityTests.cs

@@ -2,16 +2,16 @@
 using System.Dynamic;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class MethodAmbiguityTests : IDisposable
 {
-    public class MethodAmbiguityTests : IDisposable
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public MethodAmbiguityTests()
-        {
-            _engine = new Engine(cfg => cfg
-                .AllowOperatorOverloading())
+    public MethodAmbiguityTests()
+    {
+        _engine = new Engine(cfg => cfg
+                    .AllowOperatorOverloading())
                 .SetValue("log", new Action<object>(Console.WriteLine))
                 .SetValue("throws", new Func<Action, Exception>(Assert.Throws<Exception>))
                 .SetValue("assert", new Action<bool>(Assert.True))
@@ -20,41 +20,41 @@ namespace Jint.Tests.Runtime
                 .SetValue("TestClass", typeof(TestClass))
                 .SetValue("ChildTestClass", typeof(ChildTestClass))
             ;
-        }
-
-        void IDisposable.Dispose()
-        {
-        }
-
-        private void RunTest(string source)
-        {
-            _engine.Execute(source);
-        }
-
-        public class TestClass
-        {
-            public string this[int index] => "int";
-            public string this[string index] => "string";
-            public int TestMethod(double a, string b, double c) => 0;
-            public int TestMethod(double a, double b, double c) => 1;
-            public int TestMethod(TestClass a, string b, double c) => 2;
-            public int TestMethod(TestClass a, TestClass b, double c) => 3;
-            public int TestMethod(TestClass a, TestClass b, TestClass c) => 4;
-            public int TestMethod(TestClass a, double b, string c) => 5;
-            public int TestMethod(ChildTestClass a, double b, string c) => 6;
-            public int TestMethod(ChildTestClass a, string b, JsValue c) => 7;
-
-            public static implicit operator TestClass(double i) => new TestClass();
-            public static implicit operator double(TestClass tc) => 0;
-            public static explicit operator string(TestClass tc) => "";
-        }
-
-        public class ChildTestClass : TestClass { }
-
-        [Fact]
-        public void BestMatchingMethodShouldBeCalled()
-        {
-            RunTest(@"
+    }
+
+    void IDisposable.Dispose()
+    {
+    }
+
+    private void RunTest(string source)
+    {
+        _engine.Execute(source);
+    }
+
+    public class TestClass
+    {
+        public string this[int index] => "int";
+        public string this[string index] => "string";
+        public int TestMethod(double a, string b, double c) => 0;
+        public int TestMethod(double a, double b, double c) => 1;
+        public int TestMethod(TestClass a, string b, double c) => 2;
+        public int TestMethod(TestClass a, TestClass b, double c) => 3;
+        public int TestMethod(TestClass a, TestClass b, TestClass c) => 4;
+        public int TestMethod(TestClass a, double b, string c) => 5;
+        public int TestMethod(ChildTestClass a, double b, string c) => 6;
+        public int TestMethod(ChildTestClass a, string b, JsValue c) => 7;
+
+        public static implicit operator TestClass(double i) => new TestClass();
+        public static implicit operator double(TestClass tc) => 0;
+        public static explicit operator string(TestClass tc) => "";
+    }
+
+    public class ChildTestClass : TestClass { }
+
+    [Fact]
+    public void BestMatchingMethodShouldBeCalled()
+    {
+        RunTest(@"
                 var tc = new TestClass();
                 var cc = new ChildTestClass();
 
@@ -72,41 +72,41 @@ namespace Jint.Tests.Runtime
                 equal(6, tc.TestMethod(cc, 0, tc));
                 equal(7, tc.TestMethod(cc, '', {}));
             ");
-        }
+    }
 
-        [Fact]
-        public void IndexerCachesMethodsCorrectly()
-        {
-            RunTest(@"
+    [Fact]
+    public void IndexerCachesMethodsCorrectly()
+    {
+        RunTest(@"
                 var tc = new TestClass();
                 equal('string:int', tc['Whistler'] + ':' + tc[10]);
                 equal('int:string', tc[10] + ':' + tc['Whistler']);
             ");
-        }
-
-        [Fact]
-        public void ShouldFavorOtherOverloadsOverObjectParameter()
-        {
-            var engine = new Engine(cfg => cfg.AllowOperatorOverloading());
-            engine.SetValue("Class1", TypeReference.CreateTypeReference<Class1>(engine));
-            engine.SetValue("Class2", TypeReference.CreateTypeReference<Class2>(engine));
-
-            Assert.Equal("Class1.Double[]", engine.Evaluate("Class1.Print([ 1, 2 ]);"));
-            Assert.Equal("Class1.ExpandoObject", engine.Evaluate("Class1.Print({ x: 1, y: 2 });"));
-            Assert.Equal("Class1.Int32", engine.Evaluate("Class1.Print(5);"));
-            Assert.Equal("Class2.Double[]", engine.Evaluate("Class2.Print([ 1, 2 ]); "));
-            Assert.Equal("Class2.ExpandoObject", engine.Evaluate("Class2.Print({ x: 1, y: 2 });"));
-            Assert.Equal("Class2.Int32", engine.Evaluate("Class2.Print(5);"));
-            Assert.Equal("Class2.Object", engine.Evaluate("Class2.Print(() => '');"));
-        }
-
-        [Fact]
-        public void ShouldMatchCorrectConstructors()
-        {
-            Engine engine = new Engine();
-            engine.SetValue("MyClass", TypeReference.CreateTypeReference(engine, typeof(Class3)));
-
-            engine.Execute(@"
+    }
+
+    [Fact]
+    public void ShouldFavorOtherOverloadsOverObjectParameter()
+    {
+        var engine = new Engine(cfg => cfg.AllowOperatorOverloading());
+        engine.SetValue("Class1", TypeReference.CreateTypeReference<Class1>(engine));
+        engine.SetValue("Class2", TypeReference.CreateTypeReference<Class2>(engine));
+
+        Assert.Equal("Class1.Double[]", engine.Evaluate("Class1.Print([ 1, 2 ]);"));
+        Assert.Equal("Class1.ExpandoObject", engine.Evaluate("Class1.Print({ x: 1, y: 2 });"));
+        Assert.Equal("Class1.Int32", engine.Evaluate("Class1.Print(5);"));
+        Assert.Equal("Class2.Double[]", engine.Evaluate("Class2.Print([ 1, 2 ]); "));
+        Assert.Equal("Class2.ExpandoObject", engine.Evaluate("Class2.Print({ x: 1, y: 2 });"));
+        Assert.Equal("Class2.Int32", engine.Evaluate("Class2.Print(5);"));
+        Assert.Equal("Class2.Object", engine.Evaluate("Class2.Print(() => '');"));
+    }
+
+    [Fact]
+    public void ShouldMatchCorrectConstructors()
+    {
+        Engine engine = new Engine();
+        engine.SetValue("MyClass", TypeReference.CreateTypeReference(engine, typeof(Class3)));
+
+        engine.Execute(@"
                 const a = new MyClass();
                 a.Print(1); // Works
                 a.Print([1, 2]); // Works
@@ -114,34 +114,33 @@ namespace Jint.Tests.Runtime
                 const b = new MyClass(1); // Works
                 const c = new MyClass([1, 2]); // Throws 'an object must implement IConvertible' exception
 			");
-        }
+    }
 
-        private struct Class1
-        {
-            public static string Print(ExpandoObject eo) => nameof(Class1) + "." + nameof(ExpandoObject);
-            public static string Print(double[] a) => nameof(Class1) + "." + nameof(Double) + "[]";
-            public static string Print(int i) => nameof(Class1) + "." + nameof(Int32);
-        }
+    private struct Class1
+    {
+        public static string Print(ExpandoObject eo) => nameof(Class1) + "." + nameof(ExpandoObject);
+        public static string Print(double[] a) => nameof(Class1) + "." + nameof(Double) + "[]";
+        public static string Print(int i) => nameof(Class1) + "." + nameof(Int32);
+    }
 
-        private struct Class2
-        {
-            public static string Print(ExpandoObject eo) => nameof(Class2) + "." + nameof(ExpandoObject);
-            public static string Print(double[] a) => nameof(Class2) + "." + nameof(Double) + "[]";
-            public static string Print(int i) => nameof(Class2) + "." + nameof(Int32);
-            public static string Print(object o) => nameof(Class2) + "." + nameof(Object);
-        }
+    private struct Class2
+    {
+        public static string Print(ExpandoObject eo) => nameof(Class2) + "." + nameof(ExpandoObject);
+        public static string Print(double[] a) => nameof(Class2) + "." + nameof(Double) + "[]";
+        public static string Print(int i) => nameof(Class2) + "." + nameof(Int32);
+        public static string Print(object o) => nameof(Class2) + "." + nameof(Object);
+    }
 
-        public class Class3
-        {
-            public Class3() { }
+    public class Class3
+    {
+        public Class3() { }
 
-            public Class3(int a) => Console.WriteLine("Class1(int a): " + a);
+        public Class3(int a) => Console.WriteLine("Class1(int a): " + a);
 
-            public Class3(object a) => Console.WriteLine("Class1(object a): " + a);
+        public Class3(object a) => Console.WriteLine("Class1(object a): " + a);
 
-            public void Print(int a) => Console.WriteLine("Print(int a): " + a);
+        public void Print(int a) => Console.WriteLine("Print(int a): " + a);
 
-            public void Print(object a) => Console.WriteLine("Print(object a): " + a);
-        }
+        public void Print(object a) => Console.WriteLine("Print(object a): " + a);
     }
-}
+}

+ 76 - 77
Jint.Tests/Runtime/NullPropagation.cs

@@ -2,69 +2,69 @@
 using Jint.Runtime;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class NullPropagation
 {
-    public class NullPropagation
+    public class NullPropagationReferenceResolver : IReferenceResolver
     {
-        public class NullPropagationReferenceResolver : IReferenceResolver
+        public bool TryUnresolvableReference(Engine engine, Reference reference, out JsValue value)
         {
-            public bool TryUnresolvableReference(Engine engine, Reference reference, out JsValue value)
-            {
-                value = reference.Base;
-                return true;
-            }
+            value = reference.Base;
+            return true;
+        }
 
-            public bool TryPropertyReference(Engine engine, Reference reference, ref JsValue value)
-            {
-                return value.IsNull() || value.IsUndefined();
-            }
+        public bool TryPropertyReference(Engine engine, Reference reference, ref JsValue value)
+        {
+            return value.IsNull() || value.IsUndefined();
+        }
 
-            public bool TryGetCallable(Engine engine, object callee, out JsValue value)
+        public bool TryGetCallable(Engine engine, object callee, out JsValue value)
+        {
+            if (callee is Reference reference)
             {
-                if (callee is Reference reference)
+                var name = reference.ReferencedName.AsString();
+                if (name == "filter")
                 {
-                    var name = reference.ReferencedName.AsString();
-                    if (name == "filter")
-                    {
-                        value = new ClrFunction(engine, "map", (thisObj, values) => engine.Realm.Intrinsics.Array.ArrayCreate(0));
-                        return true;
-                    }
+                    value = new ClrFunction(engine, "map", (thisObj, values) => engine.Realm.Intrinsics.Array.ArrayCreate(0));
+                    return true;
                 }
-
-                value = new ClrFunction(engine, "anonymous", (thisObj, values) => thisObj);
-                return true;
             }
 
-            public bool CheckCoercible(JsValue value)
-            {
-                return true;
-            }
+            value = new ClrFunction(engine, "anonymous", (thisObj, values) => thisObj);
+            return true;
         }
 
-        [Fact]
-        public void CanCallFilterOnNull()
+        public bool CheckCoercible(JsValue value)
         {
-            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
+            return true;
+        }
+    }
+
+    [Fact]
+    public void CanCallFilterOnNull()
+    {
+        var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
-            const string Script = @"
+        const string Script = @"
 var input = {};
 
 var output = { Tags : input.Tags.filter(x=>x!=null) };
 ";
 
-            engine.Execute(Script);
+        engine.Execute(Script);
 
-            var output = engine.GetValue("output").AsObject();
+        var output = engine.GetValue("output").AsObject();
 
-            Assert.True(output.Get("Tags").IsArray());
-        }
+        Assert.True(output.Get("Tags").IsArray());
+    }
 
-        [Fact]
-        public void NullPropagationTest()
-        {
-            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
+    [Fact]
+    public void NullPropagationTest()
+    {
+        var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
-            const string Script = @"
+        const string Script = @"
 var input = {
 	Address : null
 };
@@ -79,28 +79,28 @@ var output = {
 };
 ";
 
-            engine.Execute(Script);
+        engine.Execute(Script);
 
-            var address = engine.GetValue("address");
-            var city = engine.GetValue("city");
-            var length = engine.GetValue("length");
-            var output = engine.GetValue("output").AsObject();
+        var address = engine.GetValue("address");
+        var city = engine.GetValue("city");
+        var length = engine.GetValue("length");
+        var output = engine.GetValue("output").AsObject();
 
-            Assert.Equal(JsValue.Null, address);
-            Assert.Equal(JsValue.Null, city);
-            Assert.Equal(JsValue.Null, length);
+        Assert.Equal(JsValue.Null, address);
+        Assert.Equal(JsValue.Null, city);
+        Assert.Equal(JsValue.Null, length);
 
-            Assert.Equal(JsValue.Null, output.Get("Count1"));
-            Assert.Equal(JsValue.Undefined, output.Get("Count2"));
-        }
+        Assert.Equal(JsValue.Null, output.Get("Count1"));
+        Assert.Equal(JsValue.Undefined, output.Get("Count2"));
+    }
 
-        [Fact]
-        public void NullPropagationFromArg()
-        {
-            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
+    [Fact]
+    public void NullPropagationFromArg()
+    {
+        var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
 
-            const string Script = @"
+        const string Script = @"
 function test(arg) {
     return arg.Name;
 }
@@ -109,39 +109,38 @@ function test2(arg) {
     return arg.Name.toUpperCase();
 }
 ";
-            engine.Execute(Script);
-            var result = engine.Invoke("test", JsValue.Null);
+        engine.Execute(Script);
+        var result = engine.Invoke("test", JsValue.Null);
 
-            Assert.Equal(JsValue.Null, result);
+        Assert.Equal(JsValue.Null, result);
 
-            result = engine.Invoke("test2", JsValue.Null);
+        result = engine.Invoke("test2", JsValue.Null);
 
-            Assert.Equal(JsValue.Null, result);
-        }
+        Assert.Equal(JsValue.Null, result);
+    }
 
-        [Fact]
-        public void NullPropagationShouldNotAffectOperators()
-        {
-            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
+    [Fact]
+    public void NullPropagationShouldNotAffectOperators()
+    {
+        var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
-            var jsObject = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
-            jsObject.Set("NullField", JsValue.Null);
+        var jsObject = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
+        jsObject.Set("NullField", JsValue.Null);
 
-            var script = @"
+        var script = @"
 this.is_nullfield_not_null = this.NullField !== null;
 this.is_notnullfield_not_null = this.NotNullField !== null;
 this.has_emptyfield_not_null = this.EmptyField !== null;
 ";
 
-            var wrapperScript = $@"function ExecutePatchScript(docInner){{ (function(doc){{ {script} }}).apply(docInner); }};";
+        var wrapperScript = $@"function ExecutePatchScript(docInner){{ (function(doc){{ {script} }}).apply(docInner); }};";
 
-            engine.Execute(wrapperScript, "main.js");
+        engine.Execute(wrapperScript, "main.js");
 
-            engine.Invoke("ExecutePatchScript", jsObject);
+        engine.Invoke("ExecutePatchScript", jsObject);
 
-            Assert.False(jsObject.Get("is_nullfield_not_null").AsBoolean());
-            Assert.True(jsObject.Get("is_notnullfield_not_null").AsBoolean());
-            Assert.True(jsObject.Get("has_emptyfield_not_null").AsBoolean());
-        }
+        Assert.False(jsObject.Get("is_nullfield_not_null").AsBoolean());
+        Assert.True(jsObject.Get("is_notnullfield_not_null").AsBoolean());
+        Assert.True(jsObject.Get("has_emptyfield_not_null").AsBoolean());
     }
-}
+}

+ 134 - 135
Jint.Tests/Runtime/NumberTests.cs

@@ -1,148 +1,147 @@
 using Jint.Runtime;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class NumberTests
 {
-    public class NumberTests
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public NumberTests()
-        {
-            _engine = new Engine()
-                    .SetValue("log", new Action<object>(Console.WriteLine))
-                    .SetValue("assert", new Action<bool>(Assert.True))
-                    .SetValue("equal", new Action<object, object>(Assert.Equal));
-        }
+    public NumberTests()
+    {
+        _engine = new Engine()
+            .SetValue("log", new Action<object>(Console.WriteLine))
+            .SetValue("assert", new Action<bool>(Assert.True))
+            .SetValue("equal", new Action<object, object>(Assert.Equal));
+    }
 
-        private void RunTest(string source)
-        {
-            _engine.Execute(source);
-        }
+    private void RunTest(string source)
+    {
+        _engine.Execute(source);
+    }
 
-        [Theory]
-        [InlineData(1, "3.0e+0")]
-        [InlineData(50, "3.00000000000000000000000000000000000000000000000000e+0")]
-        [InlineData(100, "3.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0")]
-        public void ToExponential(int fractionDigits, string result)
-        {
-            var value = _engine.Evaluate($"(3).toExponential({fractionDigits}).toString()").AsString();
-            Assert.Equal(result, value);
-        }
+    [Theory]
+    [InlineData(1, "3.0e+0")]
+    [InlineData(50, "3.00000000000000000000000000000000000000000000000000e+0")]
+    [InlineData(100, "3.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0")]
+    public void ToExponential(int fractionDigits, string result)
+    {
+        var value = _engine.Evaluate($"(3).toExponential({fractionDigits}).toString()").AsString();
+        Assert.Equal(result, value);
+    }
 
-        [Theory]
-        [InlineData(1, "3.0")]
-        [InlineData(50, "3.00000000000000000000000000000000000000000000000000")]
-        [InlineData(99, "3.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
-        public void ToFixed(int fractionDigits, string result)
-        {
-            var value = _engine.Evaluate($"(3).toFixed({fractionDigits}).toString()").AsString();
-            Assert.Equal(result, value);
-        }
+    [Theory]
+    [InlineData(1, "3.0")]
+    [InlineData(50, "3.00000000000000000000000000000000000000000000000000")]
+    [InlineData(99, "3.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
+    public void ToFixed(int fractionDigits, string result)
+    {
+        var value = _engine.Evaluate($"(3).toFixed({fractionDigits}).toString()").AsString();
+        Assert.Equal(result, value);
+    }
 
-        [Fact]
-        public void ToFixedWith100FractionDigitsThrows()
-        {
-            var ex = Assert.Throws<JavaScriptException>(() => _engine.Evaluate($"(3).toFixed(100)"));
-            Assert.Equal("100 fraction digits is not supported due to .NET format specifier limitation", ex.Message);
-        }
+    [Fact]
+    public void ToFixedWith100FractionDigitsThrows()
+    {
+        var ex = Assert.Throws<JavaScriptException>(() => _engine.Evaluate($"(3).toFixed(100)"));
+        Assert.Equal("100 fraction digits is not supported due to .NET format specifier limitation", ex.Message);
+    }
 
-        [Theory]
-        [InlineData(1, "3")]
-        [InlineData(50, "3.0000000000000000000000000000000000000000000000000")]
-        [InlineData(100, "3.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
-        public void ToPrecision(int fractionDigits, string result)
-        {
-            var value = _engine.Evaluate($"(3).toPrecision({fractionDigits}).toString()").AsString();
-            Assert.Equal(result, value);
-        }
+    [Theory]
+    [InlineData(1, "3")]
+    [InlineData(50, "3.0000000000000000000000000000000000000000000000000")]
+    [InlineData(100, "3.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
+    public void ToPrecision(int fractionDigits, string result)
+    {
+        var value = _engine.Evaluate($"(3).toPrecision({fractionDigits}).toString()").AsString();
+        Assert.Equal(result, value);
+    }
 
-        [Theory]
-        [InlineData("1.7976931348623157e+308", double.MaxValue)]
-        public void ParseFloat(string input, double result)
-        {
-            var value = _engine.Evaluate($"parseFloat('{input}')").AsNumber();
-            Assert.Equal(result, value);
-        }
+    [Theory]
+    [InlineData("1.7976931348623157e+308", double.MaxValue)]
+    public void ParseFloat(string input, double result)
+    {
+        var value = _engine.Evaluate($"parseFloat('{input}')").AsNumber();
+        Assert.Equal(result, value);
+    }
 
-        // Results from node -v v18.18.0.
-        [Theory]
-        // Thousand separators.
-        [InlineData("1000000", "en-US", "1,000,000")]
-        [InlineData("1000000", "en-GB", "1,000,000")]
-        [InlineData("1000000", "de-DE", "1.000.000")]
-        // TODO. Fails in Win CI due to U+2009
-        // Check https://learn.microsoft.com/en-us/dotnet/core/extensions/globalization-icu
-        // [InlineData("1000000", "fr-FR", "1 000 000")] 
-        [InlineData("1000000", "es-ES", "1.000.000")]
-        [InlineData("1000000", "es-LA", "1.000.000")]
-        [InlineData("1000000", "es-MX", "1,000,000")]
-        [InlineData("1000000", "es-AR", "1.000.000")]
-        [InlineData("1000000", "es-CL", "1.000.000")]
-        // Comma separator.
-        [InlineData("1,23", "en-US", "23")]
-        [InlineData("1,23", "en-GB", "23")]
-        [InlineData("1,23", "de-DE", "23")]
-        [InlineData("1,23", "fr-FR", "23")]
-        [InlineData("1,23", "es-ES", "23")]
-        [InlineData("1,23", "es-LA", "23")]
-        [InlineData("1,23", "es-MX", "23")]
-        [InlineData("1,23", "es-AR", "23")]
-        [InlineData("1,23", "es-CL", "23")]
-        // Dot deicimal separator.
-        [InlineData("1.23", "en-US", "1.23")]
-        [InlineData("1.23", "en-GB", "1.23")]
-        [InlineData("1.23", "de-DE", "1,23")]
-        [InlineData("1.23", "fr-FR", "1,23")]
-        [InlineData("1.23", "es-ES", "1,23")]
-        [InlineData("1.23", "es-LA", "1,23")]
-        [InlineData("1.23", "es-MX", "1.23")]
-        [InlineData("1.23", "es-AR", "1,23")]
-        [InlineData("1.23", "es-CL", "1,23")]
-        // Scientific notation.
-        [InlineData("1e6", "en-US", "1,000,000")]
-        [InlineData("1e6", "en-GB", "1,000,000")]
-        [InlineData("1e6", "de-DE", "1.000.000")]
-        // TODO. Fails in Win CI due to U+2009
-        // Check https://learn.microsoft.com/en-us/dotnet/core/extensions/globalization-icu
-        // [InlineData("1000000", "fr-FR", "1 000 000")]
-        [InlineData("1e6", "es-ES", "1.000.000")]
-        [InlineData("1e6", "es-LA", "1.000.000")]
-        [InlineData("1e6", "es-MX", "1,000,000")]
-        [InlineData("1e6", "es-AR", "1.000.000")]
-        [InlineData("1e6", "es-CL", "1.000.000")]
-        // Returns the correct max decimal degits for the respective cultures, rounded down.
-        [InlineData("1.234444449", "en-US", "1.234")]
-        [InlineData("1.234444449", "en-GB", "1.234")]
-        [InlineData("1.234444449", "de-DE", "1,234")]
-        [InlineData("1.234444449", "fr-FR", "1,234")]
-        [InlineData("1.234444449", "es-ES", "1,234")]
-        [InlineData("1.234444449", "es-LA", "1,234")]
-        [InlineData("1.234444449", "es-MX", "1.234")]
-        [InlineData("1.234444449", "es-AR", "1,234")]
-        [InlineData("1.234444449", "es-CL", "1,234")]
-        // Returns the correct max decimal degits for the respective cultures, rounded up.
-        [InlineData("1.234500001", "en-US", "1.235")]
-        [InlineData("1.234500001", "en-GB", "1.235")]
-        [InlineData("1.234500001", "de-DE", "1,235")]
-        [InlineData("1.234500001", "fr-FR", "1,235")]
-        [InlineData("1.234500001", "es-ES", "1,235")]
-        [InlineData("1.234500001", "es-LA", "1,235")]
-        [InlineData("1.234500001", "es-MX", "1.235")]
-        [InlineData("1.234500001", "es-AR", "1,235")]
-        [InlineData("1.234500001", "es-CL", "1,235")]
-        public void ToLocaleString(string parseNumber, string culture, string result)
-        {
-            var value = _engine.Evaluate($"({parseNumber}).toLocaleString('{culture}')").AsString();
-            Assert.Equal(result, value);
-        }
+    // Results from node -v v18.18.0.
+    [Theory]
+    // Thousand separators.
+    [InlineData("1000000", "en-US", "1,000,000")]
+    [InlineData("1000000", "en-GB", "1,000,000")]
+    [InlineData("1000000", "de-DE", "1.000.000")]
+    // TODO. Fails in Win CI due to U+2009
+    // Check https://learn.microsoft.com/en-us/dotnet/core/extensions/globalization-icu
+    // [InlineData("1000000", "fr-FR", "1 000 000")] 
+    [InlineData("1000000", "es-ES", "1.000.000")]
+    [InlineData("1000000", "es-LA", "1.000.000")]
+    [InlineData("1000000", "es-MX", "1,000,000")]
+    [InlineData("1000000", "es-AR", "1.000.000")]
+    [InlineData("1000000", "es-CL", "1.000.000")]
+    // Comma separator.
+    [InlineData("1,23", "en-US", "23")]
+    [InlineData("1,23", "en-GB", "23")]
+    [InlineData("1,23", "de-DE", "23")]
+    [InlineData("1,23", "fr-FR", "23")]
+    [InlineData("1,23", "es-ES", "23")]
+    [InlineData("1,23", "es-LA", "23")]
+    [InlineData("1,23", "es-MX", "23")]
+    [InlineData("1,23", "es-AR", "23")]
+    [InlineData("1,23", "es-CL", "23")]
+    // Dot deicimal separator.
+    [InlineData("1.23", "en-US", "1.23")]
+    [InlineData("1.23", "en-GB", "1.23")]
+    [InlineData("1.23", "de-DE", "1,23")]
+    [InlineData("1.23", "fr-FR", "1,23")]
+    [InlineData("1.23", "es-ES", "1,23")]
+    [InlineData("1.23", "es-LA", "1,23")]
+    [InlineData("1.23", "es-MX", "1.23")]
+    [InlineData("1.23", "es-AR", "1,23")]
+    [InlineData("1.23", "es-CL", "1,23")]
+    // Scientific notation.
+    [InlineData("1e6", "en-US", "1,000,000")]
+    [InlineData("1e6", "en-GB", "1,000,000")]
+    [InlineData("1e6", "de-DE", "1.000.000")]
+    // TODO. Fails in Win CI due to U+2009
+    // Check https://learn.microsoft.com/en-us/dotnet/core/extensions/globalization-icu
+    // [InlineData("1000000", "fr-FR", "1 000 000")]
+    [InlineData("1e6", "es-ES", "1.000.000")]
+    [InlineData("1e6", "es-LA", "1.000.000")]
+    [InlineData("1e6", "es-MX", "1,000,000")]
+    [InlineData("1e6", "es-AR", "1.000.000")]
+    [InlineData("1e6", "es-CL", "1.000.000")]
+    // Returns the correct max decimal degits for the respective cultures, rounded down.
+    [InlineData("1.234444449", "en-US", "1.234")]
+    [InlineData("1.234444449", "en-GB", "1.234")]
+    [InlineData("1.234444449", "de-DE", "1,234")]
+    [InlineData("1.234444449", "fr-FR", "1,234")]
+    [InlineData("1.234444449", "es-ES", "1,234")]
+    [InlineData("1.234444449", "es-LA", "1,234")]
+    [InlineData("1.234444449", "es-MX", "1.234")]
+    [InlineData("1.234444449", "es-AR", "1,234")]
+    [InlineData("1.234444449", "es-CL", "1,234")]
+    // Returns the correct max decimal degits for the respective cultures, rounded up.
+    [InlineData("1.234500001", "en-US", "1.235")]
+    [InlineData("1.234500001", "en-GB", "1.235")]
+    [InlineData("1.234500001", "de-DE", "1,235")]
+    [InlineData("1.234500001", "fr-FR", "1,235")]
+    [InlineData("1.234500001", "es-ES", "1,235")]
+    [InlineData("1.234500001", "es-LA", "1,235")]
+    [InlineData("1.234500001", "es-MX", "1.235")]
+    [InlineData("1.234500001", "es-AR", "1,235")]
+    [InlineData("1.234500001", "es-CL", "1,235")]
+    public void ToLocaleString(string parseNumber, string culture, string result)
+    {
+        var value = _engine.Evaluate($"({parseNumber}).toLocaleString('{culture}')").AsString();
+        Assert.Equal(result, value);
+    }
 
-        [Theory]
-        // Does not add extra zeros of there is no cuture argument.
-        [InlineData("123456")]
-        public void ToLocaleStringNoArg(string parseNumber)
-        {
-            var value = _engine.Evaluate($"({parseNumber}).toLocaleString()").AsString();
-            Assert.DoesNotContain(".0", value);
-        }
+    [Theory]
+    // Does not add extra zeros of there is no cuture argument.
+    [InlineData("123456")]
+    public void ToLocaleStringNoArg(string parseNumber)
+    {
+        var value = _engine.Evaluate($"({parseNumber}).toLocaleString()").AsString();
+        Assert.DoesNotContain(".0", value);
     }
-}
+}

+ 35 - 36
Jint.Tests/Runtime/ObjectInstanceTests.cs

@@ -1,32 +1,32 @@
 using Jint.Native;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class ObjectInstanceTests
 {
-    public class ObjectInstanceTests
+    [Fact]
+    public void RemovingFirstPropertyFromObjectInstancePropertiesBucketAndEnumerating()
     {
-        [Fact]
-        public void RemovingFirstPropertyFromObjectInstancePropertiesBucketAndEnumerating()
-        {
-            var engine = new Engine();
-            var instance = new JsObject(engine);
-            instance.FastSetDataProperty("bare", JsValue.Null);
-            instance.FastSetDataProperty("scope", JsValue.Null);
-            instance.RemoveOwnProperty("bare");
-            var propertyNames = instance.GetOwnProperties().Select(x => x.Key).ToList();
-            Assert.Equal(new JsValue[] { "scope" }, propertyNames);
-        }
+        var engine = new Engine();
+        var instance = new JsObject(engine);
+        instance.FastSetDataProperty("bare", JsValue.Null);
+        instance.FastSetDataProperty("scope", JsValue.Null);
+        instance.RemoveOwnProperty("bare");
+        var propertyNames = instance.GetOwnProperties().Select(x => x.Key).ToList();
+        Assert.Equal(new JsValue[] { "scope" }, propertyNames);
+    }
 
-        [Theory]
-        [InlineData("Array")]
-        [InlineData("Boolean")]
-        [InlineData("Date")]
-        [InlineData("Error")]
-        [InlineData("Number")]
-        [InlineData("Object")]
-        [InlineData("String")]
-        public void ExtendingObjects(string baseType)
-        {
-            var code = $@"
+    [Theory]
+    [InlineData("Array")]
+    [InlineData("Boolean")]
+    [InlineData("Date")]
+    [InlineData("Error")]
+    [InlineData("Number")]
+    [InlineData("Object")]
+    [InlineData("String")]
+    public void ExtendingObjects(string baseType)
+    {
+        var code = $@"
                 class My{baseType} extends {baseType} {{
                     constructor(...args) {{
                         super(...args);
@@ -35,17 +35,16 @@ namespace Jint.Tests.Runtime
                 const o = new My{baseType}();
                 o.constructor === My{baseType}";
 
-            var engine = new Engine();
-            Assert.True(engine.Evaluate(code).AsBoolean());
-        }
+        var engine = new Engine();
+        Assert.True(engine.Evaluate(code).AsBoolean());
+    }
 
-        [Fact]
-        public void ShouldHavePrototypeInPlaceByDefault()
-        {
-            var engine = new Engine();
-            var instance = new JsObject(engine);
-            Assert.NotNull(instance.GetPrototypeOf());
-            Assert.Equal("[object Object]", instance.ToString());
-        }
+    [Fact]
+    public void ShouldHavePrototypeInPlaceByDefault()
+    {
+        var engine = new Engine();
+        var instance = new JsObject(engine);
+        Assert.NotNull(instance.GetPrototypeOf());
+        Assert.Equal("[object Object]", instance.ToString());
     }
-}
+}

+ 146 - 147
Jint.Tests/Runtime/OperatorOverloadingTests.cs

@@ -1,126 +1,126 @@
 using Jint.Native.String;
 using Jint.Runtime.Interop;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class OperatorOverloadingTests
 {
-    public class OperatorOverloadingTests
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public OperatorOverloadingTests()
-        {
-            _engine = new Engine(cfg => cfg
+    public OperatorOverloadingTests()
+    {
+        _engine = new Engine(cfg => cfg
                 .AllowOperatorOverloading())
-                .SetValue("log", new Action<object>(Console.WriteLine))
-                .SetValue("assert", new Action<bool>(Assert.True))
-                .SetValue("assertFalse", new Action<bool>(Assert.False))
-                .SetValue("equal", new Action<object, object>(Assert.Equal))
-                .SetValue("Vector2", typeof(Vector2))
-                .SetValue("Vector3", typeof(Vector3))
-                .SetValue("Vector2Child", typeof(Vector2Child));
-        }
+            .SetValue("log", new Action<object>(Console.WriteLine))
+            .SetValue("assert", new Action<bool>(Assert.True))
+            .SetValue("assertFalse", new Action<bool>(Assert.False))
+            .SetValue("equal", new Action<object, object>(Assert.Equal))
+            .SetValue("Vector2", typeof(Vector2))
+            .SetValue("Vector3", typeof(Vector3))
+            .SetValue("Vector2Child", typeof(Vector2Child));
+    }
 
-        private void RunTest(string source)
-        {
-            _engine.Execute(source);
-        }
+    private void RunTest(string source)
+    {
+        _engine.Execute(source);
+    }
+
+    public class Vector2
+    {
+        public double X { get; }
+        public double Y { get; }
+        public double SqrMagnitude => X * X + Y * Y;
+        public double Magnitude => Math.Sqrt(SqrMagnitude);
 
-        public class Vector2
+        public Vector2(double x, double y)
         {
-            public double X { get; }
-            public double Y { get; }
-            public double SqrMagnitude => X * X + Y * Y;
-            public double Magnitude => Math.Sqrt(SqrMagnitude);
-
-            public Vector2(double x, double y)
-            {
-                X = x;
-                Y = y;
-            }
-
-            public static Vector2 operator +(Vector2 left, Vector2 right) => new Vector2(left.X + right.X, left.Y + right.Y);
-            public static Vector2 operator +(Vector2 left, double right) => new Vector2(left.X + right, left.Y + right);
-            public static Vector2 operator +(string left, Vector2 right) => new Vector2(right.X, right.Y);
-            public static Vector2 operator +(double left, Vector2 right) => new Vector2(right.X + left, right.Y + left);
-            public static Vector2 operator -(Vector2 left, Vector2 right) => new Vector2(left.X - right.X, left.Y - right.Y);
-            public static Vector2 operator *(Vector2 left, double right) => new Vector2(left.X * right, left.Y * right);
-            public static Vector2 operator /(Vector2 left, double right) => new Vector2(left.X / right, left.Y / right);
-
-            public static bool operator >(Vector2 left, Vector2 right) => left.Magnitude > right.Magnitude;
-            public static bool operator <(Vector2 left, Vector2 right) => left.Magnitude < right.Magnitude;
-            public static bool operator >=(Vector2 left, Vector2 right) => left.Magnitude >= right.Magnitude;
-            public static bool operator <=(Vector2 left, Vector2 right) => left.Magnitude <= right.Magnitude;
-            public static Vector2 operator %(Vector2 left, Vector2 right) => new Vector2(left.X % right.X, left.Y % right.Y);
-            public static double operator &(Vector2 left, Vector2 right) => left.X * right.X + left.Y * right.Y;
-            public static Vector2 operator |(Vector2 left, Vector2 right) => right * ((left & right) / right.SqrMagnitude);
-
-
-            public static double operator +(Vector2 operand) => operand.Magnitude;
-            public static Vector2 operator -(Vector2 operand) => new Vector2(-operand.X, -operand.Y);
-            public static bool operator !(Vector2 operand) => operand.Magnitude == 0;
-            public static Vector2 operator ~(Vector2 operand) => new Vector2(operand.Y, operand.X);
-            public static Vector2 operator ++(Vector2 operand) => new Vector2(operand.X + 1, operand.Y + 1);
-            public static Vector2 operator --(Vector2 operand) => new Vector2(operand.X - 1, operand.Y - 1);
-
-            public static implicit operator Vector3(Vector2 val) => new Vector3(val.X, val.Y, 0);
-            public static bool operator !=(Vector2 left, Vector2 right) => !(left == right);
-            public static bool operator ==(Vector2 left, Vector2 right) => left.X == right.X && left.Y == right.Y;
-            public override bool Equals(object obj) => ReferenceEquals(this, obj);
-            public override int GetHashCode() => X.GetHashCode() + Y.GetHashCode();
+            X = x;
+            Y = y;
         }
 
-        public class Vector2Child : Vector2
-        {
-            public Vector2Child(double x, double y) : base(x, y) { }
+        public static Vector2 operator +(Vector2 left, Vector2 right) => new Vector2(left.X + right.X, left.Y + right.Y);
+        public static Vector2 operator +(Vector2 left, double right) => new Vector2(left.X + right, left.Y + right);
+        public static Vector2 operator +(string left, Vector2 right) => new Vector2(right.X, right.Y);
+        public static Vector2 operator +(double left, Vector2 right) => new Vector2(right.X + left, right.Y + left);
+        public static Vector2 operator -(Vector2 left, Vector2 right) => new Vector2(left.X - right.X, left.Y - right.Y);
+        public static Vector2 operator *(Vector2 left, double right) => new Vector2(left.X * right, left.Y * right);
+        public static Vector2 operator /(Vector2 left, double right) => new Vector2(left.X / right, left.Y / right);
+
+        public static bool operator >(Vector2 left, Vector2 right) => left.Magnitude > right.Magnitude;
+        public static bool operator <(Vector2 left, Vector2 right) => left.Magnitude < right.Magnitude;
+        public static bool operator >=(Vector2 left, Vector2 right) => left.Magnitude >= right.Magnitude;
+        public static bool operator <=(Vector2 left, Vector2 right) => left.Magnitude <= right.Magnitude;
+        public static Vector2 operator %(Vector2 left, Vector2 right) => new Vector2(left.X % right.X, left.Y % right.Y);
+        public static double operator &(Vector2 left, Vector2 right) => left.X * right.X + left.Y * right.Y;
+        public static Vector2 operator |(Vector2 left, Vector2 right) => right * ((left & right) / right.SqrMagnitude);
+
+
+        public static double operator +(Vector2 operand) => operand.Magnitude;
+        public static Vector2 operator -(Vector2 operand) => new Vector2(-operand.X, -operand.Y);
+        public static bool operator !(Vector2 operand) => operand.Magnitude == 0;
+        public static Vector2 operator ~(Vector2 operand) => new Vector2(operand.Y, operand.X);
+        public static Vector2 operator ++(Vector2 operand) => new Vector2(operand.X + 1, operand.Y + 1);
+        public static Vector2 operator --(Vector2 operand) => new Vector2(operand.X - 1, operand.Y - 1);
+
+        public static implicit operator Vector3(Vector2 val) => new Vector3(val.X, val.Y, 0);
+        public static bool operator !=(Vector2 left, Vector2 right) => !(left == right);
+        public static bool operator ==(Vector2 left, Vector2 right) => left.X == right.X && left.Y == right.Y;
+        public override bool Equals(object obj) => ReferenceEquals(this, obj);
+        public override int GetHashCode() => X.GetHashCode() + Y.GetHashCode();
+    }
 
-            public static Vector2Child operator +(Vector2Child left, double right) => new Vector2Child(left.X + 2 * right, left.Y + 2 * right);
-        }
+    public class Vector2Child : Vector2
+    {
+        public Vector2Child(double x, double y) : base(x, y) { }
 
-        public class Vector3
+        public static Vector2Child operator +(Vector2Child left, double right) => new Vector2Child(left.X + 2 * right, left.Y + 2 * right);
+    }
+
+    public class Vector3
+    {
+        public double X { get; }
+        public double Y { get; }
+        public double Z { get; }
+
+        public Vector3(double x, double y, double z)
         {
-            public double X { get; }
-            public double Y { get; }
-            public double Z { get; }
-
-            public Vector3(double x, double y, double z)
-            {
-                X = x;
-                Y = y;
-                Z = z;
-            }
-
-            public static Vector3 operator +(Vector3 left, double right) => new Vector3(left.X + right, left.Y + right, left.Z + right);
-            public static Vector3 operator +(double left, Vector3 right) => new Vector3(right.X + left, right.Y + left, right.Z + left);
-            public static Vector3 operator +(Vector3 left, Vector3 right) => new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
+            X = x;
+            Y = y;
+            Z = z;
         }
 
-        private struct Vector2D
-        {
-            public double X { get; set; }
-            public double Y { get; set; }
+        public static Vector3 operator +(Vector3 left, double right) => new Vector3(left.X + right, left.Y + right, left.Z + right);
+        public static Vector3 operator +(double left, Vector3 right) => new Vector3(right.X + left, right.Y + left, right.Z + left);
+        public static Vector3 operator +(Vector3 left, Vector3 right) => new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
+    }
 
-            public Vector2D(double x, double y)
-            {
-                X = x;
-                Y = y;
-            }
+    private struct Vector2D
+    {
+        public double X { get; set; }
+        public double Y { get; set; }
 
+        public Vector2D(double x, double y)
+        {
+            X = x;
+            Y = y;
+        }
 
-            public static Vector2D operator +(Vector2D lhs, Vector2D rhs)
-            {
-                return new Vector2D(lhs.X + rhs.X, lhs.Y + rhs.Y);
-            }
 
-            public override string ToString()
-            {
-                return $"({X}, {Y})";
-            }
+        public static Vector2D operator +(Vector2D lhs, Vector2D rhs)
+        {
+            return new Vector2D(lhs.X + rhs.X, lhs.Y + rhs.Y);
         }
 
-        [Fact]
-        public void OperatorOverloading_BinaryOperators()
+        public override string ToString()
         {
-            RunTest(@"
+            return $"({X}, {Y})";
+        }
+    }
+
+    [Fact]
+    public void OperatorOverloading_BinaryOperators()
+    {
+        RunTest(@"
                 var v1 = new Vector2(1, 2);
                 var v2 = new Vector2(3, 4);
                 var n = 6;
@@ -179,12 +179,12 @@ namespace Jint.Tests.Runtime
                 assertFalse(vBig < vSmall);
                 assertFalse(vBig <= vSmall);
             ");
-        }
+    }
 
-        [Fact]
-        public void OperatorOverloading_AssignmentOperators()
-        {
-            RunTest(@"
+    [Fact]
+    public void OperatorOverloading_AssignmentOperators()
+    {
+        RunTest(@"
                 var v1 = new Vector2(1, 2);
                 var v2 = new Vector2(3, 4);
                 var n = 6;
@@ -233,12 +233,12 @@ namespace Jint.Tests.Runtime
                 equal(2, r9.X);
                 equal(2, r9.Y);
             ");
-        }
+    }
 
-        [Fact]
-        public void OperatorOverloading_ShouldCoerceTypes()
-        {
-            RunTest(@"
+    [Fact]
+    public void OperatorOverloading_ShouldCoerceTypes()
+    {
+        RunTest(@"
                 var v1 = new Vector2(1, 2);
                 var v2 = new Vector3(4, 5, 6);
                 var res = v1 + v2;
@@ -246,12 +246,12 @@ namespace Jint.Tests.Runtime
                 equal(7, res.Y);
                 equal(6, res.Z);
             ");
-        }
+    }
 
-        [Fact]
-        public void OperatorOverloading_ShouldWorkForEqualityButNotForStrictEquality()
-        {
-            RunTest(@"
+    [Fact]
+    public void OperatorOverloading_ShouldWorkForEqualityButNotForStrictEquality()
+    {
+        RunTest(@"
                 var v1 = new Vector2(1, 2);
                 var v2 = new Vector2(1, 2);
                 assert(v1 == v2);
@@ -264,12 +264,12 @@ namespace Jint.Tests.Runtime
                 var z2 = new Vector3(1, 2, 3);
                 assertFalse(z1 == z2);
             ");
-        }
+    }
 
-        [Fact]
-        public void OperatorOverloading_UnaryOperators()
-        {
-            RunTest(@"
+    [Fact]
+    public void OperatorOverloading_UnaryOperators()
+    {
+        RunTest(@"
                 var v0 = new Vector2(0, 0);
                 var v = new Vector2(3, 4);
                 var rv = -v;
@@ -287,12 +287,12 @@ namespace Jint.Tests.Runtime
                 equal(4, bv.X);
                 equal(3, bv.Y);
             ");
-        }
+    }
 
-        [Fact]
-        public void OperatorOverloading_IncrementOperatorShouldWork()
-        {
-            RunTest(@"
+    [Fact]
+    public void OperatorOverloading_IncrementOperatorShouldWork()
+    {
+        RunTest(@"
                 var v = new Vector2(3, 22);
                 var original = v;
                 var pre = ++v;
@@ -310,12 +310,12 @@ namespace Jint.Tests.Runtime
                 equal(4, decPost.X);
                 equal(3, v.X);
             ");
-        }
+    }
 
-        [Fact]
-        public void OperatorOverloading_ShouldWorkOnDerivedClasses()
-        {
-            RunTest(@"
+    [Fact]
+    public void OperatorOverloading_ShouldWorkOnDerivedClasses()
+    {
+        RunTest(@"
                 var v1 = new Vector2Child(1, 2);
                 var v2 = new Vector2Child(3, 4);
                 var n = 5;
@@ -331,12 +331,12 @@ namespace Jint.Tests.Runtime
                 equal(11, v1n.X);
                 equal(12, v1n.Y);
             ");
-        }
+    }
 
-        [Fact]
-        public void OperatorOverloading_ShouldEvaluateOnlyOnce()
-        {
-            RunTest(@"
+    [Fact]
+    public void OperatorOverloading_ShouldEvaluateOnlyOnce()
+    {
+        RunTest(@"
                 var c;
                 var resolve = v => { c++; return v; };
 
@@ -355,18 +355,17 @@ namespace Jint.Tests.Runtime
                 equal(n3, -1);
                 equal(c, 1);
             ");
-        }
+    }
 
-        [Fact]
-        public void ShouldAllowStringConcatenateForOverloaded()
-        {
-            var engine = new Engine(cfg => cfg.AllowOperatorOverloading());
-            engine.SetValue("Vector2D", TypeReference.CreateTypeReference<Vector2D>(engine));
-            engine.SetValue("log", new Action<object>(Console.WriteLine));
+    [Fact]
+    public void ShouldAllowStringConcatenateForOverloaded()
+    {
+        var engine = new Engine(cfg => cfg.AllowOperatorOverloading());
+        engine.SetValue("Vector2D", TypeReference.CreateTypeReference<Vector2D>(engine));
+        engine.SetValue("log", new Action<object>(Console.WriteLine));
 
-            engine.Evaluate("let v1 = new Vector2D(1, 2);");
-            Assert.Equal("(1, 2)", engine.Evaluate("new String(v1)").As<StringInstance>().StringData.ToString());
-            Assert.Equal("### (1, 2) ###", engine.Evaluate("'### ' + v1 + ' ###'"));
-        }
+        engine.Evaluate("let v1 = new Vector2D(1, 2);");
+        Assert.Equal("(1, 2)", engine.Evaluate("new String(v1)").As<StringInstance>().StringData.ToString());
+        Assert.Equal("### (1, 2) ###", engine.Evaluate("'### ' + v1 + ' ###'"));
     }
-}
+}

+ 25 - 26
Jint.Tests/Runtime/SamplesTests.cs

@@ -1,35 +1,34 @@
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class SamplesTests : IDisposable
 {
-    public class SamplesTests : IDisposable
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public SamplesTests()
-        {
-            _engine = new Engine()
+    public SamplesTests()
+    {
+        _engine = new Engine()
                 .SetValue("log", new Action<object>(Console.WriteLine))
                 .SetValue("assert", new Action<bool>(Assert.True))
-                ;
-        }
+            ;
+    }
 
-        void IDisposable.Dispose()
-        {
-        }
+    void IDisposable.Dispose()
+    {
+    }
 
-        private void RunTest(string source)
-        {
-            _engine.Execute(source);
-        }
+    private void RunTest(string source)
+    {
+        _engine.Execute(source);
+    }
 
-        [Fact]
-        public void GithubReadme1()
-        {
-            var square = new Engine()
-                .SetValue("x", 3)
-                .Evaluate("x * x")
-                .ToObject();
+    [Fact]
+    public void GithubReadme1()
+    {
+        var square = new Engine()
+            .SetValue("x", 3)
+            .Evaluate("x * x")
+            .ToObject();
 
-            Assert.Equal(9d, square);
-        }
+        Assert.Equal(9d, square);
     }
-}
+}

+ 87 - 88
Jint.Tests/Runtime/StringTetsLithuaniaData.cs

@@ -1,97 +1,96 @@
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class StringTetsLithuaniaData
 {
-    public class StringTetsLithuaniaData
-    {
-        // Contains the non-uppercased string that will be processed by the engine and the expected result.
-        private readonly TheoryData<string, string> fullSetOfData = new TheoryData<string, string>();
-        // From: https://github.com/tc39/test262/blob/main/test/intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian.js
-        private readonly string[] softDotted = [
-            "\u0069", "\u006A",   // LATIN SMALL LETTER I..LATIN SMALL LETTER J
-            "\u012F",             // LATIN SMALL LETTER I WITH OGONEK
-            "\u0249",             // LATIN SMALL LETTER J WITH STROKE
-            "\u0268",             // LATIN SMALL LETTER I WITH STROKE
-            "\u029D",             // LATIN SMALL LETTER J WITH CROSSED-TAIL
-            "\u02B2",             // MODIFIER LETTER SMALL J
-            "\u03F3",             // GREEK LETTER YOT
-            "\u0456",             // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
-            "\u0458",             // CYRILLIC SMALL LETTER JE
-            "\u1D62",             // LATIN SUBSCRIPT SMALL LETTER I
-            "\u1D96",             // LATIN SMALL LETTER I WITH RETROFLEX HOOK
-            "\u1DA4",             // MODIFIER LETTER SMALL I WITH STROKE
-            "\u1DA8",             // MODIFIER LETTER SMALL J WITH CROSSED-TAIL
-            "\u1E2D",             // LATIN SMALL LETTER I WITH TILDE BELOW
-            "\u1ECB",             // LATIN SMALL LETTER I WITH DOT BELOW
-            "\u2071",             // SUPERSCRIPT LATIN SMALL LETTER I
-            "\u2148", "\u2149",   // DOUBLE-STRUCK ITALIC SMALL I..DOUBLE-STRUCK ITALIC SMALL J
-            "\u2C7C",             // LATIN SUBSCRIPT SMALL LETTER J
-            "\uD835\uDC22", "\uD835\uDC23",   // MATHEMATICAL BOLD SMALL I..MATHEMATICAL BOLD SMALL J
-            "\uD835\uDC56", "\uD835\uDC57",   // MATHEMATICAL ITALIC SMALL I..MATHEMATICAL ITALIC SMALL J
-            "\uD835\uDC8A", "\uD835\uDC8B",   // MATHEMATICAL BOLD ITALIC SMALL I..MATHEMATICAL BOLD ITALIC SMALL J
-            "\uD835\uDCBE", "\uD835\uDCBF",   // MATHEMATICAL SCRIPT SMALL I..MATHEMATICAL SCRIPT SMALL J
-            "\uD835\uDCF2", "\uD835\uDCF3",   // MATHEMATICAL BOLD SCRIPT SMALL I..MATHEMATICAL BOLD SCRIPT SMALL J
-            "\uD835\uDD26", "\uD835\uDD27",   // MATHEMATICAL FRAKTUR SMALL I..MATHEMATICAL FRAKTUR SMALL J
-            "\uD835\uDD5A", "\uD835\uDD5B",   // MATHEMATICAL DOUBLE-STRUCK SMALL I..MATHEMATICAL DOUBLE-STRUCK SMALL J
-            "\uD835\uDD8E", "\uD835\uDD8F",   // MATHEMATICAL BOLD FRAKTUR SMALL I..MATHEMATICAL BOLD FRAKTUR SMALL J
-            "\uD835\uDDC2", "\uD835\uDDC3",   // MATHEMATICAL SANS-SERIF SMALL I..MATHEMATICAL SANS-SERIF SMALL J
-            "\uD835\uDDF6", "\uD835\uDDF7",   // MATHEMATICAL SANS-SERIF BOLD SMALL I..MATHEMATICAL SANS-SERIF BOLD SMALL J
-            "\uD835\uDE2A", "\uD835\uDE2B",   // MATHEMATICAL SANS-SERIF ITALIC SMALL I..MATHEMATICAL SANS-SERIF ITALIC SMALL J
-            "\uD835\uDE5E", "\uD835\uDE5F",   // MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J
-            "\uD835\uDE92", "\uD835\uDE93",   // MATHEMATICAL MONOSPACE SMALL I..MATHEMATICAL MONOSPACE SMALL J
-        ];
+    // Contains the non-uppercased string that will be processed by the engine and the expected result.
+    private readonly TheoryData<string, string> fullSetOfData = new TheoryData<string, string>();
+    // From: https://github.com/tc39/test262/blob/main/test/intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian.js
+    private readonly string[] softDotted = [
+        "\u0069", "\u006A",   // LATIN SMALL LETTER I..LATIN SMALL LETTER J
+        "\u012F",             // LATIN SMALL LETTER I WITH OGONEK
+        "\u0249",             // LATIN SMALL LETTER J WITH STROKE
+        "\u0268",             // LATIN SMALL LETTER I WITH STROKE
+        "\u029D",             // LATIN SMALL LETTER J WITH CROSSED-TAIL
+        "\u02B2",             // MODIFIER LETTER SMALL J
+        "\u03F3",             // GREEK LETTER YOT
+        "\u0456",             // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+        "\u0458",             // CYRILLIC SMALL LETTER JE
+        "\u1D62",             // LATIN SUBSCRIPT SMALL LETTER I
+        "\u1D96",             // LATIN SMALL LETTER I WITH RETROFLEX HOOK
+        "\u1DA4",             // MODIFIER LETTER SMALL I WITH STROKE
+        "\u1DA8",             // MODIFIER LETTER SMALL J WITH CROSSED-TAIL
+        "\u1E2D",             // LATIN SMALL LETTER I WITH TILDE BELOW
+        "\u1ECB",             // LATIN SMALL LETTER I WITH DOT BELOW
+        "\u2071",             // SUPERSCRIPT LATIN SMALL LETTER I
+        "\u2148", "\u2149",   // DOUBLE-STRUCK ITALIC SMALL I..DOUBLE-STRUCK ITALIC SMALL J
+        "\u2C7C",             // LATIN SUBSCRIPT SMALL LETTER J
+        "\uD835\uDC22", "\uD835\uDC23",   // MATHEMATICAL BOLD SMALL I..MATHEMATICAL BOLD SMALL J
+        "\uD835\uDC56", "\uD835\uDC57",   // MATHEMATICAL ITALIC SMALL I..MATHEMATICAL ITALIC SMALL J
+        "\uD835\uDC8A", "\uD835\uDC8B",   // MATHEMATICAL BOLD ITALIC SMALL I..MATHEMATICAL BOLD ITALIC SMALL J
+        "\uD835\uDCBE", "\uD835\uDCBF",   // MATHEMATICAL SCRIPT SMALL I..MATHEMATICAL SCRIPT SMALL J
+        "\uD835\uDCF2", "\uD835\uDCF3",   // MATHEMATICAL BOLD SCRIPT SMALL I..MATHEMATICAL BOLD SCRIPT SMALL J
+        "\uD835\uDD26", "\uD835\uDD27",   // MATHEMATICAL FRAKTUR SMALL I..MATHEMATICAL FRAKTUR SMALL J
+        "\uD835\uDD5A", "\uD835\uDD5B",   // MATHEMATICAL DOUBLE-STRUCK SMALL I..MATHEMATICAL DOUBLE-STRUCK SMALL J
+        "\uD835\uDD8E", "\uD835\uDD8F",   // MATHEMATICAL BOLD FRAKTUR SMALL I..MATHEMATICAL BOLD FRAKTUR SMALL J
+        "\uD835\uDDC2", "\uD835\uDDC3",   // MATHEMATICAL SANS-SERIF SMALL I..MATHEMATICAL SANS-SERIF SMALL J
+        "\uD835\uDDF6", "\uD835\uDDF7",   // MATHEMATICAL SANS-SERIF BOLD SMALL I..MATHEMATICAL SANS-SERIF BOLD SMALL J
+        "\uD835\uDE2A", "\uD835\uDE2B",   // MATHEMATICAL SANS-SERIF ITALIC SMALL I..MATHEMATICAL SANS-SERIF ITALIC SMALL J
+        "\uD835\uDE5E", "\uD835\uDE5F",   // MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J
+        "\uD835\uDE92", "\uD835\uDE93",   // MATHEMATICAL MONOSPACE SMALL I..MATHEMATICAL MONOSPACE SMALL J
+    ];
 
-        // Results obtained from node -v 18.12.0.
-        private readonly string[] softDottedUpperCased = [
-            "I", "J", "Į", "Ɉ", "Ɨ", "Ʝ", "ʲ", "Ϳ", "І", "Ј",
-            "ᵢ", "ᶖ", "ᶤ", "ᶨ", "Ḭ", "Ị", "ⁱ", "ⅈ", "ⅉ", "ⱼ",
-            "𝐢", "𝐣", "𝑖", "𝑗", "𝒊", "𝒋", "𝒾", "𝒿", "𝓲", "𝓳",
-            "𝔦", "𝔧", "𝕚", "𝕛", "𝖎", "𝖏", "𝗂", "𝗃", "𝗶", "𝗷",
-            "𝘪", "𝘫", "𝙞", "𝙟", "𝚒", "𝚓",
-        ];
+    // Results obtained from node -v 18.12.0.
+    private readonly string[] softDottedUpperCased = [
+        "I", "J", "Į", "Ɉ", "Ɨ", "Ʝ", "ʲ", "Ϳ", "І", "Ј",
+        "ᵢ", "ᶖ", "ᶤ", "ᶨ", "Ḭ", "Ị", "ⁱ", "ⅈ", "ⅉ", "ⱼ",
+        "𝐢", "𝐣", "𝑖", "𝑗", "𝒊", "𝒋", "𝒾", "𝒿", "𝓲", "𝓳",
+        "𝔦", "𝔧", "𝕚", "𝕛", "𝖎", "𝖏", "𝗂", "𝗃", "𝗶", "𝗷",
+        "𝘪", "𝘫", "𝙞", "𝙟", "𝚒", "𝚓",
+    ];
 
-        /// <summary>
-        /// Creates and adds the data to <fullSetOfData> that will be used for the tests. Six cases:
-        /// 1.- String with character at the beginning of the string.
-        /// 2.- String with double character at the beginning of the string.
-        /// 3.- String with character at the middle of the string.
-        /// 4.- String with double character at the middle of the string.
-        /// 5.- String with character at the end of the string.
-        /// 6.- String with double character at the end of the string.
-        /// </summary>
-        private void AddStringsForChars(string nonCapChar, string toUpperChar)
-        {
-            fullSetOfData.Add($"{nonCapChar}lorem ipsum", $"{toUpperChar}LOREM IPSUM");
-            fullSetOfData.Add($"{nonCapChar}{nonCapChar}lorem ipsum", $"{toUpperChar}{toUpperChar}LOREM IPSUM");
-            fullSetOfData.Add($"lorem{nonCapChar}ipsum", $"LOREM{toUpperChar}IPSUM");
-            fullSetOfData.Add($"lorem{nonCapChar}{nonCapChar}ipsum", $"LOREM{toUpperChar}{toUpperChar}IPSUM");
-            fullSetOfData.Add($"lorem ipsum{nonCapChar}", $"LOREM IPSUM{toUpperChar}");
-            fullSetOfData.Add($"lorem ipsum{nonCapChar}{nonCapChar}", $"LOREM IPSUM{toUpperChar}{toUpperChar}");
-        }
+    /// <summary>
+    /// Creates and adds the data to <fullSetOfData> that will be used for the tests. Six cases:
+    /// 1.- String with character at the beginning of the string.
+    /// 2.- String with double character at the beginning of the string.
+    /// 3.- String with character at the middle of the string.
+    /// 4.- String with double character at the middle of the string.
+    /// 5.- String with character at the end of the string.
+    /// 6.- String with double character at the end of the string.
+    /// </summary>
+    private void AddStringsForChars(string nonCapChar, string toUpperChar)
+    {
+        fullSetOfData.Add($"{nonCapChar}lorem ipsum", $"{toUpperChar}LOREM IPSUM");
+        fullSetOfData.Add($"{nonCapChar}{nonCapChar}lorem ipsum", $"{toUpperChar}{toUpperChar}LOREM IPSUM");
+        fullSetOfData.Add($"lorem{nonCapChar}ipsum", $"LOREM{toUpperChar}IPSUM");
+        fullSetOfData.Add($"lorem{nonCapChar}{nonCapChar}ipsum", $"LOREM{toUpperChar}{toUpperChar}IPSUM");
+        fullSetOfData.Add($"lorem ipsum{nonCapChar}", $"LOREM IPSUM{toUpperChar}");
+        fullSetOfData.Add($"lorem ipsum{nonCapChar}{nonCapChar}", $"LOREM IPSUM{toUpperChar}{toUpperChar}");
+    }
 
-        // All the cases from https://github.com/tc39/test262/blob/main/test/intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian.js
-        public TheoryData<string, string> TestData()
+    // All the cases from https://github.com/tc39/test262/blob/main/test/intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian.js
+    public TheoryData<string, string> TestData()
+    {
+        // COMBINING DOT ABOVE (U+0307) not removed when uppercasing capital I
+        AddStringsForChars("İ", "İ");
+        // COMBINING DOT ABOVE (U+0307) not removed when uppercasing capital J
+        AddStringsForChars("J̇", "J̇");
+        for (int i = 0; i < softDotted.Length; i++)
         {
-            // COMBINING DOT ABOVE (U+0307) not removed when uppercasing capital I
-            AddStringsForChars("İ", "İ");
-            // COMBINING DOT ABOVE (U+0307) not removed when uppercasing capital J
-            AddStringsForChars("J̇", "J̇");
-            for (int i = 0; i < softDotted.Length; i++)
-            {
-                // COMBINING DOT ABOVE (U+0307) removed when preceded by Soft_Dotted.
-                // Character directly preceded by Soft_Dotted.
-                AddStringsForChars(softDotted[i] + "\u0307", softDottedUpperCased[i]);
+            // COMBINING DOT ABOVE (U+0307) removed when preceded by Soft_Dotted.
+            // Character directly preceded by Soft_Dotted.
+            AddStringsForChars(softDotted[i] + "\u0307", softDottedUpperCased[i]);
 
-                // COMBINING DOT ABOVE (U+0307) removed if preceded by Soft_Dotted.
-                // Character not directly preceded by Soft_Dotted.
-                // - COMBINING DOT BELOW (U+0323), combining class 220 (Below)
-                AddStringsForChars(softDotted[i] + "\u0323\u0307", softDottedUpperCased[i] + "\u0323");
+            // COMBINING DOT ABOVE (U+0307) removed if preceded by Soft_Dotted.
+            // Character not directly preceded by Soft_Dotted.
+            // - COMBINING DOT BELOW (U+0323), combining class 220 (Below)
+            AddStringsForChars(softDotted[i] + "\u0323\u0307", softDottedUpperCased[i] + "\u0323");
 
-                // COMBINING DOT ABOVE removed if preceded by Soft_Dotted.
-                // Character not directly preceded by Soft_Dotted.
-                // - PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE (U+101FD = D800 DDFD), combining class 220 (Below)
-                AddStringsForChars(softDotted[i] + "\uD800\uDDFD\u0307", softDottedUpperCased[i] + "\uD800\uDDFD");
-            }
-
-            return fullSetOfData;
+            // COMBINING DOT ABOVE removed if preceded by Soft_Dotted.
+            // Character not directly preceded by Soft_Dotted.
+            // - PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE (U+101FD = D800 DDFD), combining class 220 (Below)
+            AddStringsForChars(softDotted[i] + "\uD800\uDDFD\u0307", softDottedUpperCased[i] + "\uD800\uDDFD");
         }
+
+        return fullSetOfData;
     }
-}
+}

+ 28 - 29
Jint.Tests/Runtime/TestClasses/AsyncTestClass.cs

@@ -1,40 +1,39 @@
-namespace Jint.Tests.Runtime.TestClasses
+namespace Jint.Tests.Runtime.TestClasses;
+
+internal class AsyncTestClass
 {
-    internal class AsyncTestClass
-    {
-        public static readonly string TestString = "Hello World";
+    public static readonly string TestString = "Hello World";
 
-        public string StringToAppend { get; set; } = string.Empty;
+    public string StringToAppend { get; set; } = string.Empty;
 
-        public async Task AddToStringDelayedAsync(string appendWith)
-        {
-            await Task.Delay(1000).ConfigureAwait(false);
+    public async Task AddToStringDelayedAsync(string appendWith)
+    {
+        await Task.Delay(1000).ConfigureAwait(false);
 
-            StringToAppend += appendWith;
-        }
+        StringToAppend += appendWith;
+    }
 
-        public async Task<string> ReturnDelayedTaskAsync()
-        {
-            await Task.Delay(1000).ConfigureAwait(false);
+    public async Task<string> ReturnDelayedTaskAsync()
+    {
+        await Task.Delay(1000).ConfigureAwait(false);
 
-            return TestString;
-        }
+        return TestString;
+    }
 
-        public Task<string> ReturnCompletedTask()
-        {
-            return Task.FromResult(TestString);
-        }
+    public Task<string> ReturnCompletedTask()
+    {
+        return Task.FromResult(TestString);
+    }
 
-        public Task<string> ReturnCancelledTask(CancellationToken token)
-        {
-            return Task.FromCanceled<string>(token);
-        }
+    public Task<string> ReturnCancelledTask(CancellationToken token)
+    {
+        return Task.FromCanceled<string>(token);
+    }
 
-        public async Task<string> ThrowAfterDelayAsync()
-        {
-            await Task.Delay(100).ConfigureAwait(false);
+    public async Task<string> ThrowAfterDelayAsync()
+    {
+        await Task.Delay(100).ConfigureAwait(false);
 
-            throw new Exception("Task threw exception");
-        }
+        throw new Exception("Task threw exception");
     }
-}
+}

+ 7 - 8
Jint.Tests/Runtime/TestClasses/HelloWorld.cs

@@ -1,11 +1,10 @@
-namespace Jint.Tests.Runtime.TestClasses
+namespace Jint.Tests.Runtime.TestClasses;
+
+public class HelloWorld
 {
-    public class HelloWorld
+    public void ThrowException()
     {
-        public void ThrowException()
-        {
-            int zero = 0;
-            int x = 5 / zero;
-        }
+        int zero = 0;
+        int x = 5 / zero;
     }
-}
+}

+ 70 - 72
Jint.Tests/Runtime/TypeConverterTests.cs

@@ -2,87 +2,87 @@ using Jint.Native;
 using Jint.Runtime;
 using Xunit.Abstractions;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class TypeConverterTests
 {
-    public class TypeConverterTests
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public TypeConverterTests(ITestOutputHelper output)
-        {
-            _engine = new Engine()
+    public TypeConverterTests(ITestOutputHelper output)
+    {
+        _engine = new Engine()
                 .SetValue("log", new Action<object>(o => output.WriteLine(o.ToString())))
                 .SetValue("assert", new Action<bool>(Assert.True))
                 .SetValue("equal", new Action<object, object>(Assert.Equal))
-                ;
-        }
+            ;
+    }
 
-        public static readonly IEnumerable<object[]> ConvertNumberToInt32AndUint32TestData = new TheoryData<double, int>()
-        {
-            { 0.0, 0 },
-            { -0.0, 0 },
-            { double.Epsilon, 0 },
-            { 0.5, 0 },
-            { -0.5, 0 },
-            { 0.9999999999999999, 0 },
-            { 1.0, 1 },
-            { 1.5, 1 },
-            { 10.0, 10 },
-            { -12.3, -12 },
-            { 1485772.6, 1485772 },
-            { -984737183.8, -984737183 },
+    public static readonly IEnumerable<object[]> ConvertNumberToInt32AndUint32TestData = new TheoryData<double, int>()
+    {
+        { 0.0, 0 },
+        { -0.0, 0 },
+        { double.Epsilon, 0 },
+        { 0.5, 0 },
+        { -0.5, 0 },
+        { 0.9999999999999999, 0 },
+        { 1.0, 1 },
+        { 1.5, 1 },
+        { 10.0, 10 },
+        { -12.3, -12 },
+        { 1485772.6, 1485772 },
+        { -984737183.8, -984737183 },
 
-            { Math.Pow(2, 31) - 1.0, int.MaxValue },
-            { Math.Pow(2, 31) - 0.5, int.MaxValue },
-            { Math.Pow(2, 32) - 1.0, -1 },
-            { Math.Pow(2, 32) - 0.5, -1 },
-            { Math.Pow(2, 32), 0 },
-            { -Math.Pow(2, 32), 0 },
-            { -Math.Pow(2, 32) - 0.5, 0 },
-            { Math.Pow(2, 32) + 1.0, 1 },
-            { Math.Pow(2, 45) + 17.56, 17 },
-            { Math.Pow(2, 45) - 17.56, -18 },
-            { -Math.Pow(2, 45) + 17.56, 18 },
-            { Math.Pow(2, 51) + 17.5, 17 },
-            { Math.Pow(2, 51) - 17.5, -18 },
+        { Math.Pow(2, 31) - 1.0, int.MaxValue },
+        { Math.Pow(2, 31) - 0.5, int.MaxValue },
+        { Math.Pow(2, 32) - 1.0, -1 },
+        { Math.Pow(2, 32) - 0.5, -1 },
+        { Math.Pow(2, 32), 0 },
+        { -Math.Pow(2, 32), 0 },
+        { -Math.Pow(2, 32) - 0.5, 0 },
+        { Math.Pow(2, 32) + 1.0, 1 },
+        { Math.Pow(2, 45) + 17.56, 17 },
+        { Math.Pow(2, 45) - 17.56, -18 },
+        { -Math.Pow(2, 45) + 17.56, 18 },
+        { Math.Pow(2, 51) + 17.5, 17 },
+        { Math.Pow(2, 51) - 17.5, -18 },
 
-            { Math.Pow(2, 53) - 1.0, -1 },
-            { -Math.Pow(2, 53) + 1.0, 1 },
-            { Math.Pow(2, 53), 0 },
-            { -Math.Pow(2, 53), 0 },
-            { Math.Pow(2, 53) + 12.0, 12 },
-            { -Math.Pow(2, 53) - 12.0, -12 },
+        { Math.Pow(2, 53) - 1.0, -1 },
+        { -Math.Pow(2, 53) + 1.0, 1 },
+        { Math.Pow(2, 53), 0 },
+        { -Math.Pow(2, 53), 0 },
+        { Math.Pow(2, 53) + 12.0, 12 },
+        { -Math.Pow(2, 53) - 12.0, -12 },
 
-            { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 1), -2 },
-            { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 3), 8 },
-            { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 11), 1 << 11 },
-            { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 20), -(1 << 20) },
-            { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 31), int.MinValue },
-            { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 31), int.MinValue },
-            { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 32), 0 },
-            { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 32), 0 },
-            { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 36), 0 },
+        { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 1), -2 },
+        { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 3), 8 },
+        { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 11), 1 << 11 },
+        { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 20), -(1 << 20) },
+        { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 31), int.MinValue },
+        { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 31), int.MinValue },
+        { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 32), 0 },
+        { -(Math.Pow(2, 53) - 1.0) * Math.Pow(2, 32), 0 },
+        { (Math.Pow(2, 53) - 1.0) * Math.Pow(2, 36), 0 },
 
-            { double.MaxValue, 0 },
-            { double.MinValue, 0 },
-            { double.PositiveInfinity, 0 },
-            { double.NegativeInfinity, 0 },
-            { double.NaN, 0 },
-        };
+        { double.MaxValue, 0 },
+        { double.MinValue, 0 },
+        { double.PositiveInfinity, 0 },
+        { double.NegativeInfinity, 0 },
+        { double.NaN, 0 },
+    };
 
-        [Theory]
-        [MemberData(nameof(ConvertNumberToInt32AndUint32TestData))]
-        public void ConvertNumberToInt32AndUint32(double value, int expectedResult)
-        {
-            JsValue jsval = value;
-            Assert.Equal(expectedResult, TypeConverter.ToInt32(jsval));
-            Assert.Equal((uint)expectedResult, TypeConverter.ToUint32(jsval));
-        }
+    [Theory]
+    [MemberData(nameof(ConvertNumberToInt32AndUint32TestData))]
+    public void ConvertNumberToInt32AndUint32(double value, int expectedResult)
+    {
+        JsValue jsval = value;
+        Assert.Equal(expectedResult, TypeConverter.ToInt32(jsval));
+        Assert.Equal((uint)expectedResult, TypeConverter.ToUint32(jsval));
+    }
 
-        [Fact]
-        public void ToPrimitiveShouldEvaluateOnlyOnceDuringInExpression()
-        {
-            _engine.Execute(@"
+    [Fact]
+    public void ToPrimitiveShouldEvaluateOnlyOnceDuringInExpression()
+    {
+        _engine.Execute(@"
                 var b = {};
                 var bval = 0;
                 b[Symbol.toPrimitive] = function(hint) { return bval++; };
@@ -90,7 +90,5 @@ namespace Jint.Tests.Runtime
                 b in {};
                 equal(1, bval);
             ");
-        }
     }
-
-}
+}

+ 145 - 146
Jint.Tests/Runtime/TypedArrayInteropTests.cs

@@ -1,124 +1,124 @@
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class TypedArrayInteropTests
 {
-    public class TypedArrayInteropTests
+    [Fact]
+    public void CanInteropWithInt8()
     {
-        [Fact]
-        public void CanInteropWithInt8()
-        {
-            var engine = new Engine();
-            var source = new sbyte[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int8Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Int8Array");
-
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsInt8Array());
-            Assert.Equal(source, fromEngine.AsInt8Array());
-        }
-
-        [Fact]
-        public void CanInteropWithUint8()
-        {
-            var engine = new Engine();
-            var source = new byte[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Uint8Array");
-
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsUint8Array());
-            Assert.Equal(source, fromEngine.AsUint8Array());
-        }
-
-        [Fact]
-        public void CanInteropWithUint8Clamped()
-        {
-            var engine = new Engine();
-            var source = new byte[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8ClampedArray.Construct(source));
-            ValidateCreatedTypeArray(engine, "Uint8ClampedArray");
-
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsUint8ClampedArray());
-            Assert.Equal(source, fromEngine.AsUint8ClampedArray());
-        }
-
-        [Fact]
-        public void CanInteropWithInt16()
-        {
-            var engine = new Engine();
-            var source = new short[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int16Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Int16Array");
-
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsInt16Array());
-            Assert.Equal(source, fromEngine.AsInt16Array());
-        }
-
-        [Fact]
-        public void CanInteropWithUint16()
-        {
-            var engine = new Engine();
-            var source = new ushort[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint16Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Uint16Array");
+        var engine = new Engine();
+        var source = new sbyte[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Int8Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Int8Array");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsInt8Array());
+        Assert.Equal(source, fromEngine.AsInt8Array());
+    }
 
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsUint16Array());
-            Assert.Equal(source, fromEngine.AsUint16Array());
-        }
+    [Fact]
+    public void CanInteropWithUint8()
+    {
+        var engine = new Engine();
+        var source = new byte[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Uint8Array");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsUint8Array());
+        Assert.Equal(source, fromEngine.AsUint8Array());
+    }
 
-        [Fact]
-        public void CanInteropWithInt32()
-        {
-            var engine = new Engine();
-            var source = new[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int32Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Int32Array");
+    [Fact]
+    public void CanInteropWithUint8Clamped()
+    {
+        var engine = new Engine();
+        var source = new byte[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8ClampedArray.Construct(source));
+        ValidateCreatedTypeArray(engine, "Uint8ClampedArray");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsUint8ClampedArray());
+        Assert.Equal(source, fromEngine.AsUint8ClampedArray());
+    }
 
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsInt32Array());
-            Assert.Equal(source, fromEngine.AsInt32Array());
-        }
+    [Fact]
+    public void CanInteropWithInt16()
+    {
+        var engine = new Engine();
+        var source = new short[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Int16Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Int16Array");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsInt16Array());
+        Assert.Equal(source, fromEngine.AsInt16Array());
+    }
 
-        [Fact]
-        public void CanInteropWithUint32()
-        {
-            var engine = new Engine();
-            var source = new uint[] { 42, 12 };
+    [Fact]
+    public void CanInteropWithUint16()
+    {
+        var engine = new Engine();
+        var source = new ushort[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint16Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Uint16Array");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsUint16Array());
+        Assert.Equal(source, fromEngine.AsUint16Array());
+    }
 
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint32Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Uint32Array");
+    [Fact]
+    public void CanInteropWithInt32()
+    {
+        var engine = new Engine();
+        var source = new[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Int32Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Int32Array");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsInt32Array());
+        Assert.Equal(source, fromEngine.AsInt32Array());
+    }
 
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsUint32Array());
-            Assert.Equal(source, fromEngine.AsUint32Array());
-        }
+    [Fact]
+    public void CanInteropWithUint32()
+    {
+        var engine = new Engine();
+        var source = new uint[] { 42, 12 };
 
-        [Fact]
-        public void CanInteropWithBigInt64()
-        {
-            var engine = new Engine();
-            var source = new long[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.BigInt64Array.Construct(source));
-            ValidateCreatedBigIntegerTypeArray(engine, "BigInt64Array");
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint32Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Uint32Array");
 
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsBigInt64Array());
-            Assert.Equal(source, fromEngine.AsBigInt64Array());
-        }
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsUint32Array());
+        Assert.Equal(source, fromEngine.AsUint32Array());
+    }
 
-        [Fact]
-        public void CanInteropWithBigUint64()
-        {
-            var engine = new Engine();
-            var source = new ulong[] { 42, 12 };
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.BigUint64Array.Construct(source));
-            ValidateCreatedBigIntegerTypeArray(engine, "BigUint64Array");
+    [Fact]
+    public void CanInteropWithBigInt64()
+    {
+        var engine = new Engine();
+        var source = new long[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.BigInt64Array.Construct(source));
+        ValidateCreatedBigIntegerTypeArray(engine, "BigInt64Array");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsBigInt64Array());
+        Assert.Equal(source, fromEngine.AsBigInt64Array());
+    }
 
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsBigUint64Array());
-            Assert.Equal(source, fromEngine.AsBigUint64Array());
-        }
+    [Fact]
+    public void CanInteropWithBigUint64()
+    {
+        var engine = new Engine();
+        var source = new ulong[] { 42, 12 };
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.BigUint64Array.Construct(source));
+        ValidateCreatedBigIntegerTypeArray(engine, "BigUint64Array");
+
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsBigUint64Array());
+        Assert.Equal(source, fromEngine.AsBigUint64Array());
+    }
 
 #if NET6_0_OR_GREATER
         [Fact]
@@ -136,48 +136,47 @@ namespace Jint.Tests.Runtime
         }
 #endif
 
-        [Fact]
-        public void CanInteropWithFloat32()
-        {
-            var engine = new Engine();
-            var source = new float[] { 42f, 12f };
+    [Fact]
+    public void CanInteropWithFloat32()
+    {
+        var engine = new Engine();
+        var source = new float[] { 42f, 12f };
 
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Float32Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Float32Array");
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Float32Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Float32Array");
 
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsFloat32Array());
-            Assert.Equal(source, fromEngine.AsFloat32Array());
-        }
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsFloat32Array());
+        Assert.Equal(source, fromEngine.AsFloat32Array());
+    }
 
-        [Fact]
-        public void CanInteropWithFloat64()
-        {
-            var engine = new Engine();
-            var source = new double[] { 42f, 12f };
+    [Fact]
+    public void CanInteropWithFloat64()
+    {
+        var engine = new Engine();
+        var source = new double[] { 42f, 12f };
             
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Float64Array.Construct(source));
-            ValidateCreatedTypeArray(engine, "Float64Array");
+        engine.SetValue("testSubject", engine.Realm.Intrinsics.Float64Array.Construct(source));
+        ValidateCreatedTypeArray(engine, "Float64Array");
             
-            var fromEngine = engine.GetValue("testSubject");
-            Assert.True(fromEngine.IsFloat64Array());
-            Assert.Equal(source, fromEngine.AsFloat64Array());
-        }
+        var fromEngine = engine.GetValue("testSubject");
+        Assert.True(fromEngine.IsFloat64Array());
+        Assert.Equal(source, fromEngine.AsFloat64Array());
+    }
         
-        private static void ValidateCreatedTypeArray(Engine engine, string arrayName)
-        {
-            Assert.Equal(arrayName, engine.Evaluate("testSubject.constructor.name").AsString());
-            Assert.Equal(2, engine.Evaluate("testSubject.length").AsNumber());
-            Assert.Equal(42, engine.Evaluate("testSubject[0]").AsNumber());
-            Assert.Equal(12, engine.Evaluate("testSubject[1]").AsNumber());
-        }
+    private static void ValidateCreatedTypeArray(Engine engine, string arrayName)
+    {
+        Assert.Equal(arrayName, engine.Evaluate("testSubject.constructor.name").AsString());
+        Assert.Equal(2, engine.Evaluate("testSubject.length").AsNumber());
+        Assert.Equal(42, engine.Evaluate("testSubject[0]").AsNumber());
+        Assert.Equal(12, engine.Evaluate("testSubject[1]").AsNumber());
+    }
 
-        private static void ValidateCreatedBigIntegerTypeArray(Engine engine, string arrayName)
-        {
-            Assert.Equal(arrayName, engine.Evaluate("testSubject.constructor.name").AsString());
-            Assert.Equal(2, engine.Evaluate("testSubject.length").AsNumber());
-            Assert.Equal(42, engine.Evaluate("testSubject[0]").AsBigInt());
-            Assert.Equal(12, engine.Evaluate("testSubject[1]").AsBigInt());
-        }
+    private static void ValidateCreatedBigIntegerTypeArray(Engine engine, string arrayName)
+    {
+        Assert.Equal(arrayName, engine.Evaluate("testSubject.constructor.name").AsString());
+        Assert.Equal(2, engine.Evaluate("testSubject.length").AsNumber());
+        Assert.Equal(42, engine.Evaluate("testSubject[0]").AsBigInt());
+        Assert.Equal(12, engine.Evaluate("testSubject[1]").AsBigInt());
     }
-}
+}

+ 61 - 62
Jint.Tests/Runtime/UnicodeTests.cs

@@ -1,63 +1,62 @@
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class UnicodeTests
 {
-    public class UnicodeTests
-    {
-        private readonly Engine _engine;
-
-        public UnicodeTests()
-        {
-            _engine = new Engine()
-                    .SetValue("log", new Action<object>(Console.WriteLine))
-                    .SetValue("assert", new Action<bool>(Assert.True))
-                    .SetValue("equal", new Action<object, object>(Assert.Equal));
-        }
-
-        private void RunTest(string source)
-        {
-            _engine.Execute(source);
-        }
-
-        [Fact]
-        public void EscapeUnicodeUnits()
-        {
-            var value = _engine.Evaluate(@"var a = '\uD83D\uDE80'; return a;").AsString();
-            Assert.Equal("🚀", value);
-        }
-
-        [Fact]
-        public void EscapeUnicodeEscaped()
-        {
-            var value = _engine.Evaluate(@"var a = '\u{1F680}'; return a;").AsString();
-            Assert.Equal("🚀", value);
-        }
-
-        [Fact]
-        public void UnicodeIdentifiers()
-        {
-            var value = _engine.Evaluate(@"const hello = 123; return hell\u{6F}").AsNumber();
-            Assert.Equal(123, value);
-        }
-
-        [Fact]
-        public void RegexDontParseUnicodeEscapesWithoutFlag()
-        {
-            var value = _engine.Evaluate(@"return /^\u{3}$/.test('uuu')").AsBoolean();
-            Assert.True(value);
-        }
-
-        [Fact]
-        public void RegexParseUnicodeEscapesWithFlag()
-        {
-            var value = _engine.Evaluate(@"return /^\u{3}$/u.test('uuu')").AsBoolean();
-            Assert.False(value);
-        }
-
-        [Fact]
-        public void RegexParseUnicodeDoesntChangeSource()
-        {
-            var value = _engine.Evaluate(@"return /a\u0041/.source").AsString();
-            Assert.Equal("a\\u0041", value);
-        }
-
-    }
-}
+    private readonly Engine _engine;
+
+    public UnicodeTests()
+    {
+        _engine = new Engine()
+            .SetValue("log", new Action<object>(Console.WriteLine))
+            .SetValue("assert", new Action<bool>(Assert.True))
+            .SetValue("equal", new Action<object, object>(Assert.Equal));
+    }
+
+    private void RunTest(string source)
+    {
+        _engine.Execute(source);
+    }
+
+    [Fact]
+    public void EscapeUnicodeUnits()
+    {
+        var value = _engine.Evaluate(@"var a = '\uD83D\uDE80'; return a;").AsString();
+        Assert.Equal("🚀", value);
+    }
+
+    [Fact]
+    public void EscapeUnicodeEscaped()
+    {
+        var value = _engine.Evaluate(@"var a = '\u{1F680}'; return a;").AsString();
+        Assert.Equal("🚀", value);
+    }
+
+    [Fact]
+    public void UnicodeIdentifiers()
+    {
+        var value = _engine.Evaluate(@"const hello = 123; return hell\u{6F}").AsNumber();
+        Assert.Equal(123, value);
+    }
+
+    [Fact]
+    public void RegexDontParseUnicodeEscapesWithoutFlag()
+    {
+        var value = _engine.Evaluate(@"return /^\u{3}$/.test('uuu')").AsBoolean();
+        Assert.True(value);
+    }
+
+    [Fact]
+    public void RegexParseUnicodeEscapesWithFlag()
+    {
+        var value = _engine.Evaluate(@"return /^\u{3}$/u.test('uuu')").AsBoolean();
+        Assert.False(value);
+    }
+
+    [Fact]
+    public void RegexParseUnicodeDoesntChangeSource()
+    {
+        var value = _engine.Evaluate(@"return /a\u0041/.source").AsString();
+        Assert.Equal("a\\u0041", value);
+    }
+
+}

+ 41 - 42
Jint.Tests/Runtime/UuidTests.cs

@@ -1,48 +1,47 @@
 using Jint.Tests.Runtime.Domain;
 
-namespace Jint.Tests.Runtime
+namespace Jint.Tests.Runtime;
+
+public class UuidTests : IDisposable
 {
-    public class UuidTests : IDisposable
-    {
-        private readonly Engine _engine;
+    private readonly Engine _engine;
 
-        public UuidTests()
-        {
-            _engine = new Engine(o => o.AddObjectConverter(new UuidConverter()))
+    public UuidTests()
+    {
+        _engine = new Engine(o => o.AddObjectConverter(new UuidConverter()))
                 .SetValue("copy", new Func<Guid, Guid>(v => new Guid(v.ToByteArray())))
-                ;
-            UuidConstructor.CreateUuidConstructor(_engine);
-        }
-
-        void IDisposable.Dispose()
-        {
-        }
-
-        private object RunTest(string source)
-        {
-            return _engine.Evaluate(source).ToObject();
-        }
-
-        [Fact]
-        public void Empty()
-        {
-            Assert.Equal(Guid.Empty, RunTest($"Uuid.parse('{Guid.Empty}')"));
-            Assert.Equal(Guid.Empty, RunTest($"Uuid.Empty"));
-        }
-
-        [Fact]
-        public void Random()
-        {
-            var actual = RunTest($"new Uuid()");
-            Assert.NotEqual(Guid.Empty, actual);
-            Assert.IsType<Guid>(actual);
-        }
-
-        [Fact]
-        public void Copy()
-        {
-            _engine.Evaluate("const g = new Uuid();");
-            Assert.Equal(_engine.Evaluate("copy(g).toString()").AsString(), _engine.Evaluate("g.toString()").AsString());
-        }
+            ;
+        UuidConstructor.CreateUuidConstructor(_engine);
+    }
+
+    void IDisposable.Dispose()
+    {
+    }
+
+    private object RunTest(string source)
+    {
+        return _engine.Evaluate(source).ToObject();
+    }
+
+    [Fact]
+    public void Empty()
+    {
+        Assert.Equal(Guid.Empty, RunTest($"Uuid.parse('{Guid.Empty}')"));
+        Assert.Equal(Guid.Empty, RunTest($"Uuid.Empty"));
+    }
+
+    [Fact]
+    public void Random()
+    {
+        var actual = RunTest($"new Uuid()");
+        Assert.NotEqual(Guid.Empty, actual);
+        Assert.IsType<Guid>(actual);
+    }
+
+    [Fact]
+    public void Copy()
+    {
+        _engine.Evaluate("const g = new Uuid();");
+        Assert.Equal(_engine.Evaluate("copy(g).toString()").AsString(), _engine.Evaluate("g.toString()").AsString());
     }
-}
+}

+ 406 - 407
Jint/AstExtensions.cs

@@ -9,541 +9,540 @@ using Jint.Runtime.Interpreter.Expressions;
 using Jint.Runtime.Modules;
 using Environment = Jint.Runtime.Environments.Environment;
 
-namespace Jint
+namespace Jint;
+
+public static class AstExtensions
 {
-    public static class AstExtensions
-    {
 #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
-        internal static readonly SourceLocation DefaultLocation;
+    internal static readonly SourceLocation DefaultLocation;
 #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value
 
-        public static JsValue GetKey<T>(this T property, Engine engine) where T : IProperty => GetKey(property.Key, engine, property.Computed);
+    public static JsValue GetKey<T>(this T property, Engine engine) where T : IProperty => GetKey(property.Key, engine, property.Computed);
 
-        public static JsValue GetKey(this Expression expression, Engine engine, bool resolveComputed = false)
+    public static JsValue GetKey(this Expression expression, Engine engine, bool resolveComputed = false)
+    {
+        var key = TryGetKey(expression, engine, resolveComputed);
+        if (key is not null)
         {
-            var key = TryGetKey(expression, engine, resolveComputed);
-            if (key is not null)
-            {
-                return TypeConverter.ToPropertyKey(key);
-            }
-
-            ExceptionHelper.ThrowArgumentException("Unable to extract correct key, node type: " + expression.Type);
-            return JsValue.Undefined;
+            return TypeConverter.ToPropertyKey(key);
         }
 
-        internal static JsValue TryGetKey<T>(this T property, Engine engine) where T : IProperty
+        ExceptionHelper.ThrowArgumentException("Unable to extract correct key, node type: " + expression.Type);
+        return JsValue.Undefined;
+    }
+
+    internal static JsValue TryGetKey<T>(this T property, Engine engine) where T : IProperty
+    {
+        return TryGetKey(property.Key, engine, property.Computed);
+    }
+
+    internal static JsValue TryGetKey<T>(this T expression, Engine engine, bool resolveComputed) where T : Expression
+    {
+        JsValue key;
+        if (expression is Literal literal)
         {
-            return TryGetKey(property.Key, engine, property.Computed);
+            key = literal.Kind == TokenKind.NullLiteral ? JsValue.Null : LiteralKeyToString(literal);
         }
-
-        internal static JsValue TryGetKey<T>(this T expression, Engine engine, bool resolveComputed) where T : Expression
+        else if (!resolveComputed && expression is Identifier identifier)
         {
-            JsValue key;
-            if (expression is Literal literal)
-            {
-                key = literal.Kind == TokenKind.NullLiteral ? JsValue.Null : LiteralKeyToString(literal);
-            }
-            else if (!resolveComputed && expression is Identifier identifier)
-            {
-                key = identifier.Name;
-            }
-            else if (expression is PrivateIdentifier privateIdentifier)
-            {
-                key = engine.ExecutionContext.PrivateEnvironment!.Names[privateIdentifier];
-            }
-            else if (resolveComputed)
-            {
-                return TryGetComputedPropertyKey(expression, engine);
-            }
-            else
-            {
-                key = JsValue.Undefined;
-            }
-            return key;
-        }
-
-        internal static JsValue TryGetComputedPropertyKey<T>(T expression, Engine engine)
-            where T : Expression
-        {
-            if (expression.Type is NodeType.Identifier
-                or NodeType.CallExpression
-                or NodeType.BinaryExpression
-                or NodeType.UpdateExpression
-                or NodeType.AssignmentExpression
-                or NodeType.UnaryExpression
-                or NodeType.MemberExpression
-                or NodeType.LogicalExpression
-                or NodeType.ConditionalExpression
-                or NodeType.ArrowFunctionExpression
-                or NodeType.FunctionExpression
-                or NodeType.YieldExpression
-                or NodeType.TemplateLiteral)
-            {
-                var context = engine._activeEvaluationContext ?? new EvaluationContext(engine);
-                return JintExpression.Build(expression).GetValue(context);
-            }
-
-            return JsValue.Undefined;
+            key = identifier.Name;
         }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsFunctionDefinition<T>(this T node) where T : Node
+        else if (expression is PrivateIdentifier privateIdentifier)
+        {
+            key = engine.ExecutionContext.PrivateEnvironment!.Names[privateIdentifier];
+        }
+        else if (resolveComputed)
+        {
+            return TryGetComputedPropertyKey(expression, engine);
+        }
+        else
         {
-            var type = node.Type;
-            return type
-                is NodeType.FunctionExpression
-                or NodeType.ArrowFunctionExpression
-                or NodeType.ClassExpression;
+            key = JsValue.Undefined;
         }
+        return key;
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsStrict(this IFunction function)
+    internal static JsValue TryGetComputedPropertyKey<T>(T expression, Engine engine)
+        where T : Expression
+    {
+        if (expression.Type is NodeType.Identifier
+            or NodeType.CallExpression
+            or NodeType.BinaryExpression
+            or NodeType.UpdateExpression
+            or NodeType.AssignmentExpression
+            or NodeType.UnaryExpression
+            or NodeType.MemberExpression
+            or NodeType.LogicalExpression
+            or NodeType.ConditionalExpression
+            or NodeType.ArrowFunctionExpression
+            or NodeType.FunctionExpression
+            or NodeType.YieldExpression
+            or NodeType.TemplateLiteral)
         {
-            return function.Body is FunctionBody { Strict: true };
+            var context = engine._activeEvaluationContext ?? new EvaluationContext(engine);
+            return JintExpression.Build(expression).GetValue(context);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-static-semantics-isconstantdeclaration
-        /// </summary>
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsConstantDeclaration(this Declaration d)
+        return JsValue.Undefined;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool IsFunctionDefinition<T>(this T node) where T : Node
+    {
+        var type = node.Type;
+        return type
+            is NodeType.FunctionExpression
+            or NodeType.ArrowFunctionExpression
+            or NodeType.ClassExpression;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool IsStrict(this IFunction function)
+    {
+        return function.Body is FunctionBody { Strict: true };
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-static-semantics-isconstantdeclaration
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool IsConstantDeclaration(this Declaration d)
+    {
+        return d is VariableDeclaration { Kind: VariableDeclarationKind.Const };
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool HasName<T>(this T node) where T : Node
+    {
+        if (!node.IsFunctionDefinition())
         {
-            return d is VariableDeclaration { Kind: VariableDeclarationKind.Const };
+            return false;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool HasName<T>(this T node) where T : Node
+        if (node is IFunction { Id: not null })
         {
-            if (!node.IsFunctionDefinition())
-            {
-                return false;
-            }
+            return true;
+        }
 
-            if (node is IFunction { Id: not null })
-            {
-                return true;
-            }
+        if (node is ClassExpression { Id: not null })
+        {
+            return true;
+        }
 
-            if (node is ClassExpression { Id: not null })
-            {
-                return true;
-            }
+        return false;
+    }
 
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool IsAnonymousFunctionDefinition<T>(this T node) where T : Node
+    {
+        if (!node.IsFunctionDefinition())
+        {
             return false;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsAnonymousFunctionDefinition<T>(this T node) where T : Node
+        if (node.HasName())
         {
-            if (!node.IsFunctionDefinition())
-            {
-                return false;
-            }
+            return false;
+        }
 
-            if (node.HasName())
-            {
-                return false;
-            }
+        return true;
+    }
 
-            return true;
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool IsOptional<T>(this T node) where T : Expression
+    {
+        return node is IChainElement { Optional: true };
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static string LiteralKeyToString(Literal literal)
+    {
+        if (literal is StringLiteral stringLiteral)
+        {
+            return stringLiteral.Value;
+        }
+        // prevent conversion to scientific notation
+        else if (literal is NumericLiteral numericLiteral)
+        {
+            return TypeConverter.ToString(numericLiteral.Value);
+        }
+        else if (literal is BigIntLiteral bigIntLiteral)
+        {
+            return bigIntLiteral.Value.ToString(provider: null);
+        }
+        else
+        {
+            // We shouldn't ever reach this line in the case of a literal property key.
+            return Convert.ToString(literal.Value, provider: null) ?? "";
         }
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsOptional<T>(this T node) where T : Expression
+    internal static void GetBoundNames(this VariableDeclaration variableDeclaration, List<Key> target)
+    {
+        ref readonly var declarations = ref variableDeclaration.Declarations;
+        for (var i = 0; i < declarations.Count; i++)
         {
-            return node is IChainElement { Optional: true };
+            var declaration = declarations[i];
+            GetBoundNames(declaration.Id, target);
         }
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static string LiteralKeyToString(Literal literal)
+    internal static void GetBoundNames(this Node? parameter, List<Key> target)
+    {
+        if (parameter is null || parameter.Type == NodeType.Literal)
         {
-            if (literal is StringLiteral stringLiteral)
-            {
-                return stringLiteral.Value;
-            }
-            // prevent conversion to scientific notation
-            else if (literal is NumericLiteral numericLiteral)
-            {
-                return TypeConverter.ToString(numericLiteral.Value);
-            }
-            else if (literal is BigIntLiteral bigIntLiteral)
-            {
-                return bigIntLiteral.Value.ToString(provider: null);
-            }
-            else
-            {
-                // We shouldn't ever reach this line in the case of a literal property key.
-                return Convert.ToString(literal.Value, provider: null) ?? "";
-            }
+            return;
         }
 
-        internal static void GetBoundNames(this VariableDeclaration variableDeclaration, List<Key> target)
+        // try to get away without a loop
+        if (parameter is Identifier id)
         {
-            ref readonly var declarations = ref variableDeclaration.Declarations;
-            for (var i = 0; i < declarations.Count; i++)
-            {
-                var declaration = declarations[i];
-                GetBoundNames(declaration.Id, target);
-            }
+            target.Add(id.Name);
+            return;
         }
 
-        internal static void GetBoundNames(this Node? parameter, List<Key> target)
+        if (parameter is VariableDeclaration variableDeclaration)
         {
-            if (parameter is null || parameter.Type == NodeType.Literal)
-            {
-                return;
-            }
+            variableDeclaration.GetBoundNames(target);
+            return;
+        }
 
-            // try to get away without a loop
-            if (parameter is Identifier id)
+        while (true)
+        {
+            if (parameter is Identifier identifier)
             {
-                target.Add(id.Name);
+                target.Add(identifier.Name);
                 return;
             }
 
-            if (parameter is VariableDeclaration variableDeclaration)
+            if (parameter is RestElement restElement)
             {
-                variableDeclaration.GetBoundNames(target);
-                return;
+                parameter = restElement.Argument;
+                continue;
             }
 
-            while (true)
+            if (parameter is ArrayPattern arrayPattern)
             {
-                if (parameter is Identifier identifier)
-                {
-                    target.Add(identifier.Name);
-                    return;
-                }
-
-                if (parameter is RestElement restElement)
+                ref readonly var arrayPatternElements = ref arrayPattern.Elements;
+                for (var i = 0; i < arrayPatternElements.Count; i++)
                 {
-                    parameter = restElement.Argument;
-                    continue;
+                    var expression = arrayPatternElements[i];
+                    GetBoundNames(expression, target);
                 }
-
-                if (parameter is ArrayPattern arrayPattern)
+            }
+            else if (parameter is ObjectPattern objectPattern)
+            {
+                ref readonly var objectPatternProperties = ref objectPattern.Properties;
+                for (var i = 0; i < objectPatternProperties.Count; i++)
                 {
-                    ref readonly var arrayPatternElements = ref arrayPattern.Elements;
-                    for (var i = 0; i < arrayPatternElements.Count; i++)
+                    var property = objectPatternProperties[i];
+                    if (property is AssignmentProperty p)
                     {
-                        var expression = arrayPatternElements[i];
-                        GetBoundNames(expression, target);
+                        GetBoundNames(p.Value, target);
                     }
-                }
-                else if (parameter is ObjectPattern objectPattern)
-                {
-                    ref readonly var objectPatternProperties = ref objectPattern.Properties;
-                    for (var i = 0; i < objectPatternProperties.Count; i++)
-                    {
-                        var property = objectPatternProperties[i];
-                        if (property is AssignmentProperty p)
-                        {
-                            GetBoundNames(p.Value, target);
-                        }
-                        else
-                        {
-                            GetBoundNames((RestElement) property, target);
-                        }
-                    }
-                }
-                else if (parameter is AssignmentPattern assignmentPattern)
-                {
-                    parameter = assignmentPattern.Left;
-                    continue;
-                }
-                else if (parameter is ClassDeclaration classDeclaration)
-                {
-                    var name = classDeclaration.Id?.Name;
-                    if (name != null)
+                    else
                     {
-                        target.Add(name);
+                        GetBoundNames((RestElement) property, target);
                     }
                 }
-                break;
             }
-        }
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-static-semantics-privateboundidentifiers
-        /// </summary>
-        internal static void PrivateBoundIdentifiers(this Node parameter, HashSet<PrivateIdentifier> target)
-        {
-            if (parameter.Type == NodeType.PrivateIdentifier)
+            else if (parameter is AssignmentPattern assignmentPattern)
             {
-                target.Add((PrivateIdentifier) parameter);
+                parameter = assignmentPattern.Left;
+                continue;
             }
-            else if (parameter.Type is NodeType.AccessorProperty or NodeType.MethodDefinition or NodeType.PropertyDefinition)
+            else if (parameter is ClassDeclaration classDeclaration)
             {
-                if (((ClassProperty) parameter).Key is PrivateIdentifier privateKeyIdentifier)
+                var name = classDeclaration.Id?.Name;
+                if (name != null)
                 {
-                    target.Add(privateKeyIdentifier);
-                }
-            }
-            else if (parameter.Type == NodeType.ClassBody)
-            {
-                ref readonly var elements = ref ((ClassBody) parameter).Body;
-                for (var i = 0; i < elements.Count; i++)
-                {
-                    var element = elements[i];
-                    PrivateBoundIdentifiers(element, target);
+                    target.Add(name);
                 }
             }
+            break;
         }
+    }
 
-        internal static void BindingInitialization(
-            this Node? expression,
-            EvaluationContext context,
-            JsValue value,
-            Environment env)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-static-semantics-privateboundidentifiers
+    /// </summary>
+    internal static void PrivateBoundIdentifiers(this Node parameter, HashSet<PrivateIdentifier> target)
+    {
+        if (parameter.Type == NodeType.PrivateIdentifier)
         {
-            if (expression is Identifier identifier)
+            target.Add((PrivateIdentifier) parameter);
+        }
+        else if (parameter.Type is NodeType.AccessorProperty or NodeType.MethodDefinition or NodeType.PropertyDefinition)
+        {
+            if (((ClassProperty) parameter).Key is PrivateIdentifier privateKeyIdentifier)
             {
-                var catchEnvRecord = (DeclarativeEnvironment) env;
-                catchEnvRecord.CreateMutableBindingAndInitialize(identifier.Name, canBeDeleted: false, value);
+                target.Add(privateKeyIdentifier);
             }
-            else if (expression is DestructuringPattern pattern)
+        }
+        else if (parameter.Type == NodeType.ClassBody)
+        {
+            ref readonly var elements = ref ((ClassBody) parameter).Body;
+            for (var i = 0; i < elements.Count; i++)
             {
-                DestructuringPatternAssignmentExpression.ProcessPatterns(context, pattern, value, env);
+                var element = elements[i];
+                PrivateBoundIdentifiers(element, target);
             }
         }
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-runtime-semantics-definemethod
-        /// </summary>
-        internal static Record DefineMethod<T>(this T m, ObjectInstance obj, ObjectInstance? functionPrototype = null) where T : IProperty
+    internal static void BindingInitialization(
+        this Node? expression,
+        EvaluationContext context,
+        JsValue value,
+        Environment env)
+    {
+        if (expression is Identifier identifier)
         {
-            var engine = obj.Engine;
-            var propKey = TypeConverter.ToPropertyKey(m.GetKey(engine));
-            var intrinsics = engine.Realm.Intrinsics;
-
-            var runningExecutionContext = engine.ExecutionContext;
-            var env = runningExecutionContext.LexicalEnvironment;
-            var privateEnv = runningExecutionContext.PrivateEnvironment;
+            var catchEnvRecord = (DeclarativeEnvironment) env;
+            catchEnvRecord.CreateMutableBindingAndInitialize(identifier.Name, canBeDeleted: false, value);
+        }
+        else if (expression is DestructuringPattern pattern)
+        {
+            DestructuringPatternAssignmentExpression.ProcessPatterns(context, pattern, value, env);
+        }
+    }
 
-            var prototype = functionPrototype ?? intrinsics.Function.PrototypeObject;
-            var function = m.Value as IFunction;
-            if (function is null)
-            {
-                ExceptionHelper.ThrowSyntaxError(engine.Realm);
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-runtime-semantics-definemethod
+    /// </summary>
+    internal static Record DefineMethod<T>(this T m, ObjectInstance obj, ObjectInstance? functionPrototype = null) where T : IProperty
+    {
+        var engine = obj.Engine;
+        var propKey = TypeConverter.ToPropertyKey(m.GetKey(engine));
+        var intrinsics = engine.Realm.Intrinsics;
 
-            var definition = new JintFunctionDefinition(function);
-            var closure = intrinsics.Function.OrdinaryFunctionCreate(prototype, definition, definition.ThisMode, env, privateEnv);
-            closure.MakeMethod(obj);
+        var runningExecutionContext = engine.ExecutionContext;
+        var env = runningExecutionContext.LexicalEnvironment;
+        var privateEnv = runningExecutionContext.PrivateEnvironment;
 
-            return new Record(propKey, closure);
+        var prototype = functionPrototype ?? intrinsics.Function.PrototypeObject;
+        var function = m.Value as IFunction;
+        if (function is null)
+        {
+            ExceptionHelper.ThrowSyntaxError(engine.Realm);
         }
 
-        internal static void GetImportEntries(this ImportDeclaration import, List<ImportEntry> importEntries, HashSet<ModuleRequest> requestedModules)
-        {
-            var source = import.Source.Value;
-            var specifiers = import.Specifiers;
-            var attributes = GetAttributes(import.Attributes);
-            requestedModules.Add(new ModuleRequest(source, attributes));
+        var definition = new JintFunctionDefinition(function);
+        var closure = intrinsics.Function.OrdinaryFunctionCreate(prototype, definition, definition.ThisMode, env, privateEnv);
+        closure.MakeMethod(obj);
+
+        return new Record(propKey, closure);
+    }
+
+    internal static void GetImportEntries(this ImportDeclaration import, List<ImportEntry> importEntries, HashSet<ModuleRequest> requestedModules)
+    {
+        var source = import.Source.Value;
+        var specifiers = import.Specifiers;
+        var attributes = GetAttributes(import.Attributes);
+        requestedModules.Add(new ModuleRequest(source, attributes));
 
-            foreach (var specifier in specifiers)
+        foreach (var specifier in specifiers)
+        {
+            switch (specifier)
             {
-                switch (specifier)
-                {
-                    case ImportNamespaceSpecifier namespaceSpecifier:
-                        importEntries.Add(new ImportEntry(new ModuleRequest(source, attributes), "*", namespaceSpecifier.Local.GetModuleKey()));
-                        break;
-                    case ImportSpecifier importSpecifier:
-                        importEntries.Add(new ImportEntry(new ModuleRequest(source, attributes), importSpecifier.Imported.GetModuleKey(), importSpecifier.Local.GetModuleKey()!));
-                        break;
-                    case ImportDefaultSpecifier defaultSpecifier:
-                        importEntries.Add(new ImportEntry(new ModuleRequest(source, attributes), "default", defaultSpecifier.Local.GetModuleKey()));
-                        break;
-                }
+                case ImportNamespaceSpecifier namespaceSpecifier:
+                    importEntries.Add(new ImportEntry(new ModuleRequest(source, attributes), "*", namespaceSpecifier.Local.GetModuleKey()));
+                    break;
+                case ImportSpecifier importSpecifier:
+                    importEntries.Add(new ImportEntry(new ModuleRequest(source, attributes), importSpecifier.Imported.GetModuleKey(), importSpecifier.Local.GetModuleKey()!));
+                    break;
+                case ImportDefaultSpecifier defaultSpecifier:
+                    importEntries.Add(new ImportEntry(new ModuleRequest(source, attributes), "default", defaultSpecifier.Local.GetModuleKey()));
+                    break;
             }
         }
+    }
 
-        private static ModuleImportAttribute[] GetAttributes(in NodeList<ImportAttribute> importAttributes)
+    private static ModuleImportAttribute[] GetAttributes(in NodeList<ImportAttribute> importAttributes)
+    {
+        if (importAttributes.Count == 0)
         {
-            if (importAttributes.Count == 0)
-            {
-                return Array.Empty<ModuleImportAttribute>();
-            }
+            return Array.Empty<ModuleImportAttribute>();
+        }
 
-            var attributes = new ModuleImportAttribute[importAttributes.Count];
-            for (var i = 0; i < importAttributes.Count; i++)
-            {
-                var attribute = importAttributes[i];
-                var key = attribute.Key is Identifier identifier ? identifier.Name : ((StringLiteral) attribute.Key).Value;
-                attributes[i] = new ModuleImportAttribute(key, attribute.Value.Value);
-            }
-            return attributes;
+        var attributes = new ModuleImportAttribute[importAttributes.Count];
+        for (var i = 0; i < importAttributes.Count; i++)
+        {
+            var attribute = importAttributes[i];
+            var key = attribute.Key is Identifier identifier ? identifier.Name : ((StringLiteral) attribute.Key).Value;
+            attributes[i] = new ModuleImportAttribute(key, attribute.Value.Value);
         }
+        return attributes;
+    }
 
-        internal static void GetExportEntries(this ExportDeclaration export, List<ExportEntry> exportEntries, HashSet<ModuleRequest> requestedModules)
+    internal static void GetExportEntries(this ExportDeclaration export, List<ExportEntry> exportEntries, HashSet<ModuleRequest> requestedModules)
+    {
+        switch (export)
         {
-            switch (export)
-            {
-                case ExportDefaultDeclaration defaultDeclaration:
-                    GetExportEntries(true, defaultDeclaration.Declaration, exportEntries);
-                    break;
-                case ExportAllDeclaration allDeclaration:
-                    //Note: there is a pending PR for Esprima to support exporting an imported modules content as a namespace i.e. 'export * as ns from "mod"'
-                    requestedModules.Add(new ModuleRequest(allDeclaration.Source.Value, []));
-                    exportEntries.Add(new(allDeclaration.Exported?.GetModuleKey(), new ModuleRequest(allDeclaration.Source.Value, []), "*", null));
-                    break;
-                case ExportNamedDeclaration namedDeclaration:
-                    ref readonly var specifiers = ref namedDeclaration.Specifiers;
-                    if (specifiers.Count == 0)
-                    {
-                        ModuleRequest? moduleRequest = namedDeclaration.Source != null
-                            ? new ModuleRequest(namedDeclaration.Source.Value, [])
-                            : null;
+            case ExportDefaultDeclaration defaultDeclaration:
+                GetExportEntries(true, defaultDeclaration.Declaration, exportEntries);
+                break;
+            case ExportAllDeclaration allDeclaration:
+                //Note: there is a pending PR for Esprima to support exporting an imported modules content as a namespace i.e. 'export * as ns from "mod"'
+                requestedModules.Add(new ModuleRequest(allDeclaration.Source.Value, []));
+                exportEntries.Add(new(allDeclaration.Exported?.GetModuleKey(), new ModuleRequest(allDeclaration.Source.Value, []), "*", null));
+                break;
+            case ExportNamedDeclaration namedDeclaration:
+                ref readonly var specifiers = ref namedDeclaration.Specifiers;
+                if (specifiers.Count == 0)
+                {
+                    ModuleRequest? moduleRequest = namedDeclaration.Source != null
+                        ? new ModuleRequest(namedDeclaration.Source.Value, [])
+                        : null;
 
-                        GetExportEntries(false, namedDeclaration.Declaration!, exportEntries, moduleRequest);
-                    }
-                    else
+                    GetExportEntries(false, namedDeclaration.Declaration!, exportEntries, moduleRequest);
+                }
+                else
+                {
+                    for (var i = 0; i < specifiers.Count; i++)
                     {
-                        for (var i = 0; i < specifiers.Count; i++)
+                        var specifier = specifiers[i];
+                        if (namedDeclaration.Source != null)
                         {
-                            var specifier = specifiers[i];
-                            if (namedDeclaration.Source != null)
-                            {
-                                exportEntries.Add(new(specifier.Exported.GetModuleKey(), new ModuleRequest(namedDeclaration.Source.Value, []), specifier.Local.GetModuleKey(), null));
-                            }
-                            else
-                            {
-                                exportEntries.Add(new(specifier.Exported.GetModuleKey(), null, null, specifier.Local.GetModuleKey()));
-                            }
+                            exportEntries.Add(new(specifier.Exported.GetModuleKey(), new ModuleRequest(namedDeclaration.Source.Value, []), specifier.Local.GetModuleKey(), null));
+                        }
+                        else
+                        {
+                            exportEntries.Add(new(specifier.Exported.GetModuleKey(), null, null, specifier.Local.GetModuleKey()));
                         }
                     }
+                }
 
-                    if (namedDeclaration.Source is not null)
-                    {
-                        requestedModules.Add(new ModuleRequest(namedDeclaration.Source.Value, []));
-                    }
+                if (namedDeclaration.Source is not null)
+                {
+                    requestedModules.Add(new ModuleRequest(namedDeclaration.Source.Value, []));
+                }
 
-                    break;
-            }
+                break;
         }
+    }
 
-        private static void GetExportEntries(bool defaultExport, StatementOrExpression declaration, List<ExportEntry> exportEntries, ModuleRequest? moduleRequest = null)
-        {
-            var names = GetExportNames(declaration);
+    private static void GetExportEntries(bool defaultExport, StatementOrExpression declaration, List<ExportEntry> exportEntries, ModuleRequest? moduleRequest = null)
+    {
+        var names = GetExportNames(declaration);
 
-            if (names.Count == 0)
+        if (names.Count == 0)
+        {
+            if (defaultExport)
             {
-                if (defaultExport)
-                {
-                    exportEntries.Add(new("default", null, null, "*default*"));
-                }
+                exportEntries.Add(new("default", null, null, "*default*"));
             }
-            else
+        }
+        else
+        {
+            for (var i = 0; i < names.Count; i++)
             {
-                for (var i = 0; i < names.Count; i++)
-                {
-                    var name = names[i];
-                    var exportName = defaultExport ? "default" : name.Name;
-                    exportEntries.Add(new(exportName, moduleRequest, null, name));
-                }
+                var name = names[i];
+                var exportName = defaultExport ? "default" : name.Name;
+                exportEntries.Add(new(exportName, moduleRequest, null, name));
             }
         }
+    }
+
+    private static List<Key> GetExportNames(StatementOrExpression declaration)
+    {
+        var result = new List<Key>();
 
-        private static List<Key> GetExportNames(StatementOrExpression declaration)
+        switch (declaration)
         {
-            var result = new List<Key>();
+            case FunctionDeclaration functionDeclaration:
+                var funcName = functionDeclaration.Id?.Name;
+                if (funcName is not null)
+                {
+                    result.Add(funcName);
+                }
 
-            switch (declaration)
-            {
-                case FunctionDeclaration functionDeclaration:
-                    var funcName = functionDeclaration.Id?.Name;
-                    if (funcName is not null)
-                    {
-                        result.Add(funcName);
-                    }
+                break;
+            case ClassDeclaration classDeclaration:
+                var className = classDeclaration.Id?.Name;
+                if (className is not null)
+                {
+                    result.Add(className);
+                }
 
-                    break;
-                case ClassDeclaration classDeclaration:
-                    var className = classDeclaration.Id?.Name;
-                    if (className is not null)
-                    {
-                        result.Add(className);
-                    }
+                break;
+            case VariableDeclaration variableDeclaration:
+                variableDeclaration.GetBoundNames(result);
+                break;
+        }
 
-                    break;
-                case VariableDeclaration variableDeclaration:
-                    variableDeclaration.GetBoundNames(result);
-                    break;
-            }
+        return result;
+    }
 
-            return result;
-        }
+    private static string GetModuleKey(this Expression expression)
+    {
+        return (expression as Identifier)?.Name ?? ((StringLiteral) expression).Value;
+    }
 
-        private static string GetModuleKey(this Expression expression)
-        {
-            return (expression as Identifier)?.Name ?? ((StringLiteral) expression).Value;
-        }
+    internal readonly record struct Record(JsValue Key, ScriptFunction Closure);
+
+    /// <summary>
+    /// Creates a dummy node that can be used when only location available and node is required.
+    /// </summary>
+    internal static Node CreateLocationNode(in SourceLocation location)
+    {
+        return new MinimalSyntaxElement(location);
+    }
 
-        internal readonly record struct Record(JsValue Key, ScriptFunction Closure);
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-static-semantics-allprivateidentifiersvalid
+    /// </summary>
+    internal static void AllPrivateIdentifiersValid(this Script script, Realm realm, HashSet<PrivateIdentifier>? privateIdentifiers)
+    {
+        var validator = new PrivateIdentifierValidator(realm, privateIdentifiers);
+        validator.Visit(script);
+    }
 
-        /// <summary>
-        /// Creates a dummy node that can be used when only location available and node is required.
-        /// </summary>
-        internal static Node CreateLocationNode(in SourceLocation location)
+    private sealed class MinimalSyntaxElement : Node
+    {
+        public MinimalSyntaxElement(in SourceLocation location) : base(NodeType.Unknown)
         {
-            return new MinimalSyntaxElement(location);
+            Location = location;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-static-semantics-allprivateidentifiersvalid
-        /// </summary>
-        internal static void AllPrivateIdentifiersValid(this Script script, Realm realm, HashSet<PrivateIdentifier>? privateIdentifiers)
+        protected override IEnumerator<Node>? GetChildNodes() => throw new NotImplementedException();
+        protected override object? Accept(AstVisitor visitor) => throw new NotImplementedException();
+    }
+
+    private sealed class PrivateIdentifierValidator : AstVisitor
+    {
+        private readonly Realm _realm;
+        private HashSet<PrivateIdentifier>? _privateNames;
+
+        public PrivateIdentifierValidator(Realm realm, HashSet<PrivateIdentifier>? privateNames)
         {
-            var validator = new PrivateIdentifierValidator(realm, privateIdentifiers);
-            validator.Visit(script);
+            _realm = realm;
+            _privateNames = privateNames;
         }
 
-        private sealed class MinimalSyntaxElement : Node
+        protected override object VisitPrivateIdentifier(PrivateIdentifier privateIdentifier)
         {
-            public MinimalSyntaxElement(in SourceLocation location) : base(NodeType.Unknown)
+            if (_privateNames is null || !_privateNames.Contains(privateIdentifier))
             {
-                Location = location;
+                Throw(_realm, privateIdentifier);
             }
-
-            protected override IEnumerator<Node>? GetChildNodes() => throw new NotImplementedException();
-            protected override object? Accept(AstVisitor visitor) => throw new NotImplementedException();
+            return privateIdentifier;
         }
 
-        private sealed class PrivateIdentifierValidator : AstVisitor
+        protected override object VisitClassBody(ClassBody classBody)
         {
-            private readonly Realm _realm;
-            private HashSet<PrivateIdentifier>? _privateNames;
-
-            public PrivateIdentifierValidator(Realm realm, HashSet<PrivateIdentifier>? privateNames)
-            {
-                _realm = realm;
-                _privateNames = privateNames;
-            }
-
-            protected override object VisitPrivateIdentifier(PrivateIdentifier privateIdentifier)
-            {
-                if (_privateNames is null || !_privateNames.Contains(privateIdentifier))
-                {
-                    Throw(_realm, privateIdentifier);
-                }
-                return privateIdentifier;
-            }
-
-            protected override object VisitClassBody(ClassBody classBody)
-            {
-                var oldList = _privateNames;
-                _privateNames = new HashSet<PrivateIdentifier>(PrivateIdentifierNameComparer._instance);
-                classBody.PrivateBoundIdentifiers(_privateNames);
-                base.VisitClassBody(classBody);
-                _privateNames = oldList;
-                return classBody;
-            }
+            var oldList = _privateNames;
+            _privateNames = new HashSet<PrivateIdentifier>(PrivateIdentifierNameComparer._instance);
+            classBody.PrivateBoundIdentifiers(_privateNames);
+            base.VisitClassBody(classBody);
+            _privateNames = oldList;
+            return classBody;
+        }
 
-            [MethodImpl(MethodImplOptions.NoInlining)]
-            private static void Throw(Realm r, PrivateIdentifier id)
-            {
-                ExceptionHelper.ThrowSyntaxError(r, $"Private field '#{id.Name}' must be declared in an enclosing class");
-            }
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void Throw(Realm r, PrivateIdentifier id)
+        {
+            ExceptionHelper.ThrowSyntaxError(r, $"Private field '#{id.Name}' must be declared in an enclosing class");
         }
     }
-}
+}

+ 229 - 230
Jint/Collections/DictionarySlim.cs

@@ -9,292 +9,291 @@ using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
-namespace Jint.Collections
+namespace Jint.Collections;
+
+/// <summary>
+/// DictionarySlim&lt;string, TValue> is similar to Dictionary&lt;TKey, TValue> but optimized in three ways:
+/// 1) It allows access to the value by ref replacing the common TryGetValue and Add pattern.
+/// 2) It does not store the hash code (assumes it is cheap to equate values).
+/// 3) It does not accept an equality comparer (assumes Object.GetHashCode() and Object.Equals() or overridden implementation are cheap and sufficient).
+/// </summary>
+[DebuggerDisplay("Count = {Count}")]
+internal class DictionarySlim<TKey, TValue> : IReadOnlyCollection<KeyValuePair<TKey, TValue>> where TKey : IEquatable<TKey>
 {
-    /// <summary>
-    /// DictionarySlim&lt;string, TValue> is similar to Dictionary&lt;TKey, TValue> but optimized in three ways:
-    /// 1) It allows access to the value by ref replacing the common TryGetValue and Add pattern.
-    /// 2) It does not store the hash code (assumes it is cheap to equate values).
-    /// 3) It does not accept an equality comparer (assumes Object.GetHashCode() and Object.Equals() or overridden implementation are cheap and sufficient).
-    /// </summary>
-    [DebuggerDisplay("Count = {Count}")]
-    internal class DictionarySlim<TKey, TValue> : IReadOnlyCollection<KeyValuePair<TKey, TValue>> where TKey : IEquatable<TKey>
+    // We want to initialize without allocating arrays. We also want to avoid null checks.
+    // Array.Empty would give divide by zero in modulo operation. So we use static one element arrays.
+    // The first add will cause a resize replacing these with real arrays of three elements.
+    // Arrays are wrapped in a class to avoid being duplicated for each <TKey, TValue>
+    private static readonly Entry[] InitialEntries = new Entry[1];
+    private int _count;
+    // 0-based index into _entries of head of free chain: -1 means empty
+    private int _freeList = -1;
+    // 1-based index into _entries; 0 means empty
+    private int[] _buckets;
+    private Entry[] _entries;
+
+    [DebuggerDisplay("({key}, {value})->{next}")]
+    [StructLayout(LayoutKind.Auto)]
+    private struct Entry
     {
-        // We want to initialize without allocating arrays. We also want to avoid null checks.
-        // Array.Empty would give divide by zero in modulo operation. So we use static one element arrays.
-        // The first add will cause a resize replacing these with real arrays of three elements.
-        // Arrays are wrapped in a class to avoid being duplicated for each <TKey, TValue>
-        private static readonly Entry[] InitialEntries = new Entry[1];
-        private int _count;
-        // 0-based index into _entries of head of free chain: -1 means empty
-        private int _freeList = -1;
-        // 1-based index into _entries; 0 means empty
-        private int[] _buckets;
-        private Entry[] _entries;
-
-        [DebuggerDisplay("({key}, {value})->{next}")]
-        [StructLayout(LayoutKind.Auto)]
-        private struct Entry
-        {
-            public TKey key;
-            public TValue value;
-            // 0-based index of next entry in chain: -1 means end of chain
-            // also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3,
-            // so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc.
-            public int next;
-        }
+        public TKey key;
+        public TValue value;
+        // 0-based index of next entry in chain: -1 means end of chain
+        // also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3,
+        // so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc.
+        public int next;
+    }
 
-        public DictionarySlim()
-        {
-            _buckets = HashHelpers.SizeOneIntArray;
-            _entries = InitialEntries;
-        }
+    public DictionarySlim()
+    {
+        _buckets = HashHelpers.SizeOneIntArray;
+        _entries = InitialEntries;
+    }
 
-        public DictionarySlim(int capacity)
-        {
-            if (capacity < 2)
-                capacity = 2; // 1 would indicate the dummy array
-            capacity = HashHelpers.PowerOf2(capacity);
-            _buckets = new int[capacity];
-            _entries = new Entry[capacity];
-        }
+    public DictionarySlim(int capacity)
+    {
+        if (capacity < 2)
+            capacity = 2; // 1 would indicate the dummy array
+        capacity = HashHelpers.PowerOf2(capacity);
+        _buckets = new int[capacity];
+        _entries = new Entry[capacity];
+    }
+
+    public int Count => _count;
 
-        public int Count => _count;
+    /// <summary>
+    /// Clears the dictionary. Note that this invalidates any active enumerators.
+    /// </summary>
+    public void Clear()
+    {
+        _count = 0;
+        _freeList = -1;
+        _buckets = HashHelpers.SizeOneIntArray;
+        _entries = InitialEntries;
+    }
 
-        /// <summary>
-        /// Clears the dictionary. Note that this invalidates any active enumerators.
-        /// </summary>
-        public void Clear()
+    public bool ContainsKey(TKey key)
+    {
+        Entry[] entries = _entries;
+        for (int i = _buckets[key.GetHashCode() & (_buckets.Length-1)] - 1;
+             (uint)i < (uint)entries.Length; i = entries[i].next)
         {
-            _count = 0;
-            _freeList = -1;
-            _buckets = HashHelpers.SizeOneIntArray;
-            _entries = InitialEntries;
+            if (key.Equals(entries[i].key))
+                return true;
         }
 
-        public bool ContainsKey(TKey key)
+        return false;
+    }
+
+    public bool TryGetValue(TKey key, out TValue value)
+    {
+        Entry[] entries = _entries;
+        for (int i = _buckets[key.GetHashCode() & (_buckets.Length - 1)] - 1;
+             (uint)i < (uint)entries.Length; i = entries[i].next)
         {
-            Entry[] entries = _entries;
-            for (int i = _buckets[key.GetHashCode() & (_buckets.Length-1)] - 1;
-                (uint)i < (uint)entries.Length; i = entries[i].next)
+            if (key.Equals(entries[i].key))
             {
-                if (key.Equals(entries[i].key))
-                    return true;
+                value = entries[i].value;
+                return true;
             }
-
-            return false;
         }
 
-        public bool TryGetValue(TKey key, out TValue value)
+        value = default;
+        return false;
+    }
+
+    public bool Remove(TKey key)
+    {
+        Entry[] entries = _entries;
+        int bucketIndex = key.GetHashCode() & (_buckets.Length - 1);
+        int entryIndex = _buckets[bucketIndex] - 1;
+
+        int lastIndex = -1;
+        while (entryIndex != -1)
         {
-            Entry[] entries = _entries;
-            for (int i = _buckets[key.GetHashCode() & (_buckets.Length - 1)] - 1;
-                (uint)i < (uint)entries.Length; i = entries[i].next)
+            Entry candidate = entries[entryIndex];
+            if (candidate.key.Equals(key))
             {
-                if (key.Equals(entries[i].key))
-                {
-                    value = entries[i].value;
-                    return true;
+                if (lastIndex != -1)
+                {   // Fixup preceding element in chain to point to next (if any)
+                    entries[lastIndex].next = candidate.next;
+                }
+                else
+                {   // Fixup bucket to new head (if any)
+                    _buckets[bucketIndex] = candidate.next + 1;
                 }
-            }
 
-            value = default;
-            return false;
-        }
+                entries[entryIndex] = default;
 
-        public bool Remove(TKey key)
-        {
-            Entry[] entries = _entries;
-            int bucketIndex = key.GetHashCode() & (_buckets.Length - 1);
-            int entryIndex = _buckets[bucketIndex] - 1;
+                entries[entryIndex].next = -3 - _freeList; // New head of free list
+                _freeList = entryIndex;
 
-            int lastIndex = -1;
-            while (entryIndex != -1)
-            {
-                Entry candidate = entries[entryIndex];
-                if (candidate.key.Equals(key))
-                {
-                    if (lastIndex != -1)
-                    {   // Fixup preceding element in chain to point to next (if any)
-                        entries[lastIndex].next = candidate.next;
-                    }
-                    else
-                    {   // Fixup bucket to new head (if any)
-                        _buckets[bucketIndex] = candidate.next + 1;
-                    }
-
-                    entries[entryIndex] = default;
-
-                    entries[entryIndex].next = -3 - _freeList; // New head of free list
-                    _freeList = entryIndex;
-
-                    _count--;
-                    return true;
-                }
-                lastIndex = entryIndex;
-                entryIndex = candidate.next;
+                _count--;
+                return true;
             }
-
-            return false;
+            lastIndex = entryIndex;
+            entryIndex = candidate.next;
         }
 
-       // Not safe for concurrent _reads_ (at least, if either of them add)
-        // For concurrent reads, prefer TryGetValue(key, out value)
-        /// <summary>
-        /// Gets the value for the specified key, or, if the key is not present,
-        /// adds an entry and returns the value by ref. This makes it possible to
-        /// add or update a value in a single look up operation.
-        /// </summary>
-        /// <param name="key">Key to look for</param>
-        /// <returns>Reference to the new or existing value</returns>
-        public ref TValue GetOrAddValueRef(TKey key)
-        {
-            Entry[] entries = _entries;
-            int bucketIndex = key.GetHashCode() & (_buckets.Length - 1);
-            for (int i = _buckets[bucketIndex] - 1;
-                    (uint)i < (uint)entries.Length; i = entries[i].next)
-            {
-                if (key.Equals(entries[i].key))
-                    return ref entries[i].value;
-            }
+        return false;
+    }
 
-            return ref AddKey(key, bucketIndex);
+    // Not safe for concurrent _reads_ (at least, if either of them add)
+    // For concurrent reads, prefer TryGetValue(key, out value)
+    /// <summary>
+    /// Gets the value for the specified key, or, if the key is not present,
+    /// adds an entry and returns the value by ref. This makes it possible to
+    /// add or update a value in a single look up operation.
+    /// </summary>
+    /// <param name="key">Key to look for</param>
+    /// <returns>Reference to the new or existing value</returns>
+    public ref TValue GetOrAddValueRef(TKey key)
+    {
+        Entry[] entries = _entries;
+        int bucketIndex = key.GetHashCode() & (_buckets.Length - 1);
+        for (int i = _buckets[bucketIndex] - 1;
+             (uint)i < (uint)entries.Length; i = entries[i].next)
+        {
+            if (key.Equals(entries[i].key))
+                return ref entries[i].value;
         }
 
-        public ref TValue this[TKey key]
+        return ref AddKey(key, bucketIndex);
+    }
+
+    public ref TValue this[TKey key]
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        get => ref GetOrAddValueRef(key);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private ref TValue AddKey(TKey key, int bucketIndex)
+    {
+        Entry[] entries = _entries;
+        int entryIndex;
+        if (_freeList != -1)
         {
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get => ref GetOrAddValueRef(key);
+            entryIndex = _freeList;
+            _freeList = -3 - entries[_freeList].next;
         }
-
-        [MethodImpl(MethodImplOptions.NoInlining)]
-        private ref TValue AddKey(TKey key, int bucketIndex)
+        else
         {
-            Entry[] entries = _entries;
-            int entryIndex;
-            if (_freeList != -1)
+            if (_count == entries.Length || entries.Length == 1)
             {
-                entryIndex = _freeList;
-                _freeList = -3 - entries[_freeList].next;
+                entries = Resize();
+                bucketIndex = key.GetHashCode() & (_buckets.Length - 1);
+                // entry indexes were not changed by Resize
             }
-            else
-            {
-                if (_count == entries.Length || entries.Length == 1)
-                {
-                    entries = Resize();
-                    bucketIndex = key.GetHashCode() & (_buckets.Length - 1);
-                    // entry indexes were not changed by Resize
-                }
-                entryIndex = _count;
-            }
-
-            entries[entryIndex].key = key;
-            entries[entryIndex].next = _buckets[bucketIndex] - 1;
-            _buckets[bucketIndex] = entryIndex + 1;
-            _count++;
-            return ref entries[entryIndex].value;
+            entryIndex = _count;
         }
 
-        private Entry[] Resize()
-        {
-            Debug.Assert(_entries.Length == _count || _entries.Length == 1); // We only copy _count, so if it's longer we will miss some
-            int count = _count;
-            int newSize = _entries.Length * 2;
-            if ((uint)newSize > (uint)int.MaxValue) // uint cast handles overflow
-                throw new InvalidOperationException("Capacity Overflow");
-
-            var entries = new Entry[newSize];
-            Array.Copy(_entries, 0, entries, 0, count);
+        entries[entryIndex].key = key;
+        entries[entryIndex].next = _buckets[bucketIndex] - 1;
+        _buckets[bucketIndex] = entryIndex + 1;
+        _count++;
+        return ref entries[entryIndex].value;
+    }
 
-            var newBuckets = new int[entries.Length];
-            while (count-- > 0)
-            {
-                int bucketIndex = entries[count].key.GetHashCode() & (newBuckets.Length - 1);
-                entries[count].next = newBuckets[bucketIndex] - 1;
-                newBuckets[bucketIndex] = count + 1;
-            }
+    private Entry[] Resize()
+    {
+        Debug.Assert(_entries.Length == _count || _entries.Length == 1); // We only copy _count, so if it's longer we will miss some
+        int count = _count;
+        int newSize = _entries.Length * 2;
+        if ((uint)newSize > (uint)int.MaxValue) // uint cast handles overflow
+            throw new InvalidOperationException("Capacity Overflow");
 
-            _buckets = newBuckets;
-            _entries = entries;
+        var entries = new Entry[newSize];
+        Array.Copy(_entries, 0, entries, 0, count);
 
-            return entries;
+        var newBuckets = new int[entries.Length];
+        while (count-- > 0)
+        {
+            int bucketIndex = entries[count].key.GetHashCode() & (newBuckets.Length - 1);
+            entries[count].next = newBuckets[bucketIndex] - 1;
+            newBuckets[bucketIndex] = count + 1;
         }
 
-        /// <summary>
-        /// Gets an enumerator over the dictionary
-        /// </summary>
-        public Enumerator GetEnumerator() => new Enumerator(this); // avoid boxing
+        _buckets = newBuckets;
+        _entries = entries;
+
+        return entries;
+    }
+
+    /// <summary>
+    /// Gets an enumerator over the dictionary
+    /// </summary>
+    public Enumerator GetEnumerator() => new Enumerator(this); // avoid boxing
+
+    /// <summary>
+    /// Gets an enumerator over the dictionary
+    /// </summary>
+    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() =>
+        new Enumerator(this);
 
-        /// <summary>
-        /// Gets an enumerator over the dictionary
-        /// </summary>
-        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() =>
-            new Enumerator(this);
+    /// <summary>
+    /// Gets an enumerator over the dictionary
+    /// </summary>
+    IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);
 
-        /// <summary>
-        /// Gets an enumerator over the dictionary
-        /// </summary>
-        IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);
+    public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
+    {
+        private readonly DictionarySlim<TKey, TValue> _dictionary;
+        private int _index;
+        private int _count;
+        private KeyValuePair<TKey, TValue> _current;
 
-        public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
+        internal Enumerator(DictionarySlim<TKey, TValue> dictionary)
         {
-            private readonly DictionarySlim<TKey, TValue> _dictionary;
-            private int _index;
-            private int _count;
-            private KeyValuePair<TKey, TValue> _current;
+            _dictionary = dictionary;
+            _index = 0;
+            _count = _dictionary._count;
+            _current = default;
+        }
 
-            internal Enumerator(DictionarySlim<TKey, TValue> dictionary)
+        public bool MoveNext()
+        {
+            if (_count == 0)
             {
-                _dictionary = dictionary;
-                _index = 0;
-                _count = _dictionary._count;
                 _current = default;
+                return false;
             }
 
-            public bool MoveNext()
-            {
-                if (_count == 0)
-                {
-                    _current = default;
-                    return false;
-                }
+            _count--;
 
-                _count--;
+            while (_dictionary._entries[_index].next < -1)
+                _index++;
 
-                while (_dictionary._entries[_index].next < -1)
-                    _index++;
+            _current = new KeyValuePair<TKey, TValue>(
+                _dictionary._entries[_index].key,
+                _dictionary._entries[_index++].value);
+            return true;
+        }
 
-                _current = new KeyValuePair<TKey, TValue>(
-                    _dictionary._entries[_index].key,
-                    _dictionary._entries[_index++].value);
-                return true;
-            }
+        public KeyValuePair<TKey, TValue> Current => _current;
 
-            public KeyValuePair<TKey, TValue> Current => _current;
+        object IEnumerator.Current => _current;
 
-            object IEnumerator.Current => _current;
+        void IEnumerator.Reset()
+        {
+            _index = 0;
+            _count = _dictionary._count;
+            _current = default;
+        }
 
-            void IEnumerator.Reset()
-            {
-                _index = 0;
-                _count = _dictionary._count;
-                _current = default;
-            }
+        public void Dispose() { }
+    }
 
-            public void Dispose() { }
-        }
+    internal static class HashHelpers
+    {
+        internal static readonly int[] SizeOneIntArray = new int[1];
 
-        internal static class HashHelpers
+        internal static int PowerOf2(int v)
         {
-            internal static readonly int[] SizeOneIntArray = new int[1];
-
-            internal static int PowerOf2(int v)
-            {
-                if ((v & (v - 1)) == 0) return v;
-                int i = 2;
-                while (i < v) i <<= 1;
-                return i;
-            }
+            if ((v & (v - 1)) == 0) return v;
+            int i = 2;
+            while (i < v) i <<= 1;
+            return i;
         }
     }
 }

+ 165 - 166
Jint/Collections/HybridDictionary.cs

@@ -3,249 +3,248 @@
 using System.Collections;
 using System.Runtime.CompilerServices;
 
-namespace Jint.Collections
+namespace Jint.Collections;
+
+internal class HybridDictionary<TValue> : IEnumerable<KeyValuePair<Key, TValue>>
 {
-    internal class HybridDictionary<TValue> : IEnumerable<KeyValuePair<Key, TValue>>
-    {
-        private const int CutoverPoint = 9;
-        private const int InitialDictionarySize = 13;
-        private const int FixedSizeCutoverPoint = 6;
+    private const int CutoverPoint = 9;
+    private const int InitialDictionarySize = 13;
+    private const int FixedSizeCutoverPoint = 6;
 
-        private readonly bool _checkExistingKeys;
-        private ListDictionary<TValue> _list;
-        internal StringDictionarySlim<TValue> _dictionary;
+    private readonly bool _checkExistingKeys;
+    private ListDictionary<TValue> _list;
+    internal StringDictionarySlim<TValue> _dictionary;
 
-        public HybridDictionary() : this(0, checkExistingKeys: true)
-        {
-        }
+    public HybridDictionary() : this(0, checkExistingKeys: true)
+    {
+    }
 
-        public HybridDictionary(int initialSize, bool checkExistingKeys)
+    public HybridDictionary(int initialSize, bool checkExistingKeys)
+    {
+        _checkExistingKeys = checkExistingKeys;
+        if (initialSize >= FixedSizeCutoverPoint)
         {
-            _checkExistingKeys = checkExistingKeys;
-            if (initialSize >= FixedSizeCutoverPoint)
-            {
-                _dictionary = new StringDictionarySlim<TValue>(initialSize);
-            }
+            _dictionary = new StringDictionarySlim<TValue>(initialSize);
         }
+    }
+
+    protected HybridDictionary(StringDictionarySlim<TValue> dictionary)
+    {
+        _checkExistingKeys = true;
+        _dictionary = dictionary;
+    }
 
-        protected HybridDictionary(StringDictionarySlim<TValue> dictionary)
+    public TValue this[Key key]
+    {
+        get
         {
-            _checkExistingKeys = true;
-            _dictionary = dictionary;
+            TryGetValue(key, out var value);
+            return value;
         }
-
-        public TValue this[Key key]
+        set
         {
-            get
+            if (_dictionary != null)
             {
-                TryGetValue(key, out var value);
-                return value;
+                _dictionary[key] = value;
             }
-            set
+            else if (_list != null)
             {
-                if (_dictionary != null)
+                if (_list.Count >= CutoverPoint - 1)
                 {
-                    _dictionary[key] = value;
-                }
-                else if (_list != null)
-                {
-                    if (_list.Count >= CutoverPoint - 1)
-                    {
-                        SwitchToDictionary(key, value, tryAdd: false);
-                    }
-                    else
-                    {
-                        _list[key] = value;
-                    }
+                    SwitchToDictionary(key, value, tryAdd: false);
                 }
                 else
                 {
-                    _list = new ListDictionary<TValue>(key, value, _checkExistingKeys);
+                    _list[key] = value;
                 }
             }
-        }
-
-        public bool TryGetValue(Key key, out TValue value)
-        {
-            if (_dictionary != null)
-            {
-                return _dictionary.TryGetValue(key, out value);
-            }
-
-            if (_list != null)
+            else
             {
-                return _list.TryGetValue(key, out value);
+                _list = new ListDictionary<TValue>(key, value, _checkExistingKeys);
             }
+        }
+    }
 
-            value = default;
-            return false;
+    public bool TryGetValue(Key key, out TValue value)
+    {
+        if (_dictionary != null)
+        {
+            return _dictionary.TryGetValue(key, out value);
         }
 
-        public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
+        if (_list != null)
         {
-            if (_dictionary != null)
-            {
-                _dictionary.SetOrUpdateValue(key, updater, state);
-            }
-            else if (_list != null)
-            {
-                _list.SetOrUpdateValue(key, updater, state);
-            }
-            else
-            {
-                _list = new ListDictionary<TValue>(key, updater(default, state), _checkExistingKeys);
-            }
+            return _list.TryGetValue(key, out value);
         }
 
-        private bool SwitchToDictionary(Key key, TValue value, bool tryAdd)
+        value = default;
+        return false;
+    }
+
+    public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
+    {
+        if (_dictionary != null)
         {
-            var dictionary = new StringDictionarySlim<TValue>(InitialDictionarySize);
-            foreach (var pair in _list)
-            {
-                dictionary[pair.Key] = pair.Value;
-            }
+            _dictionary.SetOrUpdateValue(key, updater, state);
+        }
+        else if (_list != null)
+        {
+            _list.SetOrUpdateValue(key, updater, state);
+        }
+        else
+        {
+            _list = new ListDictionary<TValue>(key, updater(default, state), _checkExistingKeys);
+        }
+    }
 
-            bool result;
-            if (tryAdd)
-            {
-                result = dictionary.TryAdd(key, value);
-            }
-            else
-            {
-                dictionary[key] = value;
-                result = true;
-            }
-            _dictionary = dictionary;
-            _list = null;
-            return result;
+    private bool SwitchToDictionary(Key key, TValue value, bool tryAdd)
+    {
+        var dictionary = new StringDictionarySlim<TValue>(InitialDictionarySize);
+        foreach (var pair in _list)
+        {
+            dictionary[pair.Key] = pair.Value;
         }
 
-        public int Count
+        bool result;
+        if (tryAdd)
+        {
+            result = dictionary.TryAdd(key, value);
+        }
+        else
         {
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get => _dictionary?.Count ?? _list?.Count ?? 0;
+            dictionary[key] = value;
+            result = true;
         }
+        _dictionary = dictionary;
+        _list = null;
+        return result;
+    }
+
+    public int Count
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        get => _dictionary?.Count ?? _list?.Count ?? 0;
+    }
 
-        public bool TryAdd(Key key, TValue value)
+    public bool TryAdd(Key key, TValue value)
+    {
+        if (_dictionary != null)
         {
-            if (_dictionary != null)
+            return _dictionary.TryAdd(key, value);
+        }
+        else
+        {
+            _list ??= new ListDictionary<TValue>(key, value, _checkExistingKeys);
+
+            if (_list.Count + 1 >= CutoverPoint)
             {
-                return _dictionary.TryAdd(key, value);
+                return SwitchToDictionary(key, value, tryAdd: true);
             }
             else
             {
-                _list ??= new ListDictionary<TValue>(key, value, _checkExistingKeys);
-
-                if (_list.Count + 1 >= CutoverPoint)
-                {
-                    return SwitchToDictionary(key, value, tryAdd: true);
-                }
-                else
-                {
-                    return _list.Add(key, value, tryAdd: true);
-                }
+                return _list.Add(key, value, tryAdd: true);
             }
         }
+    }
 
-        public void Add(Key key, TValue value)
+    public void Add(Key key, TValue value)
+    {
+        if (_dictionary != null)
         {
-            if (_dictionary != null)
+            _dictionary.GetOrAddValueRef(key) = value;
+        }
+        else
+        {
+            if (_list == null)
             {
-                _dictionary.GetOrAddValueRef(key) = value;
+                _list = new ListDictionary<TValue>(key, value, _checkExistingKeys);
             }
             else
             {
-                if (_list == null)
+                if (_list.Count + 1 >= CutoverPoint)
                 {
-                    _list = new ListDictionary<TValue>(key, value, _checkExistingKeys);
+                    SwitchToDictionary(key, value, tryAdd: false);
                 }
                 else
                 {
-                    if (_list.Count + 1 >= CutoverPoint)
-                    {
-                        SwitchToDictionary(key, value, tryAdd: false);
-                    }
-                    else
-                    {
-                        _list.Add(key, value);
-                    }
+                    _list.Add(key, value);
                 }
             }
         }
+    }
+
+    public void Clear()
+    {
+        _dictionary?.Clear();
+        _list?.Clear();
+    }
 
-        public void Clear()
+    public bool ContainsKey(Key key)
+    {
+        if (_dictionary != null)
         {
-            _dictionary?.Clear();
-            _list?.Clear();
+            return _dictionary.ContainsKey(key);
         }
 
-        public bool ContainsKey(Key key)
+        if (_list != null)
         {
-            if (_dictionary != null)
-            {
-                return _dictionary.ContainsKey(key);
-            }
+            return _list.ContainsKey(key);
+        }
 
-            if (_list != null)
-            {
-                return _list.ContainsKey(key);
-            }
+        return false;
+    }
 
-            return false;
+    IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator()
+    {
+        if (_dictionary != null)
+        {
+            return _dictionary.GetEnumerator();
         }
 
-        IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator()
+        if (_list != null)
         {
-            if (_dictionary != null)
-            {
-                return _dictionary.GetEnumerator();
-            }
+            return _list.GetEnumerator();
+        }
 
-            if (_list != null)
-            {
-                return _list.GetEnumerator();
-            }
+        return System.Linq.Enumerable.Empty<KeyValuePair<Key, TValue>>().GetEnumerator();
 
-            return System.Linq.Enumerable.Empty<KeyValuePair<Key, TValue>>().GetEnumerator();
+    }
 
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        if (_dictionary != null)
+        {
+            return _dictionary.GetEnumerator();
         }
 
-        IEnumerator IEnumerable.GetEnumerator()
+        if (_list != null)
         {
-            if (_dictionary != null)
-            {
-                return _dictionary.GetEnumerator();
-            }
-
-            if (_list != null)
-            {
-                return _list.GetEnumerator();
-            }
-
-            return System.Linq.Enumerable.Empty<KeyValuePair<Key, TValue>>().GetEnumerator();
+            return _list.GetEnumerator();
         }
 
-        public bool Remove(Key key)
-        {
-            if (_dictionary != null)
-            {
-                return _dictionary.Remove(key);
-            }
+        return System.Linq.Enumerable.Empty<KeyValuePair<Key, TValue>>().GetEnumerator();
+    }
 
-            return _list != null && _list.Remove(key);
+    public bool Remove(Key key)
+    {
+        if (_dictionary != null)
+        {
+            return _dictionary.Remove(key);
         }
 
-        /// <summary>
-        /// Optimization when no need to check for existing items.
-        /// </summary>
-        public bool CheckExistingKeys
+        return _list != null && _list.Remove(key);
+    }
+
+    /// <summary>
+    /// Optimization when no need to check for existing items.
+    /// </summary>
+    public bool CheckExistingKeys
+    {
+        set
         {
-            set
+            if (_list != null)
             {
-                if (_list != null)
-                {
-                    _list.CheckExistingKeys = value;
-                }
+                _list.CheckExistingKeys = value;
             }
         }
     }

+ 186 - 187
Jint/Collections/ListDictionary.cs

@@ -4,264 +4,263 @@ using System.Collections;
 using System.Runtime.CompilerServices;
 using Jint.Runtime;
 
-namespace Jint.Collections
-{
-    internal sealed class ListDictionary<TValue> : IEnumerable<KeyValuePair<Key, TValue>>
-    {
-        private DictionaryNode _head;
-        private int _count;
-        private bool _checkExistingKeys;
+namespace Jint.Collections;
 
-        public ListDictionary(Key key, TValue value, bool checkExistingKeys)
-        {
-            _checkExistingKeys = checkExistingKeys;
-            _head = new DictionaryNode
-            {
-                Key = key,
-                Value = value
-            };
-            _count = 1;
-        }
+internal sealed class ListDictionary<TValue> : IEnumerable<KeyValuePair<Key, TValue>>
+{
+    private DictionaryNode _head;
+    private int _count;
+    private bool _checkExistingKeys;
 
-        public TValue this[Key key]
+    public ListDictionary(Key key, TValue value, bool checkExistingKeys)
+    {
+        _checkExistingKeys = checkExistingKeys;
+        _head = new DictionaryNode
         {
-            get
-            {
-                TryGetValue(key, out var value);
-                return value;
-            }
-            set
-            {
-                DictionaryNode last = null;
-                DictionaryNode node;
-                var checkExistingKeys = _checkExistingKeys;
-                for (node = _head; node != null; node = node.Next)
-                {
-                    var oldKey = node.Key;
-                    if (checkExistingKeys && oldKey == key)
-                    {
-                        break;
-                    }
-
-                    last = node;
-                }
-
-                if (node != null)
-                {
-                    // Found it
-                    node.Value = value;
-                    return;
-                }
-
-                AddNode(key, value, last);
-            }
-        }
+            Key = key,
+            Value = value
+        };
+        _count = 1;
+    }
 
-        public bool TryGetValue(Key key, out TValue value)
+    public TValue this[Key key]
+    {
+        get
         {
-            var node = _head;
-            while (node != null)
-            {
-                if (node.Key == key)
-                {
-                    value = node.Value;
-                    return true;
-                }
-
-                node = node.Next;
-            }
-
-            value = default;
-            return false;
+            TryGetValue(key, out var value);
+            return value;
         }
-
-        public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
+        set
         {
             DictionaryNode last = null;
             DictionaryNode node;
+            var checkExistingKeys = _checkExistingKeys;
             for (node = _head; node != null; node = node.Next)
             {
-                if (node.Key == key)
+                var oldKey = node.Key;
+                if (checkExistingKeys && oldKey == key)
                 {
-                    node.Value = updater(node.Value, state);
-                    return;
+                    break;
                 }
 
                 last = node;
             }
 
-            AddNode(key, updater(default, state), last);
-        }
+            if (node != null)
+            {
+                // Found it
+                node.Value = value;
+                return;
+            }
 
-        public int Count
-        {
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get => _count;
+            AddNode(key, value, last);
         }
+    }
 
-        public bool Add(Key key, TValue value, bool tryAdd = false)
+    public bool TryGetValue(Key key, out TValue value)
+    {
+        var node = _head;
+        while (node != null)
         {
-            DictionaryNode last = null;
-            DictionaryNode node;
-            var checkExistingKeys = _checkExistingKeys;
-            for (node = _head; node != null; node = node.Next)
+            if (node.Key == key)
             {
-                var oldKey = node.Key;
-                if (checkExistingKeys && oldKey == key)
-                {
-                    if (tryAdd)
-                    {
-                        return false;
-                    }
-                    ExceptionHelper.ThrowArgumentException();
-                }
-
-                last = node;
+                value = node.Value;
+                return true;
             }
 
-            AddNode(key, value, last);
-            return true;
+            node = node.Next;
         }
 
-        private void AddNode(Key key, TValue value, DictionaryNode last)
+        value = default;
+        return false;
+    }
+
+    public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
+    {
+        DictionaryNode last = null;
+        DictionaryNode node;
+        for (node = _head; node != null; node = node.Next)
         {
-            var newNode = new DictionaryNode
+            if (node.Key == key)
             {
-                Key = key,
-                Value = value
-            };
-            if (_head is null)
-            {
-                _head = newNode;
+                node.Value = updater(node.Value, state);
+                return;
             }
-            else
-            {
-                last.Next = newNode;
-            }
-            _count++;
-        }
 
-        public void Clear()
-        {
-            _count = 0;
-            _head = null;
+            last = node;
         }
 
-        public bool ContainsKey(Key key)
+        AddNode(key, updater(default, state), last);
+    }
+
+    public int Count
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        get => _count;
+    }
+
+    public bool Add(Key key, TValue value, bool tryAdd = false)
+    {
+        DictionaryNode last = null;
+        DictionaryNode node;
+        var checkExistingKeys = _checkExistingKeys;
+        for (node = _head; node != null; node = node.Next)
         {
-            for (var node = _head; node != null; node = node.Next)
+            var oldKey = node.Key;
+            if (checkExistingKeys && oldKey == key)
             {
-                var oldKey = node.Key;
-                if (oldKey == key)
+                if (tryAdd)
                 {
-                    return true;
+                    return false;
                 }
+                ExceptionHelper.ThrowArgumentException();
             }
 
-            return false;
+            last = node;
         }
 
-        internal bool CheckExistingKeys
-        {
-            set => _checkExistingKeys = value;
-        }
+        AddNode(key, value, last);
+        return true;
+    }
 
-        public NodeEnumerator GetEnumerator()
+    private void AddNode(Key key, TValue value, DictionaryNode last)
+    {
+        var newNode = new DictionaryNode
         {
-            return new NodeEnumerator(this);
-        }
-
-        IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator()
+            Key = key,
+            Value = value
+        };
+        if (_head is null)
         {
-            return new NodeEnumerator(this);
+            _head = newNode;
         }
-
-        IEnumerator IEnumerable.GetEnumerator()
+        else
         {
-            return new NodeEnumerator(this);
+            last.Next = newNode;
         }
+        _count++;
+    }
 
-        public bool Remove(Key key)
+    public void Clear()
+    {
+        _count = 0;
+        _head = null;
+    }
+
+    public bool ContainsKey(Key key)
+    {
+        for (var node = _head; node != null; node = node.Next)
         {
-            DictionaryNode last = null;
-            DictionaryNode node;
-            for (node = _head; node != null; node = node.Next)
+            var oldKey = node.Key;
+            if (oldKey == key)
             {
-                var oldKey = node.Key;
-                if (oldKey == key)
-                {
-                    break;
-                }
-
-                last = node;
+                return true;
             }
+        }
 
-            if (node == null)
-            {
-                return false;
-            }
+        return false;
+    }
 
-            if (node == _head)
-            {
-                _head = node.Next;
-            }
-            else
+    internal bool CheckExistingKeys
+    {
+        set => _checkExistingKeys = value;
+    }
+
+    public NodeEnumerator GetEnumerator()
+    {
+        return new NodeEnumerator(this);
+    }
+
+    IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator()
+    {
+        return new NodeEnumerator(this);
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return new NodeEnumerator(this);
+    }
+
+    public bool Remove(Key key)
+    {
+        DictionaryNode last = null;
+        DictionaryNode node;
+        for (node = _head; node != null; node = node.Next)
+        {
+            var oldKey = node.Key;
+            if (oldKey == key)
             {
-                last.Next = node.Next;
+                break;
             }
 
-            _count--;
-            return true;
+            last = node;
         }
 
-        internal struct NodeEnumerator : IEnumerator<KeyValuePair<Key, TValue>>
+        if (node == null)
         {
-            private readonly ListDictionary<TValue> _list;
-            private DictionaryNode _current;
-            private bool _start;
+            return false;
+        }
 
-            public NodeEnumerator(ListDictionary<TValue> list)
-            {
-                _list = list;
-                _start = true;
-                _current = null;
-            }
+        if (node == _head)
+        {
+            _head = node.Next;
+        }
+        else
+        {
+            last.Next = node.Next;
+        }
 
-            public KeyValuePair<Key, TValue> Current => new KeyValuePair<Key, TValue>(_current.Key, _current.Value);
+        _count--;
+        return true;
+    }
 
-            public bool MoveNext()
-            {
-                if (_start)
-                {
-                    _current = _list._head;
-                    _start = false;
-                }
-                else if (_current != null)
-                {
-                    _current = _current.Next;
-                }
+    internal struct NodeEnumerator : IEnumerator<KeyValuePair<Key, TValue>>
+    {
+        private readonly ListDictionary<TValue> _list;
+        private DictionaryNode _current;
+        private bool _start;
 
-                return _current != null;
-            }
+        public NodeEnumerator(ListDictionary<TValue> list)
+        {
+            _list = list;
+            _start = true;
+            _current = null;
+        }
 
-            void IEnumerator.Reset()
+        public KeyValuePair<Key, TValue> Current => new KeyValuePair<Key, TValue>(_current.Key, _current.Value);
+
+        public bool MoveNext()
+        {
+            if (_start)
             {
-                _start = true;
-                _current = null;
+                _current = _list._head;
+                _start = false;
             }
-
-            public void Dispose()
+            else if (_current != null)
             {
+                _current = _current.Next;
             }
 
-            object IEnumerator.Current => _current;
+            return _current != null;
+        }
+
+        void IEnumerator.Reset()
+        {
+            _start = true;
+            _current = null;
         }
 
-        internal sealed class DictionaryNode
+        public void Dispose()
         {
-            public Key Key;
-            public TValue Value;
-            public DictionaryNode Next;
         }
+
+        object IEnumerator.Current => _current;
+    }
+
+    internal sealed class DictionaryNode
+    {
+        public Key Key;
+        public TValue Value;
+        public DictionaryNode Next;
     }
 }

+ 24 - 25
Jint/Collections/ObjectTraverseStack.cs

@@ -1,39 +1,38 @@
 using Jint.Native;
 using Jint.Runtime;
 
-namespace Jint.Collections
+namespace Jint.Collections;
+
+/// <summary>
+/// Helps traversing objects and checks for cyclic references.
+/// </summary>
+internal sealed class ObjectTraverseStack
 {
-    /// <summary>
-    /// Helps traversing objects and checks for cyclic references.
-    /// </summary>
-    internal sealed class ObjectTraverseStack
+    private readonly Engine _engine;
+    private readonly Stack<object> _stack = new();
+
+    public ObjectTraverseStack(Engine engine)
     {
-        private readonly Engine _engine;
-        private readonly Stack<object> _stack = new();
+        _engine = engine;
+    }
 
-        public ObjectTraverseStack(Engine engine)
+    public void Enter(JsValue value)
+    {
+        if (value is null)
         {
-            _engine = engine;
+            ExceptionHelper.ThrowArgumentNullException(nameof(value));
         }
 
-        public void Enter(JsValue value)
+        if (_stack.Contains(value))
         {
-            if (value is null)
-            {
-                ExceptionHelper.ThrowArgumentNullException(nameof(value));
-            }
-
-            if (_stack.Contains(value))
-            {
-                ExceptionHelper.ThrowTypeError(_engine.Realm, "Cyclic reference detected.");
-            }
-
-            _stack.Push(value);
+            ExceptionHelper.ThrowTypeError(_engine.Realm, "Cyclic reference detected.");
         }
 
-        public void Exit()
-        {
-            _stack.Pop();
-        }
+        _stack.Push(value);
+    }
+
+    public void Exit()
+    {
+        _stack.Pop();
     }
 }

+ 10 - 11
Jint/Collections/PropertyDictionary.cs

@@ -1,19 +1,18 @@
 using Jint.Runtime.Descriptors;
 
-namespace Jint.Collections
+namespace Jint.Collections;
+
+internal sealed class PropertyDictionary : HybridDictionary<PropertyDescriptor>
 {
-    internal sealed class PropertyDictionary : HybridDictionary<PropertyDescriptor>
+    public PropertyDictionary()
     {
-        public PropertyDictionary()
-        {
-        }
+    }
 
-        public PropertyDictionary(int capacity, bool checkExistingKeys) : base(capacity, checkExistingKeys)
-        {
-        }
+    public PropertyDictionary(int capacity, bool checkExistingKeys) : base(capacity, checkExistingKeys)
+    {
+    }
 
-        public PropertyDictionary(StringDictionarySlim<PropertyDescriptor> properties) : base(properties)
-        {
-        }
+    public PropertyDictionary(StringDictionarySlim<PropertyDescriptor> properties) : base(properties)
+    {
     }
 }

+ 134 - 135
Jint/Collections/RefStack.cs

@@ -3,194 +3,193 @@ using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using Jint.Runtime;
 
-namespace Jint.Collections
+namespace Jint.Collections;
+
+/// <summary>
+/// Stack for struct types.
+/// </summary>
+internal sealed class RefStack<T> : IEnumerable<T> where T : struct
 {
-    /// <summary>
-    /// Stack for struct types.
-    /// </summary>
-    internal sealed class RefStack<T> : IEnumerable<T> where T : struct
+    internal T[] _array;
+    internal int _size;
+
+    private const int DefaultCapacity = 2;
+
+    public RefStack(int capacity = DefaultCapacity)
     {
-        internal T[] _array;
-        internal int _size;
+        _array = new T[capacity];
+        _size = 0;
+    }
 
-        private const int DefaultCapacity = 2;
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public ref readonly T Peek()
+    {
+        return ref _array[_size - 1];
+    }
 
-        public RefStack(int capacity = DefaultCapacity)
-        {
-            _array = new T[capacity];
-            _size = 0;
-        }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public ref readonly T Peek(int fromTop)
+    {
+        var index = _size - 1 - fromTop;
+        return ref _array[index];
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public ref readonly T Peek()
-        {
-            return ref _array[_size - 1];
-        }
+    public T this[int index] => _array[index];
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public ref readonly T Peek(int fromTop)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool TryPeek([NotNullWhen(true)] out T item)
+    {
+        if (_size > 0)
         {
-            var index = _size - 1 - fromTop;
-            return ref _array[index];
+            item = _array[_size - 1];
+            return true;
         }
 
-        public T this[int index] => _array[index];
+        item = default;
+        return false;
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool TryPeek([NotNullWhen(true)] out T item)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public ref readonly T Pop()
+    {
+        if (_size == 0)
         {
-            if (_size > 0)
-            {
-                item = _array[_size - 1];
-                return true;
-            }
-
-            item = default;
-            return false;
+            ExceptionHelper.ThrowInvalidOperationException("stack is empty");
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public ref readonly T Pop()
-        {
-            if (_size == 0)
-            {
-                ExceptionHelper.ThrowInvalidOperationException("stack is empty");
-            }
+        _size--;
+        return ref _array[_size];
+    }
 
-            _size--;
-            return ref _array[_size];
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Push(in T item)
+    {
+        if (_size == _array.Length)
+        {
+            EnsureCapacity(_size + 1);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public void Push(in T item)
+        _array[_size++] = item;
+    }
+
+    private void EnsureCapacity(int min)
+    {
+        var array = _array;
+        if (array.Length < min)
         {
-            if (_size == _array.Length)
+            var newCapacity = array.Length == 0
+                ? DefaultCapacity
+                : array.Length * 2;
+
+            if (newCapacity < min)
             {
-                EnsureCapacity(_size + 1);
+                newCapacity = min;
             }
 
-            _array[_size++] = item;
+            Resize(newCapacity);
         }
+    }
 
-        private void EnsureCapacity(int min)
+    private void Resize(int value)
+    {
+        if (value != _array.Length)
         {
-            var array = _array;
-            if (array.Length < min)
+            if (value > 0)
             {
-                var newCapacity = array.Length == 0
-                    ? DefaultCapacity
-                    : array.Length * 2;
-
-                if (newCapacity < min)
+                var newItems = new T[value];
+                if (_size > 0)
                 {
-                    newCapacity = min;
+                    Array.Copy(_array, 0, newItems, 0, _size);
                 }
 
-                Resize(newCapacity);
+                _array = newItems;
             }
-        }
-
-        private void Resize(int value)
-        {
-            if (value != _array.Length)
+            else
             {
-                if (value > 0)
-                {
-                    var newItems = new T[value];
-                    if (_size > 0)
-                    {
-                        Array.Copy(_array, 0, newItems, 0, _size);
-                    }
-
-                    _array = newItems;
-                }
-                else
-                {
-                    _array = Array.Empty<T>();
-                }
+                _array = Array.Empty<T>();
             }
         }
+    }
 
-        public void Clear()
-        {
-            _size = 0;
-        }
+    public void Clear()
+    {
+        _size = 0;
+    }
 
-        public Enumerator GetEnumerator()
-        {
-            return new Enumerator(this);
-        }
+    public Enumerator GetEnumerator()
+    {
+        return new Enumerator(this);
+    }
 
-        IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    internal struct Enumerator : IEnumerator<T>
+    {
+        private readonly RefStack<T> _stack;
+        private int _index;
+        private T? _currentElement;
+
+        internal Enumerator(RefStack<T> stack)
         {
-            return GetEnumerator();
+            _stack = stack;
+            _index = -2;
+            _currentElement = default;
         }
 
-        IEnumerator IEnumerable.GetEnumerator()
+        public void Dispose()
         {
-            return GetEnumerator();
+            _index = -1;
         }
 
-        internal struct Enumerator : IEnumerator<T>
+        public bool MoveNext()
         {
-            private readonly RefStack<T> _stack;
-            private int _index;
-            private T? _currentElement;
-
-            internal Enumerator(RefStack<T> stack)
+            bool returnValue;
+            if (_index == -2)
             {
-                _stack = stack;
-                _index = -2;
-                _currentElement = default;
-            }
-
-            public void Dispose()
-            {
-                _index = -1;
-            }
-
-            public bool MoveNext()
-            {
-                bool returnValue;
-                if (_index == -2)
-                {
-                    // First call to enumerator.
-                    _index = _stack._size - 1;
-                    returnValue = (_index >= 0);
-                    if (returnValue)
-                    {
-                        _currentElement = _stack._array[_index];
-                    }
-                    return returnValue;
-                }
-
-                if (_index == -1)
-                {
-                    // End of enumeration.
-                    return false;
-                }
-
-                returnValue = (--_index >= 0);
+                // First call to enumerator.
+                _index = _stack._size - 1;
+                returnValue = (_index >= 0);
                 if (returnValue)
                 {
                     _currentElement = _stack._array[_index];
                 }
-                else
-                {
-                    _currentElement = default;
-                }
                 return returnValue;
             }
 
-            public T Current => (T) _currentElement!;
-
-            object? IEnumerator.Current => Current;
+            if (_index == -1)
+            {
+                // End of enumeration.
+                return false;
+            }
 
-            void IEnumerator.Reset()
+            returnValue = (--_index >= 0);
+            if (returnValue)
+            {
+                _currentElement = _stack._array[_index];
+            }
+            else
             {
-                _index = -2;
                 _currentElement = default;
             }
+            return returnValue;
+        }
+
+        public T Current => (T) _currentElement!;
+
+        object? IEnumerator.Current => Current;
+
+        void IEnumerator.Reset()
+        {
+            _index = -2;
+            _currentElement = default;
         }
     }
 }

+ 266 - 267
Jint/Collections/StringDictionarySlim.cs

@@ -12,341 +12,340 @@ using System.Diagnostics;
 using System.Linq;
 using System.Runtime.CompilerServices;
 
-namespace Jint.Collections
+namespace Jint.Collections;
+
+/// <summary>
+/// DictionarySlim&lt;string, TValue> is similar to Dictionary&lt;TKey, TValue> but optimized in three ways:
+/// 1) It allows access to the value by ref replacing the common TryGetValue and Add pattern.
+/// 2) It does not store the hash code (assumes it is cheap to equate values).
+/// 3) It does not accept an equality comparer (assumes Object.GetHashCode() and Object.Equals() or overridden implementation are cheap and sufficient).
+/// </summary>
+[DebuggerTypeProxy(typeof(DictionarySlimDebugView<>))]
+[DebuggerDisplay("Count = {Count}")]
+internal sealed class StringDictionarySlim<TValue> : IReadOnlyCollection<KeyValuePair<Key, TValue>>
 {
-    /// <summary>
-    /// DictionarySlim&lt;string, TValue> is similar to Dictionary&lt;TKey, TValue> but optimized in three ways:
-    /// 1) It allows access to the value by ref replacing the common TryGetValue and Add pattern.
-    /// 2) It does not store the hash code (assumes it is cheap to equate values).
-    /// 3) It does not accept an equality comparer (assumes Object.GetHashCode() and Object.Equals() or overridden implementation are cheap and sufficient).
-    /// </summary>
-    [DebuggerTypeProxy(typeof(DictionarySlimDebugView<>))]
-    [DebuggerDisplay("Count = {Count}")]
-    internal sealed class StringDictionarySlim<TValue> : IReadOnlyCollection<KeyValuePair<Key, TValue>>
+    // We want to initialize without allocating arrays. We also want to avoid null checks.
+    // Array.Empty would give divide by zero in modulo operation. So we use static one element arrays.
+    // The first add will cause a resize replacing these with real arrays of three elements.
+    // Arrays are wrapped in a class to avoid being duplicated for each <TKey, TValue>
+    private static readonly Entry[] InitialEntries = new Entry[1];
+    private int _count;
+    // 0-based index into _entries of head of free chain: -1 means empty
+    private int _freeList = -1;
+    // 1-based index into _entries; 0 means empty
+    private int[] _buckets;
+    private Entry[] _entries;
+
+    [DebuggerDisplay("({key}, {value})->{next}")]
+    private struct Entry
     {
-        // We want to initialize without allocating arrays. We also want to avoid null checks.
-        // Array.Empty would give divide by zero in modulo operation. So we use static one element arrays.
-        // The first add will cause a resize replacing these with real arrays of three elements.
-        // Arrays are wrapped in a class to avoid being duplicated for each <TKey, TValue>
-        private static readonly Entry[] InitialEntries = new Entry[1];
-        private int _count;
-        // 0-based index into _entries of head of free chain: -1 means empty
-        private int _freeList = -1;
-        // 1-based index into _entries; 0 means empty
-        private int[] _buckets;
-        private Entry[] _entries;
-
-        [DebuggerDisplay("({key}, {value})->{next}")]
-        private struct Entry
-        {
-            public Key key;
-            public TValue value;
-            // 0-based index of next entry in chain: -1 means end of chain
-            // also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3,
-            // so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc.
-            public int next;
-        }
+        public Key key;
+        public TValue value;
+        // 0-based index of next entry in chain: -1 means end of chain
+        // also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3,
+        // so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc.
+        public int next;
+    }
 
-        public StringDictionarySlim()
-        {
-            _buckets = HashHelpers.SizeOneIntArray;
-            _entries = InitialEntries;
-        }
+    public StringDictionarySlim()
+    {
+        _buckets = HashHelpers.SizeOneIntArray;
+        _entries = InitialEntries;
+    }
 
-        public StringDictionarySlim(int capacity)
-        {
-            if (capacity < 2)
-                capacity = 2; // 1 would indicate the dummy array
-            capacity = HashHelpers.PowerOf2(capacity);
-            _buckets = new int[capacity];
-            _entries = new Entry[capacity];
-        }
+    public StringDictionarySlim(int capacity)
+    {
+        if (capacity < 2)
+            capacity = 2; // 1 would indicate the dummy array
+        capacity = HashHelpers.PowerOf2(capacity);
+        _buckets = new int[capacity];
+        _entries = new Entry[capacity];
+    }
 
-        public int Count
-        {
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get => _count;
-        }
+    public int Count
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        get => _count;
+    }
+
+    /// <summary>
+    /// Clears the dictionary. Note that this invalidates any active enumerators.
+    /// </summary>
+    public void Clear()
+    {
+        _count = 0;
+        _freeList = -1;
+        _buckets = HashHelpers.SizeOneIntArray;
+        _entries = InitialEntries;
+    }
 
-        /// <summary>
-        /// Clears the dictionary. Note that this invalidates any active enumerators.
-        /// </summary>
-        public void Clear()
+    public bool ContainsKey(Key key)
+    {
+        Entry[] entries = _entries;
+        for (int i = _buckets[key.HashCode & (_buckets.Length-1)] - 1;
+             (uint)i < (uint)entries.Length; i = entries[i].next)
         {
-            _count = 0;
-            _freeList = -1;
-            _buckets = HashHelpers.SizeOneIntArray;
-            _entries = InitialEntries;
+            if (key.Name == entries[i].key.Name)
+                return true;
         }
 
-        public bool ContainsKey(Key key)
+        return false;
+    }
+
+    public bool TryGetValue(Key key, out TValue value)
+    {
+        Entry[] entries = _entries;
+        for (int i = _buckets[key.HashCode & (_buckets.Length - 1)] - 1;
+             (uint)i < (uint)entries.Length; i = entries[i].next)
         {
-            Entry[] entries = _entries;
-            for (int i = _buckets[key.HashCode & (_buckets.Length-1)] - 1;
-                (uint)i < (uint)entries.Length; i = entries[i].next)
+            if (key.Name == entries[i].key.Name)
             {
-                if (key.Name == entries[i].key.Name)
-                    return true;
+                value = entries[i].value;
+                return true;
             }
-
-            return false;
         }
 
-        public bool TryGetValue(Key key, out TValue value)
+        value = default;
+        return false;
+    }
+
+    public bool Remove(Key key)
+    {
+        Entry[] entries = _entries;
+        int bucketIndex = key.HashCode & (_buckets.Length - 1);
+        int entryIndex = _buckets[bucketIndex] - 1;
+
+        int lastIndex = -1;
+        while (entryIndex != -1)
         {
-            Entry[] entries = _entries;
-            for (int i = _buckets[key.HashCode & (_buckets.Length - 1)] - 1;
-                (uint)i < (uint)entries.Length; i = entries[i].next)
+            Entry candidate = entries[entryIndex];
+            if (candidate.key == key)
             {
-                if (key.Name == entries[i].key.Name)
-                {
-                    value = entries[i].value;
-                    return true;
+                if (lastIndex != -1)
+                {   // Fixup preceding element in chain to point to next (if any)
+                    entries[lastIndex].next = candidate.next;
+                }
+                else
+                {   // Fixup bucket to new head (if any)
+                    _buckets[bucketIndex] = candidate.next + 1;
                 }
-            }
 
-            value = default;
-            return false;
-        }
+                entries[entryIndex] = default;
 
-        public bool Remove(Key key)
-        {
-            Entry[] entries = _entries;
-            int bucketIndex = key.HashCode & (_buckets.Length - 1);
-            int entryIndex = _buckets[bucketIndex] - 1;
+                entries[entryIndex].next = -3 - _freeList; // New head of free list
+                _freeList = entryIndex;
 
-            int lastIndex = -1;
-            while (entryIndex != -1)
-            {
-                Entry candidate = entries[entryIndex];
-                if (candidate.key == key)
-                {
-                    if (lastIndex != -1)
-                    {   // Fixup preceding element in chain to point to next (if any)
-                        entries[lastIndex].next = candidate.next;
-                    }
-                    else
-                    {   // Fixup bucket to new head (if any)
-                        _buckets[bucketIndex] = candidate.next + 1;
-                    }
-
-                    entries[entryIndex] = default;
-
-                    entries[entryIndex].next = -3 - _freeList; // New head of free list
-                    _freeList = entryIndex;
-
-                    _count--;
-                    return true;
-                }
-                lastIndex = entryIndex;
-                entryIndex = candidate.next;
+                _count--;
+                return true;
             }
-
-            return false;
+            lastIndex = entryIndex;
+            entryIndex = candidate.next;
         }
 
-        public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
+        return false;
+    }
+
+    public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
+    {
+        ref var currentValue = ref GetOrAddValueRef(key);
+        currentValue = updater(currentValue, state);
+    }
+
+    // Not safe for concurrent _reads_ (at least, if either of them add)
+    // For concurrent reads, prefer TryGetValue(key, out value)
+    /// <summary>
+    /// Gets the value for the specified key, or, if the key is not present,
+    /// adds an entry and returns the value by ref. This makes it possible to
+    /// add or update a value in a single look up operation.
+    /// </summary>
+    /// <param name="key">Key to look for</param>
+    /// <returns>Reference to the new or existing value</returns>
+    public ref TValue GetOrAddValueRef(Key key)
+    {
+        Entry[] entries = _entries;
+        int bucketIndex = key.HashCode & (_buckets.Length - 1);
+        for (int i = _buckets[bucketIndex] - 1;
+             (uint)i < (uint)entries.Length; i = entries[i].next)
         {
-            ref var currentValue = ref GetOrAddValueRef(key);
-            currentValue = updater(currentValue, state);
+            if (key.Name == entries[i].key.Name)
+                return ref entries[i].value;
         }
 
-        // Not safe for concurrent _reads_ (at least, if either of them add)
-        // For concurrent reads, prefer TryGetValue(key, out value)
-        /// <summary>
-        /// Gets the value for the specified key, or, if the key is not present,
-        /// adds an entry and returns the value by ref. This makes it possible to
-        /// add or update a value in a single look up operation.
-        /// </summary>
-        /// <param name="key">Key to look for</param>
-        /// <returns>Reference to the new or existing value</returns>
-        public ref TValue GetOrAddValueRef(Key key)
+        return ref AddKey(key, bucketIndex);
+    }
+
+    public bool TryAdd(Key key, TValue value)
+    {
+        Entry[] entries = _entries;
+        int bucketIndex = key.HashCode & (_buckets.Length - 1);
+        for (int i = _buckets[bucketIndex] - 1;
+             (uint)i < (uint)entries.Length; i = entries[i].next)
         {
-            Entry[] entries = _entries;
-            int bucketIndex = key.HashCode & (_buckets.Length - 1);
-            for (int i = _buckets[bucketIndex] - 1;
-                    (uint)i < (uint)entries.Length; i = entries[i].next)
+            if (key.Name == entries[i].key.Name)
             {
-                if (key.Name == entries[i].key.Name)
-                    return ref entries[i].value;
+                return false;
             }
-
-            return ref AddKey(key, bucketIndex);
         }
 
-        public bool TryAdd(Key key, TValue value)
-        {
-            Entry[] entries = _entries;
-            int bucketIndex = key.HashCode & (_buckets.Length - 1);
-            for (int i = _buckets[bucketIndex] - 1;
-                 (uint)i < (uint)entries.Length; i = entries[i].next)
-            {
-                if (key.Name == entries[i].key.Name)
-                {
-                    return false;
-                }
-            }
+        AddKey(key, bucketIndex) = value;
+        return true;
+    }
 
-            AddKey(key, bucketIndex) = value;
-            return true;
-        }
+    /// <summary>
+    /// Adds a new item and expects key to not to exist.
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void AddDangerous(in Key key, TValue value)
+    {
+        AddKey(key, key.HashCode & (_buckets.Length - 1)) = value;
+    }
 
-        /// <summary>
-        /// Adds a new item and expects key to not to exist.
-        /// </summary>
+    public ref TValue this[Key key]
+    {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public void AddDangerous(in Key key, TValue value)
-        {
-            AddKey(key, key.HashCode & (_buckets.Length - 1)) = value;
-        }
+        get => ref GetOrAddValueRef(key);
+    }
 
-        public ref TValue this[Key key]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private ref TValue AddKey(Key key, int bucketIndex)
+    {
+        Entry[] entries = _entries;
+        int entryIndex;
+        if (_freeList != -1)
         {
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get => ref GetOrAddValueRef(key);
+            entryIndex = _freeList;
+            _freeList = -3 - entries[_freeList].next;
         }
-
-        [MethodImpl(MethodImplOptions.NoInlining)]
-        private ref TValue AddKey(Key key, int bucketIndex)
+        else
         {
-            Entry[] entries = _entries;
-            int entryIndex;
-            if (_freeList != -1)
-            {
-                entryIndex = _freeList;
-                _freeList = -3 - entries[_freeList].next;
-            }
-            else
+            if (_count == entries.Length || entries.Length == 1)
             {
-                if (_count == entries.Length || entries.Length == 1)
-                {
-                    entries = Resize();
-                    bucketIndex = key.HashCode & (_buckets.Length - 1);
-                    // entry indexes were not changed by Resize
-                }
-                entryIndex = _count;
+                entries = Resize();
+                bucketIndex = key.HashCode & (_buckets.Length - 1);
+                // entry indexes were not changed by Resize
             }
-
-            entries[entryIndex].key = key;
-            entries[entryIndex].next = _buckets[bucketIndex] - 1;
-            _buckets[bucketIndex] = entryIndex + 1;
-            _count++;
-            return ref entries[entryIndex].value;
+            entryIndex = _count;
         }
 
-        private Entry[] Resize()
-        {
-            Debug.Assert(_entries.Length == _count || _entries.Length == 1); // We only copy _count, so if it's longer we will miss some
-            int count = _count;
-            int newSize = _entries.Length * 2;
-            if ((uint)newSize > (uint)int.MaxValue) // uint cast handles overflow
-                throw new InvalidOperationException("Capacity Overflow");
-
-            var entries = new Entry[newSize];
-            Array.Copy(_entries, 0, entries, 0, count);
+        entries[entryIndex].key = key;
+        entries[entryIndex].next = _buckets[bucketIndex] - 1;
+        _buckets[bucketIndex] = entryIndex + 1;
+        _count++;
+        return ref entries[entryIndex].value;
+    }
 
-            var newBuckets = new int[entries.Length];
-            while (count-- > 0)
-            {
-                int bucketIndex = entries[count].key.HashCode & (newBuckets.Length - 1);
-                entries[count].next = newBuckets[bucketIndex] - 1;
-                newBuckets[bucketIndex] = count + 1;
-            }
+    private Entry[] Resize()
+    {
+        Debug.Assert(_entries.Length == _count || _entries.Length == 1); // We only copy _count, so if it's longer we will miss some
+        int count = _count;
+        int newSize = _entries.Length * 2;
+        if ((uint)newSize > (uint)int.MaxValue) // uint cast handles overflow
+            throw new InvalidOperationException("Capacity Overflow");
 
-            _buckets = newBuckets;
-            _entries = entries;
+        var entries = new Entry[newSize];
+        Array.Copy(_entries, 0, entries, 0, count);
 
-            return entries;
+        var newBuckets = new int[entries.Length];
+        while (count-- > 0)
+        {
+            int bucketIndex = entries[count].key.HashCode & (newBuckets.Length - 1);
+            entries[count].next = newBuckets[bucketIndex] - 1;
+            newBuckets[bucketIndex] = count + 1;
         }
 
-        /// <summary>
-        /// Gets an enumerator over the dictionary
-        /// </summary>
-        public Enumerator GetEnumerator() => new Enumerator(this); // avoid boxing
+        _buckets = newBuckets;
+        _entries = entries;
+
+        return entries;
+    }
 
-        /// <summary>
-        /// Gets an enumerator over the dictionary
-        /// </summary>
-        IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator() =>
-            new Enumerator(this);
+    /// <summary>
+    /// Gets an enumerator over the dictionary
+    /// </summary>
+    public Enumerator GetEnumerator() => new Enumerator(this); // avoid boxing
+
+    /// <summary>
+    /// Gets an enumerator over the dictionary
+    /// </summary>
+    IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator() =>
+        new Enumerator(this);
+
+    /// <summary>
+    /// Gets an enumerator over the dictionary
+    /// </summary>
+    IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);
 
-        /// <summary>
-        /// Gets an enumerator over the dictionary
-        /// </summary>
-        IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);
+    public struct Enumerator : IEnumerator<KeyValuePair<Key, TValue>>
+    {
+        private readonly StringDictionarySlim<TValue> _dictionary;
+        private int _index;
+        private int _count;
+        private KeyValuePair<Key, TValue> _current;
 
-        public struct Enumerator : IEnumerator<KeyValuePair<Key, TValue>>
+        internal Enumerator(StringDictionarySlim<TValue> dictionary)
         {
-            private readonly StringDictionarySlim<TValue> _dictionary;
-            private int _index;
-            private int _count;
-            private KeyValuePair<Key, TValue> _current;
+            _dictionary = dictionary;
+            _index = 0;
+            _count = _dictionary._count;
+            _current = default;
+        }
 
-            internal Enumerator(StringDictionarySlim<TValue> dictionary)
+        public bool MoveNext()
+        {
+            if (_count == 0)
             {
-                _dictionary = dictionary;
-                _index = 0;
-                _count = _dictionary._count;
                 _current = default;
+                return false;
             }
 
-            public bool MoveNext()
-            {
-                if (_count == 0)
-                {
-                    _current = default;
-                    return false;
-                }
-
-                _count--;
+            _count--;
 
-                while (_dictionary._entries[_index].next < -1)
-                    _index++;
+            while (_dictionary._entries[_index].next < -1)
+                _index++;
 
-                _current = new KeyValuePair<Key, TValue>(
-                    _dictionary._entries[_index].key,
-                    _dictionary._entries[_index++].value);
-                return true;
-            }
+            _current = new KeyValuePair<Key, TValue>(
+                _dictionary._entries[_index].key,
+                _dictionary._entries[_index++].value);
+            return true;
+        }
 
-            public KeyValuePair<Key, TValue> Current => _current;
+        public KeyValuePair<Key, TValue> Current => _current;
 
-            object IEnumerator.Current => _current;
+        object IEnumerator.Current => _current;
 
-            void IEnumerator.Reset()
-            {
-                _index = 0;
-                _count = _dictionary._count;
-                _current = default;
-            }
-
-            public void Dispose() { }
+        void IEnumerator.Reset()
+        {
+            _index = 0;
+            _count = _dictionary._count;
+            _current = default;
         }
 
-        internal static class HashHelpers
-        {
-            internal static readonly int[] SizeOneIntArray = new int[1];
+        public void Dispose() { }
+    }
 
-            internal static int PowerOf2(int v)
-            {
-                if ((v & (v - 1)) == 0) return v;
-                int i = 2;
-                while (i < v) i <<= 1;
-                return i;
-            }
-        }
+    internal static class HashHelpers
+    {
+        internal static readonly int[] SizeOneIntArray = new int[1];
 
-        internal sealed class DictionarySlimDebugView<V>
+        internal static int PowerOf2(int v)
         {
-            private readonly StringDictionarySlim<V> _dictionary;
+            if ((v & (v - 1)) == 0) return v;
+            int i = 2;
+            while (i < v) i <<= 1;
+            return i;
+        }
+    }
 
-            public DictionarySlimDebugView(StringDictionarySlim<V> dictionary)
-            {
-                _dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
-            }
+    internal sealed class DictionarySlimDebugView<V>
+    {
+        private readonly StringDictionarySlim<V> _dictionary;
 
-            [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
-            public KeyValuePair<Key, V>[] Items => _dictionary.ToArray();
+        public DictionarySlimDebugView(StringDictionarySlim<V> dictionary)
+        {
+            _dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
         }
+
+        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+        public KeyValuePair<Key, V>[] Items => _dictionary.ToArray();
     }
 }

+ 7 - 8
Jint/Collections/SymbolDictionary.cs

@@ -1,16 +1,15 @@
 using Jint.Native;
 using Jint.Runtime.Descriptors;
 
-namespace Jint.Collections
+namespace Jint.Collections;
+
+internal sealed class SymbolDictionary : DictionarySlim<JsSymbol, PropertyDescriptor>
 {
-    internal sealed class SymbolDictionary : DictionarySlim<JsSymbol, PropertyDescriptor>
+    public SymbolDictionary()
     {
-        public SymbolDictionary()
-        {
-        }
+    }
 
-        public SymbolDictionary(int capacity) : base(capacity)
-        {
-        }
+    public SymbolDictionary(int capacity) : base(capacity)
+    {
     }
 }

+ 7 - 8
Jint/DeclarationBindingType.cs

@@ -1,9 +1,8 @@
-namespace Jint
+namespace Jint;
+
+public enum DeclarationBindingType
 {
-    public enum DeclarationBindingType
-    {
-        GlobalCode,
-        FunctionCode,
-        EvalCode
-    }
-}
+    GlobalCode,
+    FunctionCode,
+    EvalCode
+}

+ 1201 - 1202
Jint/Engine.cs

@@ -20,1592 +20,1591 @@ using Jint.Runtime.Interpreter;
 using Jint.Runtime.Interpreter.Expressions;
 using Environment = Jint.Runtime.Environments.Environment;
 
-namespace Jint
+namespace Jint;
+
+/// <summary>
+/// Engine is the main API to JavaScript interpretation. Engine instances are not thread-safe.
+/// </summary>
+[DebuggerTypeProxy(typeof(EngineDebugView))]
+public sealed partial class Engine : IDisposable
 {
-    /// <summary>
-    /// Engine is the main API to JavaScript interpretation. Engine instances are not thread-safe.
-    /// </summary>
-    [DebuggerTypeProxy(typeof(EngineDebugView))]
-    public sealed partial class Engine : IDisposable
-    {
-        private static readonly Options _defaultEngineOptions = new();
+    private static readonly Options _defaultEngineOptions = new();
 
-        private readonly Parser _defaultParser;
-        private ParserOptions? _defaultModuleParserOptions; // cache default ParserOptions for ModuleBuilder instances
+    private readonly Parser _defaultParser;
+    private ParserOptions? _defaultModuleParserOptions; // cache default ParserOptions for ModuleBuilder instances
 
-        private readonly ExecutionContextStack _executionContexts;
-        private JsValue _completionValue = JsValue.Undefined;
-        internal EvaluationContext? _activeEvaluationContext;
-        internal ErrorDispatchInfo? _error;
+    private readonly ExecutionContextStack _executionContexts;
+    private JsValue _completionValue = JsValue.Undefined;
+    internal EvaluationContext? _activeEvaluationContext;
+    internal ErrorDispatchInfo? _error;
 
-        private readonly EventLoop _eventLoop = new();
+    private readonly EventLoop _eventLoop = new();
 
-        private readonly Agent _agent = new();
+    private readonly Agent _agent = new();
 
-        // lazy properties
-        private DebugHandler? _debugger;
+    // lazy properties
+    private DebugHandler? _debugger;
 
-        // cached access
-        internal readonly IObjectConverter[]? _objectConverters;
-        internal readonly Constraint[] _constraints;
-        internal readonly bool _isDebugMode;
-        internal readonly bool _isStrict;
-        internal readonly IReferenceResolver _referenceResolver;
-        internal readonly ReferencePool _referencePool;
-        internal readonly ArgumentsInstancePool _argumentsInstancePool;
-        internal readonly JsValueArrayPool _jsValueArrayPool;
-        internal readonly ExtensionMethodCache _extensionMethods;
+    // cached access
+    internal readonly IObjectConverter[]? _objectConverters;
+    internal readonly Constraint[] _constraints;
+    internal readonly bool _isDebugMode;
+    internal readonly bool _isStrict;
+    internal readonly IReferenceResolver _referenceResolver;
+    internal readonly ReferencePool _referencePool;
+    internal readonly ArgumentsInstancePool _argumentsInstancePool;
+    internal readonly JsValueArrayPool _jsValueArrayPool;
+    internal readonly ExtensionMethodCache _extensionMethods;
 
-        public ITypeConverter TypeConverter { get; internal set; }
+    public ITypeConverter TypeConverter { get; internal set; }
 
-        // cache of types used when resolving CLR type names
-        internal readonly Dictionary<string, Type?> TypeCache = new(StringComparer.Ordinal);
+    // cache of types used when resolving CLR type names
+    internal readonly Dictionary<string, Type?> TypeCache = new(StringComparer.Ordinal);
 
-        // we use registered type reference as prototype if it's known
-        internal Dictionary<Type, TypeReference>? _typeReferences;
+    // we use registered type reference as prototype if it's known
+    internal Dictionary<Type, TypeReference>? _typeReferences;
 
-        // cache for already wrapped CLR objects to keep object identity
-        internal ConditionalWeakTable<object, ObjectInstance>? _objectWrapperCache;
+    // cache for already wrapped CLR objects to keep object identity
+    internal ConditionalWeakTable<object, ObjectInstance>? _objectWrapperCache;
 
-        internal readonly JintCallStack CallStack;
-        internal readonly StackGuard _stackGuard;
+    internal readonly JintCallStack CallStack;
+    internal readonly StackGuard _stackGuard;
 
-        // needed in initial engine setup, for example CLR function construction
-        internal Intrinsics _originalIntrinsics = null!;
-        internal Host _host = null!;
+    // needed in initial engine setup, for example CLR function construction
+    internal Intrinsics _originalIntrinsics = null!;
+    internal Host _host = null!;
 
-        // we need to cache reflection accessors on engine level as configuration options can affect outcome
-        internal readonly record struct ClrPropertyDescriptorFactoriesKey(Type Type, Key PropertyName);
-        internal Dictionary<ClrPropertyDescriptorFactoriesKey, ReflectionAccessor> _reflectionAccessors = new();
+    // we need to cache reflection accessors on engine level as configuration options can affect outcome
+    internal readonly record struct ClrPropertyDescriptorFactoriesKey(Type Type, Key PropertyName);
+    internal Dictionary<ClrPropertyDescriptorFactoriesKey, ReflectionAccessor> _reflectionAccessors = new();
 
-        /// <summary>
-        /// Constructs a new engine instance.
-        /// </summary>
-        public Engine() : this(null, null)
-        {
-        }
+    /// <summary>
+    /// Constructs a new engine instance.
+    /// </summary>
+    public Engine() : this(null, null)
+    {
+    }
 
-        /// <summary>
-        /// Constructs a new engine instance and allows customizing options.
-        /// </summary>
-        public Engine(Action<Options>? options)
-            : this(null, options != null ? (_, opts) => options.Invoke(opts) : null)
-        {
-        }
+    /// <summary>
+    /// Constructs a new engine instance and allows customizing options.
+    /// </summary>
+    public Engine(Action<Options>? options)
+        : this(null, options != null ? (_, opts) => options.Invoke(opts) : null)
+    {
+    }
 
-        /// <summary>
-        /// Constructs a new engine with a custom <see cref="Options"/> instance.
-        /// </summary>
-        public Engine(Options options) : this(options, null)
-        {
-        }
+    /// <summary>
+    /// Constructs a new engine with a custom <see cref="Options"/> instance.
+    /// </summary>
+    public Engine(Options options) : this(options, null)
+    {
+    }
 
-        /// <summary>
-        /// Constructs a new engine instance and allows customizing options.
-        /// </summary>
-        /// <remarks>The provided engine instance in callback is not guaranteed to be fully configured</remarks>
-        public Engine(Action<Engine, Options> options) : this(null, options)
-        {
-        }
+    /// <summary>
+    /// Constructs a new engine instance and allows customizing options.
+    /// </summary>
+    /// <remarks>The provided engine instance in callback is not guaranteed to be fully configured</remarks>
+    public Engine(Action<Engine, Options> options) : this(null, options)
+    {
+    }
 
-        private Engine(Options? options, Action<Engine, Options>? configure)
-        {
-            Advanced = new AdvancedOperations(this);
-            Constraints = new ConstraintOperations(this);
-            TypeConverter = new DefaultTypeConverter(this);
+    private Engine(Options? options, Action<Engine, Options>? configure)
+    {
+        Advanced = new AdvancedOperations(this);
+        Constraints = new ConstraintOperations(this);
+        TypeConverter = new DefaultTypeConverter(this);
 
-            _executionContexts = new ExecutionContextStack(2);
+        _executionContexts = new ExecutionContextStack(2);
 
-            // we can use default options if there's no action to modify it
-            Options = options ?? (configure is not null ? new Options() : _defaultEngineOptions);
+        // we can use default options if there's no action to modify it
+        Options = options ?? (configure is not null ? new Options() : _defaultEngineOptions);
 
-            configure?.Invoke(this, Options);
+        configure?.Invoke(this, Options);
 
-            _extensionMethods = ExtensionMethodCache.Build(Options.Interop.ExtensionMethodTypes);
+        _extensionMethods = ExtensionMethodCache.Build(Options.Interop.ExtensionMethodTypes);
 
-            Reset();
+        Reset();
 
-            // gather some options as fields for faster checks
-            _isDebugMode = Options.Debugger.Enabled;
-            _isStrict = Options.Strict;
+        // gather some options as fields for faster checks
+        _isDebugMode = Options.Debugger.Enabled;
+        _isStrict = Options.Strict;
 
-            _objectConverters = Options.Interop.ObjectConverters.Count > 0
-                ? Options.Interop.ObjectConverters.ToArray()
-                : null;
+        _objectConverters = Options.Interop.ObjectConverters.Count > 0
+            ? Options.Interop.ObjectConverters.ToArray()
+            : null;
 
-            _constraints = Options.Constraints.Constraints.ToArray();
-            _referenceResolver = Options.ReferenceResolver;
+        _constraints = Options.Constraints.Constraints.ToArray();
+        _referenceResolver = Options.ReferenceResolver;
 
-            _referencePool = new ReferencePool();
-            _argumentsInstancePool = new ArgumentsInstancePool(this);
-            _jsValueArrayPool = new JsValueArrayPool();
+        _referencePool = new ReferencePool();
+        _argumentsInstancePool = new ArgumentsInstancePool(this);
+        _jsValueArrayPool = new JsValueArrayPool();
 
-            Options.Apply(this);
+        Options.Apply(this);
 
-            CallStack = new JintCallStack(Options.Constraints.MaxRecursionDepth >= 0);
-            _stackGuard = new StackGuard(this);
+        CallStack = new JintCallStack(Options.Constraints.MaxRecursionDepth >= 0);
+        _stackGuard = new StackGuard(this);
 
-            var defaultParserOptions = ScriptParsingOptions.Default.GetParserOptions(Options);
-            _defaultParser = new Parser(defaultParserOptions);
-        }
+        var defaultParserOptions = ScriptParsingOptions.Default.GetParserOptions(Options);
+        _defaultParser = new Parser(defaultParserOptions);
+    }
 
-        private void Reset()
-        {
-            _host = Options.Host.Factory(this);
-            _host.Initialize(this);
-        }
+    private void Reset()
+    {
+        _host = Options.Host.Factory(this);
+        _host.Initialize(this);
+    }
 
-        internal ref readonly ExecutionContext ExecutionContext
-        {
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get => ref _executionContexts.Peek();
-        }
+    internal ref readonly ExecutionContext ExecutionContext
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        get => ref _executionContexts.Peek();
+    }
 
-        // temporary state for realm so that we can easily pass it to functions while still not
-        // having a proper execution context established
-        internal Realm? _realmInConstruction;
+    // temporary state for realm so that we can easily pass it to functions while still not
+    // having a proper execution context established
+    internal Realm? _realmInConstruction;
 
-        internal Node? _lastSyntaxElement;
+    internal Node? _lastSyntaxElement;
 
-        internal Realm Realm => _realmInConstruction ?? ExecutionContext.Realm;
+    internal Realm Realm => _realmInConstruction ?? ExecutionContext.Realm;
 
-        /// <summary>
-        /// The well-known intrinsics for this engine instance.
-        /// </summary>
-        public Intrinsics Intrinsics => Realm.Intrinsics;
+    /// <summary>
+    /// The well-known intrinsics for this engine instance.
+    /// </summary>
+    public Intrinsics Intrinsics => Realm.Intrinsics;
 
-        /// <summary>
-        /// The global object for this engine instance.
-        /// </summary>
-        public ObjectInstance Global => Realm.GlobalObject;
+    /// <summary>
+    /// The global object for this engine instance.
+    /// </summary>
+    public ObjectInstance Global => Realm.GlobalObject;
 
-        internal GlobalSymbolRegistry GlobalSymbolRegistry { get; } = new();
+    internal GlobalSymbolRegistry GlobalSymbolRegistry { get; } = new();
 
-        internal long CurrentMemoryUsage { get; private set; }
+    internal long CurrentMemoryUsage { get; private set; }
 
-        internal Options Options
-        {
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get;
-            private set;
-        }
+    internal Options Options
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        get;
+        private set;
+    }
 
-        public DebugHandler Debugger => _debugger ??= new DebugHandler(this, Options.Debugger.InitialStepMode);
+    public DebugHandler Debugger => _debugger ??= new DebugHandler(this, Options.Debugger.InitialStepMode);
 
-        internal ParserOptions DefaultModuleParserOptions => _defaultModuleParserOptions ??= ModuleParsingOptions.Default.GetParserOptions(Options);
+    internal ParserOptions DefaultModuleParserOptions => _defaultModuleParserOptions ??= ModuleParsingOptions.Default.GetParserOptions(Options);
 
-        internal ParserOptions GetActiveParserOptions()
-        {
-            return _executionContexts?.GetActiveParserOptions() ?? _defaultParser.Options;
-        }
+    internal ParserOptions GetActiveParserOptions()
+    {
+        return _executionContexts?.GetActiveParserOptions() ?? _defaultParser.Options;
+    }
 
-        internal Parser GetParserFor(ScriptParsingOptions parsingOptions)
-        {
-            return ReferenceEquals(parsingOptions, ScriptParsingOptions.Default)
-                ? _defaultParser
-                : new Parser(parsingOptions.GetParserOptions(Options));
-        }
+    internal Parser GetParserFor(ScriptParsingOptions parsingOptions)
+    {
+        return ReferenceEquals(parsingOptions, ScriptParsingOptions.Default)
+            ? _defaultParser
+            : new Parser(parsingOptions.GetParserOptions(Options));
+    }
 
-        internal Parser GetParserFor(ParserOptions parserOptions)
-        {
-            return ReferenceEquals(parserOptions, _defaultParser.Options) ? _defaultParser : new Parser(parserOptions);
-        }
+    internal Parser GetParserFor(ParserOptions parserOptions)
+    {
+        return ReferenceEquals(parserOptions, _defaultParser.Options) ? _defaultParser : new Parser(parserOptions);
+    }
 
-        internal void EnterExecutionContext(
-            Environment lexicalEnvironment,
-            Environment variableEnvironment,
-            Realm realm,
-            PrivateEnvironment? privateEnvironment)
-        {
-            var context = new ExecutionContext(
-                null,
-                lexicalEnvironment,
-                variableEnvironment,
-                privateEnvironment,
-                realm,
-                null);
-
-            _executionContexts.Push(context);
-        }
+    internal void EnterExecutionContext(
+        Environment lexicalEnvironment,
+        Environment variableEnvironment,
+        Realm realm,
+        PrivateEnvironment? privateEnvironment)
+    {
+        var context = new ExecutionContext(
+            null,
+            lexicalEnvironment,
+            variableEnvironment,
+            privateEnvironment,
+            realm,
+            null);
+
+        _executionContexts.Push(context);
+    }
 
-        internal void EnterExecutionContext(in ExecutionContext context)
-        {
-            _executionContexts.Push(context);
-        }
+    internal void EnterExecutionContext(in ExecutionContext context)
+    {
+        _executionContexts.Push(context);
+    }
 
-        /// <summary>
-        /// Registers a delegate with given name. Delegate becomes a JavaScript function that can be called.
-        /// </summary>
-        public Engine SetValue(string name, Delegate value)
-        {
-            Realm.GlobalObject.FastSetProperty(name, new PropertyDescriptor(new DelegateWrapper(this, value), PropertyFlag.NonEnumerable));
-            return this;
-        }
+    /// <summary>
+    /// Registers a delegate with given name. Delegate becomes a JavaScript function that can be called.
+    /// </summary>
+    public Engine SetValue(string name, Delegate value)
+    {
+        Realm.GlobalObject.FastSetProperty(name, new PropertyDescriptor(new DelegateWrapper(this, value), PropertyFlag.NonEnumerable));
+        return this;
+    }
 
-        /// <summary>
-        /// Registers a string value as variable.
-        /// </summary>
-        public Engine SetValue(string name, string? value)
-        {
-            return SetValue(name, value is null ? JsValue.Null : JsString.Create(value));
-        }
+    /// <summary>
+    /// Registers a string value as variable.
+    /// </summary>
+    public Engine SetValue(string name, string? value)
+    {
+        return SetValue(name, value is null ? JsValue.Null : JsString.Create(value));
+    }
 
-        /// <summary>
-        /// Registers a double value as variable.
-        /// </summary>
-        public Engine SetValue(string name, double value)
-        {
-            return SetValue(name, (JsValue) JsNumber.Create(value));
-        }
+    /// <summary>
+    /// Registers a double value as variable.
+    /// </summary>
+    public Engine SetValue(string name, double value)
+    {
+        return SetValue(name, (JsValue) JsNumber.Create(value));
+    }
 
-        /// <summary>
-        /// Registers an integer value as variable.
-        /// </summary>
-        public Engine SetValue(string name, int value)
-        {
-            return SetValue(name, (JsValue) JsNumber.Create(value));
-        }
+    /// <summary>
+    /// Registers an integer value as variable.
+    /// </summary>
+    public Engine SetValue(string name, int value)
+    {
+        return SetValue(name, (JsValue) JsNumber.Create(value));
+    }
 
-        /// <summary>
-        /// Registers a boolean value as variable.
-        /// </summary>
-        public Engine SetValue(string name, bool value)
-        {
-            return SetValue(name, (JsValue) (value ? JsBoolean.True : JsBoolean.False));
-        }
+    /// <summary>
+    /// Registers a boolean value as variable.
+    /// </summary>
+    public Engine SetValue(string name, bool value)
+    {
+        return SetValue(name, (JsValue) (value ? JsBoolean.True : JsBoolean.False));
+    }
 
-        /// <summary>
-        /// Registers a native JS value as variable.
-        /// </summary>
-        public Engine SetValue(string name, JsValue value)
-        {
-            Realm.GlobalObject.Set(name, value);
-            return this;
-        }
+    /// <summary>
+    /// Registers a native JS value as variable.
+    /// </summary>
+    public Engine SetValue(string name, JsValue value)
+    {
+        Realm.GlobalObject.Set(name, value);
+        return this;
+    }
 
-        /// <summary>
-        /// Registers an object value as variable, creates an interop wrapper when needed.
-        /// </summary>
-        public Engine SetValue(string name, object? obj)
-        {
-            var value = obj is Type t
-                ? TypeReference.CreateTypeReference(this, t)
-                : JsValue.FromObject(this, obj);
+    /// <summary>
+    /// Registers an object value as variable, creates an interop wrapper when needed.
+    /// </summary>
+    public Engine SetValue(string name, object? obj)
+    {
+        var value = obj is Type t
+            ? TypeReference.CreateTypeReference(this, t)
+            : JsValue.FromObject(this, obj);
 
-            return SetValue(name, value);
-        }
+        return SetValue(name, value);
+    }
 
-        /// <summary>
-        /// Registers an object value as variable, creates an interop wrapper when needed.
-        /// </summary>
-        public Engine SetValue(string name, [DynamicallyAccessedMembers(InteropHelper.DefaultDynamicallyAccessedMemberTypes)] Type type)
-        {
+    /// <summary>
+    /// Registers an object value as variable, creates an interop wrapper when needed.
+    /// </summary>
+    public Engine SetValue(string name, [DynamicallyAccessedMembers(InteropHelper.DefaultDynamicallyAccessedMemberTypes)] Type type)
+    {
 #pragma warning disable IL2111
-            return SetValue(name, TypeReference.CreateTypeReference(this, type));
+        return SetValue(name, TypeReference.CreateTypeReference(this, type));
 #pragma warning restore IL2111
-        }
+    }
 
-        /// <summary>
-        /// Registers an object value as variable, creates an interop wrapper when needed.
-        /// </summary>
-        public Engine SetValue<[DynamicallyAccessedMembers(InteropHelper.DefaultDynamicallyAccessedMemberTypes)] T>(string name, T? obj)
-        {
-            return obj is Type t
-                ? SetValue(name, t)
-                : SetValue(name, JsValue.FromObject(this, obj));
-        }
+    /// <summary>
+    /// Registers an object value as variable, creates an interop wrapper when needed.
+    /// </summary>
+    public Engine SetValue<[DynamicallyAccessedMembers(InteropHelper.DefaultDynamicallyAccessedMemberTypes)] T>(string name, T? obj)
+    {
+        return obj is Type t
+            ? SetValue(name, t)
+            : SetValue(name, JsValue.FromObject(this, obj));
+    }
 
-        internal void LeaveExecutionContext()
-        {
-            _executionContexts.Pop();
-        }
+    internal void LeaveExecutionContext()
+    {
+        _executionContexts.Pop();
+    }
 
-        internal void ResetConstraints()
+    internal void ResetConstraints()
+    {
+        foreach (var constraint in _constraints)
         {
-            foreach (var constraint in _constraints)
-            {
-                constraint.Reset();
-            }
+            constraint.Reset();
         }
+    }
 
-        /// <summary>
-        /// Initializes list of references of called functions
-        /// </summary>
-        internal void ResetCallStack()
-        {
-            CallStack.Clear();
-        }
+    /// <summary>
+    /// Initializes list of references of called functions
+    /// </summary>
+    internal void ResetCallStack()
+    {
+        CallStack.Clear();
+    }
 
-        /// <summary>
-        /// Evaluates code and returns last return value.
-        /// </summary>
-        public JsValue Evaluate(string code, string? source = null)
-        {
-            var script = _defaultParser.ParseScriptGuarded(Realm, code, source ?? "<anonymous>", _isStrict);
-            return Evaluate(new Prepared<Script>(script, _defaultParser.Options));
-        }
+    /// <summary>
+    /// Evaluates code and returns last return value.
+    /// </summary>
+    public JsValue Evaluate(string code, string? source = null)
+    {
+        var script = _defaultParser.ParseScriptGuarded(Realm, code, source ?? "<anonymous>", _isStrict);
+        return Evaluate(new Prepared<Script>(script, _defaultParser.Options));
+    }
 
-        /// <summary>
-        /// Evaluates code and returns last return value.
-        /// </summary>
-        public JsValue Evaluate(string code, ScriptParsingOptions parsingOptions)
-            => Evaluate(code, "<anonymous>", parsingOptions);
+    /// <summary>
+    /// Evaluates code and returns last return value.
+    /// </summary>
+    public JsValue Evaluate(string code, ScriptParsingOptions parsingOptions)
+        => Evaluate(code, "<anonymous>", parsingOptions);
 
-        /// <summary>
-        /// Evaluates code and returns last return value.
-        /// </summary>
-        public JsValue Evaluate(string code, string source, ScriptParsingOptions parsingOptions)
-        {
-            var parser = GetParserFor(parsingOptions);
-            var script = parser.ParseScriptGuarded(Realm, code, source, _isStrict);
-            return Evaluate(new Prepared<Script>(script, parser.Options));
-        }
+    /// <summary>
+    /// Evaluates code and returns last return value.
+    /// </summary>
+    public JsValue Evaluate(string code, string source, ScriptParsingOptions parsingOptions)
+    {
+        var parser = GetParserFor(parsingOptions);
+        var script = parser.ParseScriptGuarded(Realm, code, source, _isStrict);
+        return Evaluate(new Prepared<Script>(script, parser.Options));
+    }
 
-        /// <summary>
-        /// Evaluates code and returns last return value.
-        /// </summary>
-        public JsValue Evaluate(in Prepared<Script> preparedScript)
-            => Execute(preparedScript)._completionValue;
+    /// <summary>
+    /// Evaluates code and returns last return value.
+    /// </summary>
+    public JsValue Evaluate(in Prepared<Script> preparedScript)
+        => Execute(preparedScript)._completionValue;
 
-        /// <summary>
-        /// Executes code into engine and returns the engine instance (useful for chaining).
-        /// </summary>
-        public Engine Execute(string code, string? source = null)
-        {
-            var script = _defaultParser.ParseScriptGuarded(Realm, code, source ?? "<anonymous>", _isStrict);
-            return Execute(new Prepared<Script>(script, _defaultParser.Options));
-        }
+    /// <summary>
+    /// Executes code into engine and returns the engine instance (useful for chaining).
+    /// </summary>
+    public Engine Execute(string code, string? source = null)
+    {
+        var script = _defaultParser.ParseScriptGuarded(Realm, code, source ?? "<anonymous>", _isStrict);
+        return Execute(new Prepared<Script>(script, _defaultParser.Options));
+    }
+
+    /// <summary>
+    /// Executes code into engine and returns the engine instance (useful for chaining).
+    /// </summary>
+    public Engine Execute(string code, ScriptParsingOptions parsingOptions)
+        => Execute(code, "<anonymous>", parsingOptions);
 
-        /// <summary>
-        /// Executes code into engine and returns the engine instance (useful for chaining).
-        /// </summary>
-        public Engine Execute(string code, ScriptParsingOptions parsingOptions)
-            => Execute(code, "<anonymous>", parsingOptions);
+    /// <summary>
+    /// Executes code into engine and returns the engine instance (useful for chaining).
+    /// </summary>
+    public Engine Execute(string code, string source, ScriptParsingOptions parsingOptions)
+    {
+        var parser = GetParserFor(parsingOptions);
+        var script = parser.ParseScriptGuarded(Realm, code, source, _isStrict);
+        return Execute(new Prepared<Script>(script, parser.Options));
+    }
 
-        /// <summary>
-        /// Executes code into engine and returns the engine instance (useful for chaining).
-        /// </summary>
-        public Engine Execute(string code, string source, ScriptParsingOptions parsingOptions)
+    /// <summary>
+    /// Executes code into engine and returns the engine instance (useful for chaining).
+    /// </summary>
+    public Engine Execute(in Prepared<Script> preparedScript)
+    {
+        if (!preparedScript.IsValid)
         {
-            var parser = GetParserFor(parsingOptions);
-            var script = parser.ParseScriptGuarded(Realm, code, source, _isStrict);
-            return Execute(new Prepared<Script>(script, parser.Options));
+            ExceptionHelper.ThrowInvalidPreparedScriptArgumentException(nameof(preparedScript));
         }
 
-        /// <summary>
-        /// Executes code into engine and returns the engine instance (useful for chaining).
-        /// </summary>
-        public Engine Execute(in Prepared<Script> preparedScript)
-        {
-            if (!preparedScript.IsValid)
-            {
-                ExceptionHelper.ThrowInvalidPreparedScriptArgumentException(nameof(preparedScript));
-            }
+        var script = preparedScript.Program;
+        var parserOptions = preparedScript.ParserOptions;
+        var strict = _isStrict || script.Strict;
+        ExecuteWithConstraints(strict, () => ScriptEvaluation(new ScriptRecord(Realm, script, script.Location.SourceFile), parserOptions));
 
-            var script = preparedScript.Program;
-            var parserOptions = preparedScript.ParserOptions;
-            var strict = _isStrict || script.Strict;
-            ExecuteWithConstraints(strict, () => ScriptEvaluation(new ScriptRecord(Realm, script, script.Location.SourceFile), parserOptions));
+        return this;
+    }
 
-            return this;
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation
+    /// </summary>
+    private Engine ScriptEvaluation(ScriptRecord scriptRecord, ParserOptions parserOptions)
+    {
+        Debugger.OnBeforeEvaluate(scriptRecord.EcmaScriptCode);
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation
-        /// </summary>
-        private Engine ScriptEvaluation(ScriptRecord scriptRecord, ParserOptions parserOptions)
-        {
-            Debugger.OnBeforeEvaluate(scriptRecord.EcmaScriptCode);
+        var globalEnv = Realm.GlobalEnv;
 
-            var globalEnv = Realm.GlobalEnv;
+        var scriptContext = new ExecutionContext(
+            scriptRecord,
+            lexicalEnvironment: globalEnv,
+            variableEnvironment: globalEnv,
+            privateEnvironment: null,
+            Realm,
+            parserOptions: parserOptions);
+
+        EnterExecutionContext(scriptContext);
+        try
+        {
+            var script = scriptRecord.EcmaScriptCode;
+            GlobalDeclarationInstantiation(script, globalEnv);
 
-            var scriptContext = new ExecutionContext(
-                scriptRecord,
-                lexicalEnvironment: globalEnv,
-                variableEnvironment: globalEnv,
-                privateEnvironment: null,
-                Realm,
-                parserOptions: parserOptions);
+            var list = new JintStatementList(null, script.Body);
 
-            EnterExecutionContext(scriptContext);
+            Completion result;
             try
             {
-                var script = scriptRecord.EcmaScriptCode;
-                GlobalDeclarationInstantiation(script, globalEnv);
+                result = list.Execute(_activeEvaluationContext!);
+            }
+            catch
+            {
+                // unhandled exception
+                ResetCallStack();
+                throw;
+            }
 
-                var list = new JintStatementList(null, script.Body);
+            if (result.Type == CompletionType.Throw)
+            {
+                var ex = new JavaScriptException(result.GetValueOrDefault()).SetJavaScriptCallstack(this, result.Location);
+                ResetCallStack();
+                throw ex;
+            }
 
-                Completion result;
-                try
-                {
-                    result = list.Execute(_activeEvaluationContext!);
-                }
-                catch
-                {
-                    // unhandled exception
-                    ResetCallStack();
-                    throw;
-                }
+            _completionValue = result.GetValueOrDefault();
 
-                if (result.Type == CompletionType.Throw)
-                {
-                    var ex = new JavaScriptException(result.GetValueOrDefault()).SetJavaScriptCallstack(this, result.Location);
-                    ResetCallStack();
-                    throw ex;
-                }
+            // TODO what about callstack and thrown exceptions?
+            RunAvailableContinuations();
 
-                _completionValue = result.GetValueOrDefault();
+            return this;
+        }
+        finally
+        {
+            LeaveExecutionContext();
+        }
+    }
 
-                // TODO what about callstack and thrown exceptions?
-                RunAvailableContinuations();
+    /// <summary>
+    /// EXPERIMENTAL! Subject to change.
+    ///
+    /// Registers a promise within the currently running EventLoop (has to be called within "ExecuteWithEventLoop" call).
+    /// Note that ExecuteWithEventLoop will not trigger "onFinished" callback until ALL manual promises are settled.
+    ///
+    /// NOTE: that resolve and reject need to be called withing the same thread as "ExecuteWithEventLoop".
+    /// The API assumes that the Engine is called from a single thread.
+    /// </summary>
+    /// <returns>a Promise instance and functions to either resolve or reject it</returns>
+    internal ManualPromise RegisterPromise()
+    {
+        var promise = new JsPromise(this)
+        {
+            _prototype = Realm.Intrinsics.Promise.PrototypeObject
+        };
+
+        var (resolve, reject) = promise.CreateResolvingFunctions();
 
-                return this;
-            }
-            finally
-            {
-                LeaveExecutionContext();
-            }
-        }
 
-        /// <summary>
-        /// EXPERIMENTAL! Subject to change.
-        ///
-        /// Registers a promise within the currently running EventLoop (has to be called within "ExecuteWithEventLoop" call).
-        /// Note that ExecuteWithEventLoop will not trigger "onFinished" callback until ALL manual promises are settled.
-        ///
-        /// NOTE: that resolve and reject need to be called withing the same thread as "ExecuteWithEventLoop".
-        /// The API assumes that the Engine is called from a single thread.
-        /// </summary>
-        /// <returns>a Promise instance and functions to either resolve or reject it</returns>
-        internal ManualPromise RegisterPromise()
+        Action<JsValue> SettleWith(Function settle) => value =>
         {
-            var promise = new JsPromise(this)
-            {
-                _prototype = Realm.Intrinsics.Promise.PrototypeObject
-            };
+            settle.Call(JsValue.Undefined, new[] { value });
+            RunAvailableContinuations();
+        };
 
-            var (resolve, reject) = promise.CreateResolvingFunctions();
+        return new ManualPromise(promise, SettleWith(resolve), SettleWith(reject));
+    }
 
+    internal void AddToEventLoop(Action continuation)
+    {
+        _eventLoop.Events.Enqueue(continuation);
+    }
 
-            Action<JsValue> SettleWith(Function settle) => value =>
-            {
-                settle.Call(JsValue.Undefined, new[] { value });
-                RunAvailableContinuations();
-            };
+    internal void AddToKeptObjects(JsValue target)
+    {
+        _agent.AddToKeptObjects(target);
+    }
 
-            return new ManualPromise(promise, SettleWith(resolve), SettleWith(reject));
+    internal void RunAvailableContinuations()
+    {
+        var queue = _eventLoop.Events;
+        DoProcessEventLoop(queue);
+    }
+
+    private static void DoProcessEventLoop(ConcurrentQueue<Action> queue)
+    {
+        while (queue.TryDequeue(out var nextContinuation))
+        {
+            // note that continuation can enqueue new events
+            nextContinuation();
         }
+    }
 
-        internal void AddToEventLoop(Action continuation)
+    internal void RunBeforeExecuteStatementChecks(StatementOrExpression? statement)
+    {
+        // Avoid allocating the enumerator because we run this loop very often.
+        foreach (var constraint in _constraints)
         {
-            _eventLoop.Events.Enqueue(continuation);
+            constraint.Check();
         }
 
-        internal void AddToKeptObjects(JsValue target)
+        if (_isDebugMode && statement != null && statement.Type != NodeType.BlockStatement)
         {
-            _agent.AddToKeptObjects(target);
+            Debugger.OnStep(statement);
         }
+    }
 
-        internal void RunAvailableContinuations()
+    internal JsValue GetValue(object value)
+    {
+        return GetValue(value, false);
+    }
+
+    internal JsValue GetValue(object value, bool returnReferenceToPool)
+    {
+        if (value is JsValue jsValue)
         {
-            var queue = _eventLoop.Events;
-            DoProcessEventLoop(queue);
+            return jsValue;
         }
 
-        private static void DoProcessEventLoop(ConcurrentQueue<Action> queue)
+        if (value is not Reference reference)
         {
-            while (queue.TryDequeue(out var nextContinuation))
-            {
-                // note that continuation can enqueue new events
-                nextContinuation();
-            }
+            return ((Completion) value).Value;
         }
 
-        internal void RunBeforeExecuteStatementChecks(StatementOrExpression? statement)
+        return GetValue(reference, returnReferenceToPool);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-getvalue
+    /// </summary>
+    internal JsValue GetValue(Reference reference, bool returnReferenceToPool)
+    {
+        var baseValue = reference.Base;
+
+        if (baseValue.IsUndefined())
         {
-            // Avoid allocating the enumerator because we run this loop very often.
-            foreach (var constraint in _constraints)
+            if (_referenceResolver.TryUnresolvableReference(this, reference, out var val))
             {
-                constraint.Check();
+                return val;
             }
 
-            if (_isDebugMode && statement != null && statement.Type != NodeType.BlockStatement)
-            {
-                Debugger.OnStep(statement);
-            }
+            ExceptionHelper.ThrowReferenceError(Realm, reference);
         }
 
-        internal JsValue GetValue(object value)
+        if ((baseValue._type & InternalTypes.ObjectEnvironmentRecord) == InternalTypes.Empty
+            && _referenceResolver.TryPropertyReference(this, reference, ref baseValue))
         {
-            return GetValue(value, false);
+            return baseValue;
         }
 
-        internal JsValue GetValue(object value, bool returnReferenceToPool)
+        if (reference.IsPropertyReference)
         {
-            if (value is JsValue jsValue)
+            var property = reference.ReferencedName;
+            if (returnReferenceToPool)
             {
-                return jsValue;
+                _referencePool.Return(reference);
             }
 
-            if (value is not Reference reference)
+            if (baseValue.IsObject())
             {
-                return ((Completion) value).Value;
-            }
-
-            return GetValue(reference, returnReferenceToPool);
-        }
+                var baseObj = Runtime.TypeConverter.ToObject(Realm, baseValue);
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-getvalue
-        /// </summary>
-        internal JsValue GetValue(Reference reference, bool returnReferenceToPool)
-        {
-            var baseValue = reference.Base;
-
-            if (baseValue.IsUndefined())
-            {
-                if (_referenceResolver.TryUnresolvableReference(this, reference, out var val))
+                if (reference.IsPrivateReference)
                 {
-                    return val;
+                    return baseObj.PrivateGet((PrivateName) reference.ReferencedName);
                 }
 
-                ExceptionHelper.ThrowReferenceError(Realm, reference);
+                reference.EvaluateAndCachePropertyKey();
+                var v = baseObj.Get(reference.ReferencedName, reference.ThisValue);
+                return v;
             }
 
-            if ((baseValue._type & InternalTypes.ObjectEnvironmentRecord) == InternalTypes.Empty
-                && _referenceResolver.TryPropertyReference(this, reference, ref baseValue))
+            // check if we are accessing a string, boxing operation can be costly to do index access
+            // we have good chance to have fast path with integer or string indexer
+            ObjectInstance? o = null;
+            if ((property._type & (InternalTypes.String | InternalTypes.Integer)) != InternalTypes.Empty
+                && baseValue is JsString s
+                && TryHandleStringValue(property, s, ref o, out var jsValue))
             {
-                return baseValue;
+                return jsValue;
             }
 
-            if (reference.IsPropertyReference)
+            if (o is null)
             {
-                var property = reference.ReferencedName;
-                if (returnReferenceToPool)
-                {
-                    _referencePool.Return(reference);
-                }
-
-                if (baseValue.IsObject())
-                {
-                    var baseObj = Runtime.TypeConverter.ToObject(Realm, baseValue);
-
-                    if (reference.IsPrivateReference)
-                    {
-                        return baseObj.PrivateGet((PrivateName) reference.ReferencedName);
-                    }
-
-                    reference.EvaluateAndCachePropertyKey();
-                    var v = baseObj.Get(reference.ReferencedName, reference.ThisValue);
-                    return v;
-                }
-
-                // check if we are accessing a string, boxing operation can be costly to do index access
-                // we have good chance to have fast path with integer or string indexer
-                ObjectInstance? o = null;
-                if ((property._type & (InternalTypes.String | InternalTypes.Integer)) != InternalTypes.Empty
-                    && baseValue is JsString s
-                    && TryHandleStringValue(property, s, ref o, out var jsValue))
-                {
-                    return jsValue;
-                }
+                o = Runtime.TypeConverter.ToObject(Realm, baseValue);
+            }
 
-                if (o is null)
-                {
-                    o = Runtime.TypeConverter.ToObject(Realm, baseValue);
-                }
+            if (reference.IsPrivateReference)
+            {
+                return o.PrivateGet((PrivateName) reference.ReferencedName);
+            }
 
-                if (reference.IsPrivateReference)
-                {
-                    return o.PrivateGet((PrivateName) reference.ReferencedName);
-                }
+            return o.Get(property, reference.ThisValue);
+        }
 
-                return o.Get(property, reference.ThisValue);
-            }
+        var record = (Environment) baseValue;
+        var bindingValue = record.GetBindingValue(reference.ReferencedName.ToString(), reference.Strict);
 
-            var record = (Environment) baseValue;
-            var bindingValue = record.GetBindingValue(reference.ReferencedName.ToString(), reference.Strict);
+        if (returnReferenceToPool)
+        {
+            _referencePool.Return(reference);
+        }
 
-            if (returnReferenceToPool)
-            {
-                _referencePool.Return(reference);
-            }
+        return bindingValue;
+    }
 
-            return bindingValue;
+    private bool TryHandleStringValue(JsValue property, JsString s, ref ObjectInstance? o, out JsValue jsValue)
+    {
+        if (CommonProperties.Length.Equals(property))
+        {
+            jsValue = JsNumber.Create((uint) s.Length);
+            return true;
         }
 
-        private bool TryHandleStringValue(JsValue property, JsString s, ref ObjectInstance? o, out JsValue jsValue)
+        if (property is JsNumber number && number.IsInteger())
         {
-            if (CommonProperties.Length.Equals(property))
+            var index = number.AsInteger();
+            if (index < 0 || index >= s.Length)
             {
-                jsValue = JsNumber.Create((uint) s.Length);
+                jsValue = JsValue.Undefined;
                 return true;
             }
 
-            if (property is JsNumber number && number.IsInteger())
-            {
-                var index = number.AsInteger();
-                if (index < 0 || index >= s.Length)
-                {
-                    jsValue = JsValue.Undefined;
-                    return true;
-                }
+            jsValue = JsString.Create(s[index]);
+            return true;
+        }
 
-                jsValue = JsString.Create(s[index]);
-                return true;
-            }
+        if (property is JsString { Length: > 0 } propertyString && char.IsLower(propertyString[0]))
+        {
+            // trying to find property that's always in prototype
+            o = Realm.Intrinsics.String.PrototypeObject;
+        }
+
+        jsValue = JsValue.Undefined;
+        return false;
+    }
 
-            if (property is JsString { Length: > 0 } propertyString && char.IsLower(propertyString[0]))
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-putvalue
+    /// </summary>
+    internal void PutValue(Reference reference, JsValue value)
+    {
+        var property = reference.ReferencedName;
+        if (reference.IsUnresolvableReference)
+        {
+            if (reference.Strict && property != CommonProperties.Arguments)
             {
-                // trying to find property that's always in prototype
-                o = Realm.Intrinsics.String.PrototypeObject;
+                ExceptionHelper.ThrowReferenceError(Realm, reference);
             }
 
-            jsValue = JsValue.Undefined;
-            return false;
+            Realm.GlobalObject.Set(property, value, throwOnError: false);
         }
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-putvalue
-        /// </summary>
-        internal void PutValue(Reference reference, JsValue value)
+        else if (reference.IsPropertyReference)
         {
-            var property = reference.ReferencedName;
-            if (reference.IsUnresolvableReference)
+            var baseObject = Runtime.TypeConverter.ToObject(Realm, reference.Base);
+            if (reference.IsPrivateReference)
             {
-                if (reference.Strict && property != CommonProperties.Arguments)
-                {
-                    ExceptionHelper.ThrowReferenceError(Realm, reference);
-                }
-
-                Realm.GlobalObject.Set(property, value, throwOnError: false);
+                baseObject.PrivateSet((PrivateName) property, value);
+                return;
             }
-            else if (reference.IsPropertyReference)
-            {
-                var baseObject = Runtime.TypeConverter.ToObject(Realm, reference.Base);
-                if (reference.IsPrivateReference)
-                {
-                    baseObject.PrivateSet((PrivateName) property, value);
-                    return;
-                }
 
-                reference.EvaluateAndCachePropertyKey();
-                var succeeded = baseObject.Set(reference.ReferencedName, value, reference.ThisValue);
-                if (!succeeded && reference.Strict)
-                {
-                    ExceptionHelper.ThrowTypeError(Realm, "Cannot assign to read only property '" + property + "' of " + baseObject);
-                }
-            }
-            else
+            reference.EvaluateAndCachePropertyKey();
+            var succeeded = baseObject.Set(reference.ReferencedName, value, reference.ThisValue);
+            if (!succeeded && reference.Strict)
             {
-                ((Environment) reference.Base).SetMutableBinding(Runtime.TypeConverter.ToString(property), value, reference.Strict);
+                ExceptionHelper.ThrowTypeError(Realm, "Cannot assign to read only property '" + property + "' of " + baseObject);
             }
         }
-
-        /// <summary>
-        /// Invoke the current value as function.
-        /// </summary>
-        /// <param name="propertyName">The name of the function to call.</param>
-        /// <param name="arguments">The arguments of the function call.</param>
-        /// <returns>The value returned by the function call.</returns>
-        public JsValue Invoke(string propertyName, params object?[] arguments)
+        else
         {
-            return Invoke(propertyName, thisObj: null, arguments);
+            ((Environment) reference.Base).SetMutableBinding(Runtime.TypeConverter.ToString(property), value, reference.Strict);
         }
+    }
 
-        /// <summary>
-        /// Invoke the current value as function.
-        /// </summary>
-        /// <param name="propertyName">The name of the function to call.</param>
-        /// <param name="thisObj">The this value inside the function call.</param>
-        /// <param name="arguments">The arguments of the function call.</param>
-        /// <returns>The value returned by the function call.</returns>
-        public JsValue Invoke(string propertyName, object? thisObj, object?[] arguments)
-        {
-            var value = GetValue(propertyName);
+    /// <summary>
+    /// Invoke the current value as function.
+    /// </summary>
+    /// <param name="propertyName">The name of the function to call.</param>
+    /// <param name="arguments">The arguments of the function call.</param>
+    /// <returns>The value returned by the function call.</returns>
+    public JsValue Invoke(string propertyName, params object?[] arguments)
+    {
+        return Invoke(propertyName, thisObj: null, arguments);
+    }
 
-            return Invoke(value, thisObj, arguments);
-        }
+    /// <summary>
+    /// Invoke the current value as function.
+    /// </summary>
+    /// <param name="propertyName">The name of the function to call.</param>
+    /// <param name="thisObj">The this value inside the function call.</param>
+    /// <param name="arguments">The arguments of the function call.</param>
+    /// <returns>The value returned by the function call.</returns>
+    public JsValue Invoke(string propertyName, object? thisObj, object?[] arguments)
+    {
+        var value = GetValue(propertyName);
+
+        return Invoke(value, thisObj, arguments);
+    }
+
+    /// <summary>
+    /// Invoke the current value as function.
+    /// </summary>
+    /// <param name="value">The function to call.</param>
+    /// <param name="arguments">The arguments of the function call.</param>
+    /// <returns>The value returned by the function call.</returns>
+    public JsValue Invoke(JsValue value, params object?[] arguments)
+    {
+        return Invoke(value, thisObj: null, arguments);
+    }
 
-        /// <summary>
-        /// Invoke the current value as function.
-        /// </summary>
-        /// <param name="value">The function to call.</param>
-        /// <param name="arguments">The arguments of the function call.</param>
-        /// <returns>The value returned by the function call.</returns>
-        public JsValue Invoke(JsValue value, params object?[] arguments)
+    /// <summary>
+    /// Invoke the current value as function.
+    /// </summary>
+    /// <param name="value">The function to call.</param>
+    /// <param name="thisObj">The this value inside the function call.</param>
+    /// <param name="arguments">The arguments of the function call.</param>
+    /// <returns>The value returned by the function call.</returns>
+    public JsValue Invoke(JsValue value, object? thisObj, object?[] arguments)
+    {
+        var callable = value as ICallable;
+        if (callable is null)
         {
-            return Invoke(value, thisObj: null, arguments);
+            ExceptionHelper.ThrowJavaScriptException(Realm.Intrinsics.TypeError, "Can only invoke functions");
         }
 
-        /// <summary>
-        /// Invoke the current value as function.
-        /// </summary>
-        /// <param name="value">The function to call.</param>
-        /// <param name="thisObj">The this value inside the function call.</param>
-        /// <param name="arguments">The arguments of the function call.</param>
-        /// <returns>The value returned by the function call.</returns>
-        public JsValue Invoke(JsValue value, object? thisObj, object?[] arguments)
+        JsValue DoInvoke()
         {
-            var callable = value as ICallable;
-            if (callable is null)
+            var items = _jsValueArrayPool.RentArray(arguments.Length);
+            for (var i = 0; i < arguments.Length; ++i)
             {
-                ExceptionHelper.ThrowJavaScriptException(Realm.Intrinsics.TypeError, "Can only invoke functions");
+                items[i] = JsValue.FromObject(this, arguments[i]);
             }
 
-            JsValue DoInvoke()
+            // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
+            JsValue result;
+            var thisObject = JsValue.FromObject(this, thisObj);
+            if (callable is Function functionInstance)
             {
-                var items = _jsValueArrayPool.RentArray(arguments.Length);
-                for (var i = 0; i < arguments.Length; ++i)
+                var callStack = CallStack;
+                callStack.Push(functionInstance, expression: null, ExecutionContext);
+                try
                 {
-                    items[i] = JsValue.FromObject(this, arguments[i]);
+                    result = functionInstance.Call(thisObject, items);
                 }
-
-                // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
-                JsValue result;
-                var thisObject = JsValue.FromObject(this, thisObj);
-                if (callable is Function functionInstance)
+                finally
                 {
-                    var callStack = CallStack;
-                    callStack.Push(functionInstance, expression: null, ExecutionContext);
-                    try
-                    {
-                        result = functionInstance.Call(thisObject, items);
-                    }
-                    finally
+                    // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
+                    if (callStack.Count > 0)
                     {
-                        // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
-                        if (callStack.Count > 0)
-                        {
-                            callStack.Pop();
-                        }
+                        callStack.Pop();
                     }
                 }
-                else
-                {
-                    result = callable.Call(thisObject, items);
-                }
-
-                _jsValueArrayPool.ReturnArray(items);
-                return result;
+            }
+            else
+            {
+                result = callable.Call(thisObject, items);
             }
 
-            return ExecuteWithConstraints(Options.Strict, DoInvoke);
+            _jsValueArrayPool.ReturnArray(items);
+            return result;
         }
 
-        internal T ExecuteWithConstraints<T>(bool strict, Func<T> callback)
-        {
-            ResetConstraints();
+        return ExecuteWithConstraints(Options.Strict, DoInvoke);
+    }
 
-            var ownsContext = _activeEvaluationContext is null;
-            _activeEvaluationContext ??= new EvaluationContext(this);
+    internal T ExecuteWithConstraints<T>(bool strict, Func<T> callback)
+    {
+        ResetConstraints();
 
-            try
-            {
-                using (new StrictModeScope(strict))
-                {
-                    return callback();
-                }
-            }
-            finally
-            {
-                if (ownsContext)
-                {
-                    _activeEvaluationContext = null!;
-                }
-                ResetConstraints();
-                _agent.ClearKeptObjects();
-            }
-        }
+        var ownsContext = _activeEvaluationContext is null;
+        _activeEvaluationContext ??= new EvaluationContext(this);
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-invoke
-        /// </summary>
-        internal JsValue Invoke(JsValue v, JsValue p, JsValue[] arguments)
+        try
         {
-            var ownsContext = _activeEvaluationContext is null;
-            _activeEvaluationContext ??= new EvaluationContext(this);
-            try
+            using (new StrictModeScope(strict))
             {
-                var func = GetV(v, p);
-                var callable = func as ICallable;
-                if (callable is null)
-                {
-                    ExceptionHelper.ThrowTypeErrorNoEngine("Can only invoke functions");
-                }
-
-                return callable.Call(v, arguments);
+                return callback();
             }
-            finally
+        }
+        finally
+        {
+            if (ownsContext)
             {
-                if (ownsContext)
-                {
-                    _activeEvaluationContext = null!;
-                }
+                _activeEvaluationContext = null!;
             }
+            ResetConstraints();
+            _agent.ClearKeptObjects();
         }
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-getv
-        /// </summary>
-        private JsValue GetV(JsValue v, JsValue p)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-invoke
+    /// </summary>
+    internal JsValue Invoke(JsValue v, JsValue p, JsValue[] arguments)
+    {
+        var ownsContext = _activeEvaluationContext is null;
+        _activeEvaluationContext ??= new EvaluationContext(this);
+        try
         {
-            var o = Runtime.TypeConverter.ToObject(Realm, v);
-            return o.Get(p);
-        }
+            var func = GetV(v, p);
+            var callable = func as ICallable;
+            if (callable is null)
+            {
+                ExceptionHelper.ThrowTypeErrorNoEngine("Can only invoke functions");
+            }
 
-        /// <summary>
-        /// Gets a named value from the Global scope.
-        /// </summary>
-        /// <param name="propertyName">The name of the property to return.</param>
-        public JsValue GetValue(string propertyName)
-        {
-            return GetValue(Realm.GlobalObject, new JsString(propertyName));
+            return callable.Call(v, arguments);
         }
-
-        /// <summary>
-        /// Gets the last evaluated <see cref="Node"/>.
-        /// </summary>
-        internal Node GetLastSyntaxElement()
+        finally
         {
-            return _lastSyntaxElement!;
+            if (ownsContext)
+            {
+                _activeEvaluationContext = null!;
+            }
         }
+    }
 
-        /// <summary>
-        /// Gets a named value from the specified scope.
-        /// </summary>
-        /// <param name="scope">The scope to get the property from.</param>
-        /// <param name="property">The name of the property to return.</param>
-        public JsValue GetValue(JsValue scope, JsValue property)
-        {
-            var reference = _referencePool.Rent(scope, property, _isStrict, thisValue: null);
-            var jsValue = GetValue(reference, returnReferenceToPool: false);
-            _referencePool.Return(reference);
-            return jsValue;
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-getv
+    /// </summary>
+    private JsValue GetV(JsValue v, JsValue p)
+    {
+        var o = Runtime.TypeConverter.ToObject(Realm, v);
+        return o.Get(p);
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-resolvebinding
-        /// </summary>
-        internal Reference ResolveBinding(string name, Environment? env = null)
-        {
-            env ??= ExecutionContext.LexicalEnvironment;
-            return GetIdentifierReference(env, name, StrictModeScope.IsStrictModeCode);
-        }
+    /// <summary>
+    /// Gets a named value from the Global scope.
+    /// </summary>
+    /// <param name="propertyName">The name of the property to return.</param>
+    public JsValue GetValue(string propertyName)
+    {
+        return GetValue(Realm.GlobalObject, new JsString(propertyName));
+    }
 
-        private static Reference GetIdentifierReference(Environment? env, string name, bool strict)
-        {
-            if (env is null)
-            {
-                return new Reference(JsValue.Undefined, name, strict);
-            }
+    /// <summary>
+    /// Gets the last evaluated <see cref="Node"/>.
+    /// </summary>
+    internal Node GetLastSyntaxElement()
+    {
+        return _lastSyntaxElement!;
+    }
 
-            var envRec = env;
-            if (envRec.HasBinding(name))
-            {
-                return new Reference(envRec, name, strict);
-            }
+    /// <summary>
+    /// Gets a named value from the specified scope.
+    /// </summary>
+    /// <param name="scope">The scope to get the property from.</param>
+    /// <param name="property">The name of the property to return.</param>
+    public JsValue GetValue(JsValue scope, JsValue property)
+    {
+        var reference = _referencePool.Rent(scope, property, _isStrict, thisValue: null);
+        var jsValue = GetValue(reference, returnReferenceToPool: false);
+        _referencePool.Return(reference);
+        return jsValue;
+    }
 
-            return GetIdentifierReference(env._outerEnv, name, strict);
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-resolvebinding
+    /// </summary>
+    internal Reference ResolveBinding(string name, Environment? env = null)
+    {
+        env ??= ExecutionContext.LexicalEnvironment;
+        return GetIdentifierReference(env, name, StrictModeScope.IsStrictModeCode);
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-getnewtarget
-        /// </summary>
-        internal JsValue GetNewTarget(Environment? thisEnvironment = null)
+    private static Reference GetIdentifierReference(Environment? env, string name, bool strict)
+    {
+        if (env is null)
         {
-            // we can take as argument if caller site has already determined the value, otherwise resolve
-            thisEnvironment ??= ExecutionContext.GetThisEnvironment();
-            return thisEnvironment.NewTarget ?? JsValue.Undefined;
+            return new Reference(JsValue.Undefined, name, strict);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-resolvethisbinding
-        /// </summary>
-        internal JsValue ResolveThisBinding()
+        var envRec = env;
+        if (envRec.HasBinding(name))
         {
-            var envRec = ExecutionContext.GetThisEnvironment();
-            return envRec.GetThisBinding();
+            return new Reference(envRec, name, strict);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-globaldeclarationinstantiation
-        /// </summary>
-        private void GlobalDeclarationInstantiation(
-            Script script,
-            GlobalEnvironment env)
-        {
-            var hoistingScope = script.GetHoistingScope();
-            var functionDeclarations = hoistingScope._functionDeclarations;
+        return GetIdentifierReference(env._outerEnv, name, strict);
+    }
 
-            var functionToInitialize = new List<JintFunctionDefinition>();
-            var declaredFunctionNames = new HashSet<Key>();
-            var declaredVarNames = new List<Key>();
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-getnewtarget
+    /// </summary>
+    internal JsValue GetNewTarget(Environment? thisEnvironment = null)
+    {
+        // we can take as argument if caller site has already determined the value, otherwise resolve
+        thisEnvironment ??= ExecutionContext.GetThisEnvironment();
+        return thisEnvironment.NewTarget ?? JsValue.Undefined;
+    }
 
-            var realm = Realm;
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-resolvethisbinding
+    /// </summary>
+    internal JsValue ResolveThisBinding()
+    {
+        var envRec = ExecutionContext.GetThisEnvironment();
+        return envRec.GetThisBinding();
+    }
 
-            if (functionDeclarations != null)
-            {
-                for (var i = functionDeclarations.Count - 1; i >= 0; i--)
-                {
-                    var d = functionDeclarations[i];
-                    var fn = (Key) d.Id!.Name;
-                    if (!declaredFunctionNames.Contains(fn))
-                    {
-                        var fnDefinable = env.CanDeclareGlobalFunction(fn);
-                        if (!fnDefinable)
-                        {
-                            ExceptionHelper.ThrowTypeError(realm, "Cannot declare global function " + fn);
-                        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-globaldeclarationinstantiation
+    /// </summary>
+    private void GlobalDeclarationInstantiation(
+        Script script,
+        GlobalEnvironment env)
+    {
+        var hoistingScope = script.GetHoistingScope();
+        var functionDeclarations = hoistingScope._functionDeclarations;
 
-                        declaredFunctionNames.Add(fn);
-                        functionToInitialize.Add(new JintFunctionDefinition(d));
-                    }
-                }
-            }
+        var functionToInitialize = new List<JintFunctionDefinition>();
+        var declaredFunctionNames = new HashSet<Key>();
+        var declaredVarNames = new List<Key>();
 
-            var varNames = script.GetVarNames(hoistingScope);
-            for (var j = 0; j < varNames.Count; j++)
-            {
-                var vn = varNames[j];
-                if (env.HasLexicalDeclaration(vn))
-                {
-                    ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{vn}' has already been declared");
-                }
+        var realm = Realm;
 
-                if (!declaredFunctionNames.Contains(vn))
+        if (functionDeclarations != null)
+        {
+            for (var i = functionDeclarations.Count - 1; i >= 0; i--)
+            {
+                var d = functionDeclarations[i];
+                var fn = (Key) d.Id!.Name;
+                if (!declaredFunctionNames.Contains(fn))
                 {
-                    var vnDefinable = env.CanDeclareGlobalVar(vn);
-                    if (!vnDefinable)
+                    var fnDefinable = env.CanDeclareGlobalFunction(fn);
+                    if (!fnDefinable)
                     {
-                        ExceptionHelper.ThrowTypeError(realm);
+                        ExceptionHelper.ThrowTypeError(realm, "Cannot declare global function " + fn);
                     }
 
-                    declaredVarNames.Add(vn);
+                    declaredFunctionNames.Add(fn);
+                    functionToInitialize.Add(new JintFunctionDefinition(d));
                 }
             }
+        }
 
-            PrivateEnvironment? privateEnv = null;
-            var lexNames = script.GetLexNames(hoistingScope);
-            for (var i = 0; i < lexNames.Count; i++)
+        var varNames = script.GetVarNames(hoistingScope);
+        for (var j = 0; j < varNames.Count; j++)
+        {
+            var vn = varNames[j];
+            if (env.HasLexicalDeclaration(vn))
             {
-                var (dn, constant) = lexNames[i];
-                if (env.HasLexicalDeclaration(dn) || env.HasRestrictedGlobalProperty(dn))
-                {
-                    ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{dn}' has already been declared");
-                }
+                ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{vn}' has already been declared");
+            }
 
-                if (constant)
-                {
-                    env.CreateImmutableBinding(dn, strict: true);
-                }
-                else
+            if (!declaredFunctionNames.Contains(vn))
+            {
+                var vnDefinable = env.CanDeclareGlobalVar(vn);
+                if (!vnDefinable)
                 {
-                    env.CreateMutableBinding(dn, canBeDeleted: false);
+                    ExceptionHelper.ThrowTypeError(realm);
                 }
+
+                declaredVarNames.Add(vn);
+            }
+        }
+
+        PrivateEnvironment? privateEnv = null;
+        var lexNames = script.GetLexNames(hoistingScope);
+        for (var i = 0; i < lexNames.Count; i++)
+        {
+            var (dn, constant) = lexNames[i];
+            if (env.HasLexicalDeclaration(dn) || env.HasRestrictedGlobalProperty(dn))
+            {
+                ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{dn}' has already been declared");
             }
 
-            // we need to go through in reverse order to handle the hoisting correctly
-            for (var i = functionToInitialize.Count - 1; i > -1; i--)
+            if (constant)
             {
-                var f = functionToInitialize[i];
-                Key fn = f.Name!;
+                env.CreateImmutableBinding(dn, strict: true);
+            }
+            else
+            {
+                env.CreateMutableBinding(dn, canBeDeleted: false);
+            }
+        }
 
-                if (env.HasLexicalDeclaration(fn))
-                {
-                    ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{fn}' has already been declared");
-                }
+        // we need to go through in reverse order to handle the hoisting correctly
+        for (var i = functionToInitialize.Count - 1; i > -1; i--)
+        {
+            var f = functionToInitialize[i];
+            Key fn = f.Name!;
 
-                var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, env, privateEnv);
-                env.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
+            if (env.HasLexicalDeclaration(fn))
+            {
+                ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{fn}' has already been declared");
             }
 
-            env.CreateGlobalVarBindings(declaredVarNames, canBeDeleted: false);
+            var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, env, privateEnv);
+            env.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
-        /// </summary>
-        internal JsArguments? FunctionDeclarationInstantiation(
-            Function function,
-            JsValue[] argumentsList)
-        {
-            var calleeContext = ExecutionContext;
-            var func = function._functionDefinition;
+        env.CreateGlobalVarBindings(declaredVarNames, canBeDeleted: false);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
+    /// </summary>
+    internal JsArguments? FunctionDeclarationInstantiation(
+        Function function,
+        JsValue[] argumentsList)
+    {
+        var calleeContext = ExecutionContext;
+        var func = function._functionDefinition;
 
-            var env = (FunctionEnvironment) ExecutionContext.LexicalEnvironment;
-            var strict = _isStrict || StrictModeScope.IsStrictModeCode;
+        var env = (FunctionEnvironment) ExecutionContext.LexicalEnvironment;
+        var strict = _isStrict || StrictModeScope.IsStrictModeCode;
 
-            var configuration = func.Initialize();
-            var parameterNames = configuration.ParameterNames;
-            var hasDuplicates = configuration.HasDuplicates;
-            var simpleParameterList = configuration.IsSimpleParameterList;
-            var hasParameterExpressions = configuration.HasParameterExpressions;
+        var configuration = func.Initialize();
+        var parameterNames = configuration.ParameterNames;
+        var hasDuplicates = configuration.HasDuplicates;
+        var simpleParameterList = configuration.IsSimpleParameterList;
+        var hasParameterExpressions = configuration.HasParameterExpressions;
 
-            var canInitializeParametersOnDeclaration = simpleParameterList && !configuration.HasDuplicates;
-            var arguments = canInitializeParametersOnDeclaration ? argumentsList : null;
-            env.InitializeParameters(parameterNames, hasDuplicates, arguments);
+        var canInitializeParametersOnDeclaration = simpleParameterList && !configuration.HasDuplicates;
+        var arguments = canInitializeParametersOnDeclaration ? argumentsList : null;
+        env.InitializeParameters(parameterNames, hasDuplicates, arguments);
 
-            JsArguments? ao = null;
-            if (configuration.ArgumentsObjectNeeded || _isDebugMode)
+        JsArguments? ao = null;
+        if (configuration.ArgumentsObjectNeeded || _isDebugMode)
+        {
+            if (strict || !simpleParameterList)
             {
-                if (strict || !simpleParameterList)
-                {
-                    ao = CreateUnmappedArgumentsObject(argumentsList);
-                }
-                else
-                {
-                    // NOTE: mapped argument object is only provided for non-strict functions that don't have a rest parameter,
-                    // any parameter default value initializers, or any destructured parameters.
-                    ao = CreateMappedArgumentsObject(function, parameterNames, argumentsList, env, configuration.HasRestParameter);
-                }
-
-                if (strict)
-                {
-                    env.CreateImmutableBindingAndInitialize(KnownKeys.Arguments, strict: false, ao);
-                }
-                else
-                {
-                    env.CreateMutableBindingAndInitialize(KnownKeys.Arguments, canBeDeleted: false, ao);
-                }
+                ao = CreateUnmappedArgumentsObject(argumentsList);
             }
-
-            if (!canInitializeParametersOnDeclaration)
+            else
             {
-                // slower set
-                env.AddFunctionParameters(_activeEvaluationContext!, func.Function, argumentsList);
+                // NOTE: mapped argument object is only provided for non-strict functions that don't have a rest parameter,
+                // any parameter default value initializers, or any destructured parameters.
+                ao = CreateMappedArgumentsObject(function, parameterNames, argumentsList, env, configuration.HasRestParameter);
             }
 
-            // Let iteratorRecord be CreateListIteratorRecord(argumentsList).
-            // If hasDuplicates is true, then
-            //     Perform ? IteratorBindingInitialization for formals with iteratorRecord and undefined as arguments.
-            // Else,
-            //     Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
-
-            Environment varEnv;
-            if (!hasParameterExpressions)
+            if (strict)
             {
-                // NOTE: Only a single lexical environment is needed for the parameters and top-level vars.
-                var varsToInitialize = configuration.VarsToInitialize!;
-                for (var i = 0; i < varsToInitialize.Count; i++)
-                {
-                    var pair = varsToInitialize[i];
-                    env.CreateMutableBindingAndInitialize(pair.Name, canBeDeleted: false, JsValue.Undefined);
-                }
-
-                varEnv = env;
+                env.CreateImmutableBindingAndInitialize(KnownKeys.Arguments, strict: false, ao);
             }
             else
             {
-                // 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.
-                var varEnvRec = JintEnvironment.NewDeclarativeEnvironment(this, env);
-                varEnv = varEnvRec;
-
-                UpdateVariableEnvironment(varEnv);
-
-                var varsToInitialize = configuration.VarsToInitialize!;
-                for (var i = 0; i < varsToInitialize.Count; i++)
-                {
-                    var pair = varsToInitialize[i];
-                    var initialValue = pair.InitialValue ?? env.GetBindingValue(pair.Name, strict: false);
-                    varEnvRec.CreateMutableBindingAndInitialize(pair.Name, canBeDeleted: false, initialValue);
-                }
+                env.CreateMutableBindingAndInitialize(KnownKeys.Arguments, canBeDeleted: false, ao);
             }
+        }
 
-            // NOTE: Annex B.3.3.1 adds additional steps at this point.
-            // A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
+        if (!canInitializeParametersOnDeclaration)
+        {
+            // slower set
+            env.AddFunctionParameters(_activeEvaluationContext!, func.Function, argumentsList);
+        }
 
-            Environment lexEnv;
-            if (!strict)
+        // Let iteratorRecord be CreateListIteratorRecord(argumentsList).
+        // If hasDuplicates is true, then
+        //     Perform ? IteratorBindingInitialization for formals with iteratorRecord and undefined as arguments.
+        // Else,
+        //     Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
+
+        Environment varEnv;
+        if (!hasParameterExpressions)
+        {
+            // NOTE: Only a single lexical environment is needed for the parameters and top-level vars.
+            var varsToInitialize = configuration.VarsToInitialize!;
+            for (var i = 0; i < varsToInitialize.Count; i++)
             {
-                lexEnv = JintEnvironment.NewDeclarativeEnvironment(this, varEnv);
-                // 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
-                // with pre-existing top-level lexically scoped declarations. This is not needed for strict functions
-                // because a strict direct eval always places all declarations into a new Environment Record.
+                var pair = varsToInitialize[i];
+                env.CreateMutableBindingAndInitialize(pair.Name, canBeDeleted: false, JsValue.Undefined);
             }
-            else
+
+            varEnv = env;
+        }
+        else
+        {
+            // 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.
+            var varEnvRec = JintEnvironment.NewDeclarativeEnvironment(this, env);
+            varEnv = varEnvRec;
+
+            UpdateVariableEnvironment(varEnv);
+
+            var varsToInitialize = configuration.VarsToInitialize!;
+            for (var i = 0; i < varsToInitialize.Count; i++)
             {
-                lexEnv = varEnv;
+                var pair = varsToInitialize[i];
+                var initialValue = pair.InitialValue ?? env.GetBindingValue(pair.Name, strict: false);
+                varEnvRec.CreateMutableBindingAndInitialize(pair.Name, canBeDeleted: false, initialValue);
             }
+        }
+
+        // NOTE: Annex B.3.3.1 adds additional steps at this point.
+        // A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
 
-            UpdateLexicalEnvironment(lexEnv);
+        Environment lexEnv;
+        if (!strict)
+        {
+            lexEnv = JintEnvironment.NewDeclarativeEnvironment(this, varEnv);
+            // 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
+            // with pre-existing top-level lexically scoped declarations. This is not needed for strict functions
+            // because a strict direct eval always places all declarations into a new Environment Record.
+        }
+        else
+        {
+            lexEnv = varEnv;
+        }
 
-            if (configuration.LexicalDeclarations.Length > 0)
+        UpdateLexicalEnvironment(lexEnv);
+
+        if (configuration.LexicalDeclarations.Length > 0)
+        {
+            foreach (var d in configuration.LexicalDeclarations)
             {
-                foreach (var d in configuration.LexicalDeclarations)
+                for (var j = 0; j < d.BoundNames.Count; j++)
                 {
-                    for (var j = 0; j < d.BoundNames.Count; j++)
+                    var dn = d.BoundNames[j];
+                    if (d.IsConstantDeclaration)
                     {
-                        var dn = d.BoundNames[j];
-                        if (d.IsConstantDeclaration)
-                        {
-                            lexEnv.CreateImmutableBinding(dn, strict: true);
-                        }
-                        else
-                        {
-                            lexEnv.CreateMutableBinding(dn, canBeDeleted: false);
-                        }
+                        lexEnv.CreateImmutableBinding(dn, strict: true);
+                    }
+                    else
+                    {
+                        lexEnv.CreateMutableBinding(dn, canBeDeleted: false);
                     }
                 }
             }
+        }
 
-            if (configuration.FunctionsToInitialize != null)
+        if (configuration.FunctionsToInitialize != null)
+        {
+            var privateEnv = calleeContext.PrivateEnvironment;
+            var realm = Realm;
+            foreach (var f in configuration.FunctionsToInitialize)
             {
-                var privateEnv = calleeContext.PrivateEnvironment;
-                var realm = Realm;
-                foreach (var f in configuration.FunctionsToInitialize)
-                {
-                    var jintFunctionDefinition = new JintFunctionDefinition(f);
-                    var fn = jintFunctionDefinition.Name!;
-                    var fo = realm.Intrinsics.Function.InstantiateFunctionObject(jintFunctionDefinition, lexEnv, privateEnv);
-                    varEnv.SetMutableBinding(fn, fo, strict: false);
-                }
+                var jintFunctionDefinition = new JintFunctionDefinition(f);
+                var fn = jintFunctionDefinition.Name!;
+                var fo = realm.Intrinsics.Function.InstantiateFunctionObject(jintFunctionDefinition, lexEnv, privateEnv);
+                varEnv.SetMutableBinding(fn, fo, strict: false);
             }
-
-            return ao;
         }
 
-        private JsArguments CreateMappedArgumentsObject(
-            Function func,
-            Key[] formals,
-            JsValue[] argumentsList,
-            DeclarativeEnvironment envRec,
-            bool hasRestParameter)
-        {
-            return _argumentsInstancePool.Rent(func, formals, argumentsList, envRec, hasRestParameter);
-        }
+        return ao;
+    }
 
-        private JsArguments CreateUnmappedArgumentsObject(JsValue[] argumentsList)
-        {
-            return _argumentsInstancePool.Rent(argumentsList);
-        }
+    private JsArguments CreateMappedArgumentsObject(
+        Function func,
+        Key[] formals,
+        JsValue[] argumentsList,
+        DeclarativeEnvironment envRec,
+        bool hasRestParameter)
+    {
+        return _argumentsInstancePool.Rent(func, formals, argumentsList, envRec, hasRestParameter);
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
-        /// </summary>
-        internal void EvalDeclarationInstantiation(
-            Script script,
-            Environment varEnv,
-            Environment lexEnv,
-            PrivateEnvironment? privateEnv,
-            bool strict)
-        {
-            var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
+    private JsArguments CreateUnmappedArgumentsObject(JsValue[] argumentsList)
+    {
+        return _argumentsInstancePool.Rent(argumentsList);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
+    /// </summary>
+    internal void EvalDeclarationInstantiation(
+        Script script,
+        Environment varEnv,
+        Environment lexEnv,
+        PrivateEnvironment? privateEnv,
+        bool strict)
+    {
+        var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
 
-            var lexEnvRec = (DeclarativeEnvironment) lexEnv;
-            var varEnvRec = varEnv;
+        var lexEnvRec = (DeclarativeEnvironment) lexEnv;
+        var varEnvRec = varEnv;
 
-            var realm = Realm;
+        var realm = Realm;
 
-            if (!strict && hoistingScope._variablesDeclarations != null)
+        if (!strict && hoistingScope._variablesDeclarations != null)
+        {
+            if (varEnvRec is GlobalEnvironment globalEnvironmentRecord)
             {
-                if (varEnvRec is GlobalEnvironment globalEnvironmentRecord)
+                ref readonly var nodes = ref hoistingScope._variablesDeclarations;
+                for (var i = 0; i < nodes.Count; i++)
                 {
-                    ref readonly var nodes = ref hoistingScope._variablesDeclarations;
-                    for (var i = 0; i < nodes.Count; i++)
+                    var variablesDeclaration = nodes[i];
+                    var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
+                    if (globalEnvironmentRecord.HasLexicalDeclaration(identifier.Name))
                     {
-                        var variablesDeclaration = nodes[i];
-                        var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
-                        if (globalEnvironmentRecord.HasLexicalDeclaration(identifier.Name))
-                        {
-                            ExceptionHelper.ThrowSyntaxError(realm, "Identifier '" + identifier.Name + "' has already been declared");
-                        }
+                        ExceptionHelper.ThrowSyntaxError(realm, "Identifier '" + identifier.Name + "' has already been declared");
                     }
                 }
+            }
 
-                var thisLex = lexEnv;
-                while (!ReferenceEquals(thisLex, varEnv))
+            var thisLex = lexEnv;
+            while (!ReferenceEquals(thisLex, varEnv))
+            {
+                var thisEnvRec = thisLex;
+                if (thisEnvRec is not ObjectEnvironment)
                 {
-                    var thisEnvRec = thisLex;
-                    if (thisEnvRec is not ObjectEnvironment)
+                    ref readonly var nodes = ref hoistingScope._variablesDeclarations;
+                    for (var i = 0; i < nodes.Count; i++)
                     {
-                        ref readonly var nodes = ref hoistingScope._variablesDeclarations;
-                        for (var i = 0; i < nodes.Count; i++)
+                        var variablesDeclaration = nodes[i];
+                        var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
+                        if (thisEnvRec!.HasBinding(identifier.Name))
                         {
-                            var variablesDeclaration = nodes[i];
-                            var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
-                            if (thisEnvRec!.HasBinding(identifier.Name))
-                            {
-                                ExceptionHelper.ThrowSyntaxError(realm);
-                            }
+                            ExceptionHelper.ThrowSyntaxError(realm);
                         }
                     }
-
-                    thisLex = thisLex!._outerEnv;
                 }
+
+                thisLex = thisLex!._outerEnv;
             }
+        }
 
-            HashSet<PrivateIdentifier>? privateIdentifiers = null;
-            var pointer = privateEnv;
-            while (pointer is not null)
+        HashSet<PrivateIdentifier>? privateIdentifiers = null;
+        var pointer = privateEnv;
+        while (pointer is not null)
+        {
+            foreach (var name in pointer.Names)
             {
-                foreach (var name in pointer.Names)
-                {
-                    privateIdentifiers ??= new HashSet<PrivateIdentifier>(PrivateIdentifierNameComparer._instance);
-                    privateIdentifiers.Add(name.Key);
-                }
-
-                pointer = pointer.OuterPrivateEnvironment;
+                privateIdentifiers ??= new HashSet<PrivateIdentifier>(PrivateIdentifierNameComparer._instance);
+                privateIdentifiers.Add(name.Key);
             }
 
-            script.AllPrivateIdentifiersValid(realm, privateIdentifiers);
+            pointer = pointer.OuterPrivateEnvironment;
+        }
+
+        script.AllPrivateIdentifiersValid(realm, privateIdentifiers);
 
-            var functionDeclarations = hoistingScope._functionDeclarations;
-            var functionsToInitialize = new LinkedList<JintFunctionDefinition>();
-            var declaredFunctionNames = new HashSet<Key>();
+        var functionDeclarations = hoistingScope._functionDeclarations;
+        var functionsToInitialize = new LinkedList<JintFunctionDefinition>();
+        var declaredFunctionNames = new HashSet<Key>();
 
-            if (functionDeclarations != null)
+        if (functionDeclarations != null)
+        {
+            for (var i = functionDeclarations.Count - 1; i >= 0; i--)
             {
-                for (var i = functionDeclarations.Count - 1; i >= 0; i--)
+                var d = functionDeclarations[i];
+                Key fn = d.Id!.Name;
+                if (!declaredFunctionNames.Contains(fn))
                 {
-                    var d = functionDeclarations[i];
-                    Key fn = d.Id!.Name;
-                    if (!declaredFunctionNames.Contains(fn))
+                    if (varEnvRec is GlobalEnvironment ger)
                     {
-                        if (varEnvRec is GlobalEnvironment ger)
+                        var fnDefinable = ger.CanDeclareGlobalFunction(fn);
+                        if (!fnDefinable)
                         {
-                            var fnDefinable = ger.CanDeclareGlobalFunction(fn);
-                            if (!fnDefinable)
-                            {
-                                ExceptionHelper.ThrowTypeError(realm);
-                            }
+                            ExceptionHelper.ThrowTypeError(realm);
                         }
-
-                        declaredFunctionNames.Add(fn);
-                        functionsToInitialize.AddFirst(new JintFunctionDefinition(d));
                     }
+
+                    declaredFunctionNames.Add(fn);
+                    functionsToInitialize.AddFirst(new JintFunctionDefinition(d));
                 }
             }
+        }
 
-            var boundNames = new List<Key>();
-            var declaredVarNames = new List<Key>();
-            var variableDeclarations = hoistingScope._variablesDeclarations;
-            var variableDeclarationsCount = variableDeclarations?.Count;
-            for (var i = 0; i < variableDeclarationsCount; i++)
+        var boundNames = new List<Key>();
+        var declaredVarNames = new List<Key>();
+        var variableDeclarations = hoistingScope._variablesDeclarations;
+        var variableDeclarationsCount = variableDeclarations?.Count;
+        for (var i = 0; i < variableDeclarationsCount; i++)
+        {
+            var variableDeclaration = variableDeclarations![i];
+            boundNames.Clear();
+            variableDeclaration.GetBoundNames(boundNames);
+            for (var j = 0; j < boundNames.Count; j++)
             {
-                var variableDeclaration = variableDeclarations![i];
-                boundNames.Clear();
-                variableDeclaration.GetBoundNames(boundNames);
-                for (var j = 0; j < boundNames.Count; j++)
+                var vn = boundNames[j];
+                if (!declaredFunctionNames.Contains(vn))
                 {
-                    var vn = boundNames[j];
-                    if (!declaredFunctionNames.Contains(vn))
+                    if (varEnvRec is GlobalEnvironment ger)
                     {
-                        if (varEnvRec is GlobalEnvironment ger)
+                        var vnDefinable = ger.CanDeclareGlobalFunction(vn);
+                        if (!vnDefinable)
                         {
-                            var vnDefinable = ger.CanDeclareGlobalFunction(vn);
-                            if (!vnDefinable)
-                            {
-                                ExceptionHelper.ThrowTypeError(realm);
-                            }
+                            ExceptionHelper.ThrowTypeError(realm);
                         }
-
-                        declaredVarNames.Add(vn);
                     }
-                }
-            }
 
-            var lexicalDeclarations = hoistingScope._lexicalDeclarations;
-            var lexicalDeclarationsCount = lexicalDeclarations?.Count;
-            for (var i = 0; i < lexicalDeclarationsCount; i++)
-            {
-                boundNames.Clear();
-                var d = lexicalDeclarations![i];
-                d.GetBoundNames(boundNames);
-                for (var j = 0; j < boundNames.Count; j++)
-                {
-                    Key dn = boundNames[j];
-                    if (d.IsConstantDeclaration())
-                    {
-                        lexEnvRec.CreateImmutableBinding(dn, strict: true);
-                    }
-                    else
-                    {
-                        lexEnvRec.CreateMutableBinding(dn, canBeDeleted: false);
-                    }
+                    declaredVarNames.Add(vn);
                 }
             }
+        }
 
-            foreach (var f in functionsToInitialize)
+        var lexicalDeclarations = hoistingScope._lexicalDeclarations;
+        var lexicalDeclarationsCount = lexicalDeclarations?.Count;
+        for (var i = 0; i < lexicalDeclarationsCount; i++)
+        {
+            boundNames.Clear();
+            var d = lexicalDeclarations![i];
+            d.GetBoundNames(boundNames);
+            for (var j = 0; j < boundNames.Count; j++)
             {
-                var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, lexEnv, privateEnv);
-                if (varEnvRec is GlobalEnvironment ger)
+                Key dn = boundNames[j];
+                if (d.IsConstantDeclaration())
                 {
-                    ger.CreateGlobalFunctionBinding(f.Name!, fo, canBeDeleted: true);
+                    lexEnvRec.CreateImmutableBinding(dn, strict: true);
                 }
                 else
                 {
-                    Key fn = f.Name!;
-                    var bindingExists = varEnvRec.HasBinding(fn);
-                    if (!bindingExists)
-                    {
-                        varEnvRec.CreateMutableBinding(fn, canBeDeleted: true);
-                        varEnvRec.InitializeBinding(fn, fo);
-                    }
-                    else
-                    {
-                        varEnvRec.SetMutableBinding(fn, fo, strict: false);
-                    }
+                    lexEnvRec.CreateMutableBinding(dn, canBeDeleted: false);
                 }
             }
+        }
 
-            foreach (var vn in declaredVarNames)
+        foreach (var f in functionsToInitialize)
+        {
+            var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, lexEnv, privateEnv);
+            if (varEnvRec is GlobalEnvironment ger)
+            {
+                ger.CreateGlobalFunctionBinding(f.Name!, fo, canBeDeleted: true);
+            }
+            else
             {
-                if (varEnvRec is GlobalEnvironment ger)
+                Key fn = f.Name!;
+                var bindingExists = varEnvRec.HasBinding(fn);
+                if (!bindingExists)
                 {
-                    ger.CreateGlobalVarBinding(vn, canBeDeleted: true);
+                    varEnvRec.CreateMutableBinding(fn, canBeDeleted: true);
+                    varEnvRec.InitializeBinding(fn, fo);
                 }
                 else
                 {
-                    var bindingExists = varEnvRec.HasBinding(vn);
-                    if (!bindingExists)
-                    {
-                        varEnvRec.CreateMutableBinding(vn, canBeDeleted: true);
-                        varEnvRec.InitializeBinding(vn, JsValue.Undefined);
-                    }
+                    varEnvRec.SetMutableBinding(fn, fo, strict: false);
                 }
             }
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void UpdateLexicalEnvironment(Environment newEnv)
-        {
-            _executionContexts.ReplaceTopLexicalEnvironment(newEnv);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void UpdateVariableEnvironment(Environment newEnv)
+        foreach (var vn in declaredVarNames)
         {
-            _executionContexts.ReplaceTopVariableEnvironment(newEnv);
+            if (varEnvRec is GlobalEnvironment ger)
+            {
+                ger.CreateGlobalVarBinding(vn, canBeDeleted: true);
+            }
+            else
+            {
+                var bindingExists = varEnvRec.HasBinding(vn);
+                if (!bindingExists)
+                {
+                    varEnvRec.CreateMutableBinding(vn, canBeDeleted: true);
+                    varEnvRec.InitializeBinding(vn, JsValue.Undefined);
+                }
+            }
         }
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void UpdatePrivateEnvironment(PrivateEnvironment? newEnv)
-        {
-            _executionContexts.ReplaceTopPrivateEnvironment(newEnv);
-        }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void UpdateLexicalEnvironment(Environment newEnv)
+    {
+        _executionContexts.ReplaceTopLexicalEnvironment(newEnv);
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal ref readonly ExecutionContext UpdateGenerator(GeneratorInstance generator)
-        {
-            return ref _executionContexts.ReplaceTopGenerator(generator);
-        }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void UpdateVariableEnvironment(Environment newEnv)
+    {
+        _executionContexts.ReplaceTopVariableEnvironment(newEnv);
+    }
 
-        /// <summary>
-        /// Invokes the named callable and returns the resulting object.
-        /// </summary>
-        /// <param name="callableName">The name of the callable.</param>
-        /// <param name="arguments">The arguments of the call.</param>
-        /// <returns>The value returned by the call.</returns>
-        public JsValue Call(string callableName, params JsValue[] arguments)
-        {
-            var callable = Evaluate(callableName);
-            return Call(callable, arguments);
-        }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void UpdatePrivateEnvironment(PrivateEnvironment? newEnv)
+    {
+        _executionContexts.ReplaceTopPrivateEnvironment(newEnv);
+    }
 
-        /// <summary>
-        /// Invokes the callable and returns the resulting object.
-        /// </summary>
-        /// <param name="callable">The callable.</param>
-        /// <param name="arguments">The arguments of the call.</param>
-        /// <returns>The value returned by the call.</returns>
-        public JsValue Call(JsValue callable, params JsValue[] arguments)
-            => Call(callable, thisObject: JsValue.Undefined, arguments);
-
-        /// <summary>
-        /// Invokes the callable and returns the resulting object.
-        /// </summary>
-        /// <param name="callable">The callable.</param>
-        /// <param name="thisObject">Value bound as this.</param>
-        /// <param name="arguments">The arguments of the call.</param>
-        /// <returns>The value returned by the call.</returns>
-        public JsValue Call(JsValue callable, JsValue thisObject, JsValue[] arguments)
-        {
-            JsValue Callback()
-            {
-                if (!callable.IsCallable)
-                {
-                    ExceptionHelper.ThrowArgumentException(callable + " is not callable");
-                }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal ref readonly ExecutionContext UpdateGenerator(GeneratorInstance generator)
+    {
+        return ref _executionContexts.ReplaceTopGenerator(generator);
+    }
 
-                return Call((ICallable) callable, thisObject, arguments, null);
-            }
+    /// <summary>
+    /// Invokes the named callable and returns the resulting object.
+    /// </summary>
+    /// <param name="callableName">The name of the callable.</param>
+    /// <param name="arguments">The arguments of the call.</param>
+    /// <returns>The value returned by the call.</returns>
+    public JsValue Call(string callableName, params JsValue[] arguments)
+    {
+        var callable = Evaluate(callableName);
+        return Call(callable, arguments);
+    }
 
-            return ExecuteWithConstraints(Options.Strict, Callback);
-        }
+    /// <summary>
+    /// Invokes the callable and returns the resulting object.
+    /// </summary>
+    /// <param name="callable">The callable.</param>
+    /// <param name="arguments">The arguments of the call.</param>
+    /// <returns>The value returned by the call.</returns>
+    public JsValue Call(JsValue callable, params JsValue[] arguments)
+        => Call(callable, thisObject: JsValue.Undefined, arguments);
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal JsValue Call(ICallable callable, JsValue thisObject, JsValue[] arguments, JintExpression? expression)
+    /// <summary>
+    /// Invokes the callable and returns the resulting object.
+    /// </summary>
+    /// <param name="callable">The callable.</param>
+    /// <param name="thisObject">Value bound as this.</param>
+    /// <param name="arguments">The arguments of the call.</param>
+    /// <returns>The value returned by the call.</returns>
+    public JsValue Call(JsValue callable, JsValue thisObject, JsValue[] arguments)
+    {
+        JsValue Callback()
         {
-            if (callable is Function functionInstance)
+            if (!callable.IsCallable)
             {
-                return Call(functionInstance, thisObject, arguments, expression);
+                ExceptionHelper.ThrowArgumentException(callable + " is not callable");
             }
 
-            return callable.Call(thisObject, arguments);
+            return Call((ICallable) callable, thisObject, arguments, null);
         }
 
-        /// <summary>
-        /// Calls the named constructor and returns the resulting object.
-        /// </summary>
-        /// <param name="constructorName">The name of the constructor to call.</param>
-        /// <param name="arguments">The arguments of the constructor call.</param>
-        /// <returns>The value returned by the constructor call.</returns>
-        public ObjectInstance Construct(string constructorName, params JsValue[] arguments)
-        {
-            var constructor = Evaluate(constructorName);
-            return Construct(constructor, arguments);
-        }
+        return ExecuteWithConstraints(Options.Strict, Callback);
+    }
 
-        /// <summary>
-        /// Calls the constructor and returns the resulting object.
-        /// </summary>
-        /// <param name="constructor">The name of the constructor to call.</param>
-        /// <param name="arguments">The arguments of the constructor call.</param>
-        /// <returns>The value returned by the constructor call.</returns>
-        public ObjectInstance Construct(JsValue constructor, params JsValue[] arguments)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal JsValue Call(ICallable callable, JsValue thisObject, JsValue[] arguments, JintExpression? expression)
+    {
+        if (callable is Function functionInstance)
         {
-            ObjectInstance Callback()
-            {
-                if (!constructor.IsConstructor)
-                {
-                    ExceptionHelper.ThrowArgumentException(constructor + " is not a constructor");
-                }
+            return Call(functionInstance, thisObject, arguments, expression);
+        }
 
-                return Construct(constructor, arguments, constructor, null);
-            }
+        return callable.Call(thisObject, arguments);
+    }
 
-            return ExecuteWithConstraints(Options.Strict, Callback);
-        }
+    /// <summary>
+    /// Calls the named constructor and returns the resulting object.
+    /// </summary>
+    /// <param name="constructorName">The name of the constructor to call.</param>
+    /// <param name="arguments">The arguments of the constructor call.</param>
+    /// <returns>The value returned by the constructor call.</returns>
+    public ObjectInstance Construct(string constructorName, params JsValue[] arguments)
+    {
+        var constructor = Evaluate(constructorName);
+        return Construct(constructor, arguments);
+    }
 
-        internal ObjectInstance Construct(
-            JsValue constructor,
-            JsValue[] arguments,
-            JsValue newTarget,
-            JintExpression? expression)
+    /// <summary>
+    /// Calls the constructor and returns the resulting object.
+    /// </summary>
+    /// <param name="constructor">The name of the constructor to call.</param>
+    /// <param name="arguments">The arguments of the constructor call.</param>
+    /// <returns>The value returned by the constructor call.</returns>
+    public ObjectInstance Construct(JsValue constructor, params JsValue[] arguments)
+    {
+        ObjectInstance Callback()
         {
-            if (constructor is Function functionInstance)
+            if (!constructor.IsConstructor)
             {
-                return Construct(functionInstance, arguments, newTarget, expression);
+                ExceptionHelper.ThrowArgumentException(constructor + " is not a constructor");
             }
 
-            return ((IConstructor) constructor).Construct(arguments, newTarget);
+            return Construct(constructor, arguments, constructor, null);
         }
 
-        internal JsValue Call(Function function, JsValue thisObject)
-            => Call(function, thisObject, Arguments.Empty, null);
+        return ExecuteWithConstraints(Options.Strict, Callback);
+    }
 
-        internal JsValue Call(
-            Function function,
-            JsValue thisObject,
-            JsValue[] arguments,
-            JintExpression? expression)
+    internal ObjectInstance Construct(
+        JsValue constructor,
+        JsValue[] arguments,
+        JsValue newTarget,
+        JintExpression? expression)
+    {
+        if (constructor is Function functionInstance)
         {
-            // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
+            return Construct(functionInstance, arguments, newTarget, expression);
+        }
 
-            var recursionDepth = CallStack.Push(function, expression, ExecutionContext);
+        return ((IConstructor) constructor).Construct(arguments, newTarget);
+    }
 
-            if (recursionDepth > Options.Constraints.MaxRecursionDepth)
-            {
-                // automatically pops the current element as it was never reached
-                ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack);
-            }
+    internal JsValue Call(Function function, JsValue thisObject)
+        => Call(function, thisObject, Arguments.Empty, null);
 
-            JsValue result;
-            try
-            {
-                result = function.Call(thisObject, arguments);
-            }
-            finally
-            {
-                // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
-                if (CallStack.Count > 0)
-                {
-                    CallStack.Pop();
-                }
-            }
+    internal JsValue Call(
+        Function function,
+        JsValue thisObject,
+        JsValue[] arguments,
+        JintExpression? expression)
+    {
+        // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
 
-            return result;
-        }
+        var recursionDepth = CallStack.Push(function, expression, ExecutionContext);
 
-        private ObjectInstance Construct(
-            Function function,
-            JsValue[] arguments,
-            JsValue newTarget,
-            JintExpression? expression)
+        if (recursionDepth > Options.Constraints.MaxRecursionDepth)
         {
-            // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
-
-            var recursionDepth = CallStack.Push(function, expression, ExecutionContext);
-
-            if (recursionDepth > Options.Constraints.MaxRecursionDepth)
-            {
-                // automatically pops the current element as it was never reached
-                ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack);
-            }
+            // automatically pops the current element as it was never reached
+            ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack);
+        }
 
-            ObjectInstance result;
-            try
-            {
-                result = ((IConstructor) function).Construct(arguments, newTarget);
-            }
-            finally
+        JsValue result;
+        try
+        {
+            result = function.Call(thisObject, arguments);
+        }
+        finally
+        {
+            // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
+            if (CallStack.Count > 0)
             {
                 CallStack.Pop();
             }
-
-            return result;
         }
 
-        internal void SignalError(ErrorDispatchInfo error)
+        return result;
+    }
+
+    private ObjectInstance Construct(
+        Function function,
+        JsValue[] arguments,
+        JsValue newTarget,
+        JintExpression? expression)
+    {
+        // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
+
+        var recursionDepth = CallStack.Push(function, expression, ExecutionContext);
+
+        if (recursionDepth > Options.Constraints.MaxRecursionDepth)
         {
-            _error = error;
+            // automatically pops the current element as it was never reached
+            ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack);
         }
 
-        internal void RegisterTypeReference(TypeReference reference)
+        ObjectInstance result;
+        try
         {
-            _typeReferences ??= new Dictionary<Type, TypeReference>();
-            _typeReferences[reference.ReferenceType] = reference;
+            result = ((IConstructor) function).Construct(arguments, newTarget);
         }
-
-        internal ref readonly ExecutionContext GetExecutionContext(int fromTop)
+        finally
         {
-            return ref _executionContexts.Peek(fromTop);
+            CallStack.Pop();
         }
 
-        public void Dispose()
+        return result;
+    }
+
+    internal void SignalError(ErrorDispatchInfo error)
+    {
+        _error = error;
+    }
+
+    internal void RegisterTypeReference(TypeReference reference)
+    {
+        _typeReferences ??= new Dictionary<Type, TypeReference>();
+        _typeReferences[reference.ReferenceType] = reference;
+    }
+
+    internal ref readonly ExecutionContext GetExecutionContext(int fromTop)
+    {
+        return ref _executionContexts.Peek(fromTop);
+    }
+
+    public void Dispose()
+    {
+        if (_objectWrapperCache is null)
         {
-            if (_objectWrapperCache is null)
-            {
-                return;
-            }
+            return;
+        }
 
 #if SUPPORTS_WEAK_TABLE_CLEAR
             _objectWrapperCache.Clear();
 #else
-            // we can expect that reflection is OK as we've been generating object wrappers already
-            var clearMethod = _objectWrapperCache.GetType().GetMethod("Clear", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
-            clearMethod?.Invoke(_objectWrapperCache, Array.Empty<object>());
+        // we can expect that reflection is OK as we've been generating object wrappers already
+        var clearMethod = _objectWrapperCache.GetType().GetMethod("Clear", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
+        clearMethod?.Invoke(_objectWrapperCache, Array.Empty<object>());
 #endif
-        }
+    }
 
-        [DebuggerDisplay("Engine")]
-        private sealed class EngineDebugView
-        {
-            private readonly Engine _engine;
+    [DebuggerDisplay("Engine")]
+    private sealed class EngineDebugView
+    {
+        private readonly Engine _engine;
 
-            public EngineDebugView(Engine engine)
-            {
-                _engine = engine;
-            }
+        public EngineDebugView(Engine engine)
+        {
+            _engine = engine;
+        }
 
-            public ObjectInstance Globals => _engine.Realm.GlobalObject;
-            public Options Options => _engine.Options;
+        public ObjectInstance Globals => _engine.Realm.GlobalObject;
+        public Options Options => _engine.Options;
 
-            public Environment VariableEnvironment => _engine.ExecutionContext.VariableEnvironment;
-            public Environment LexicalEnvironment => _engine.ExecutionContext.LexicalEnvironment;
-        }
+        public Environment VariableEnvironment => _engine.ExecutionContext.VariableEnvironment;
+        public Environment LexicalEnvironment => _engine.ExecutionContext.LexicalEnvironment;
     }
-}
+}

+ 36 - 37
Jint/Extensions/Character.cs

@@ -1,49 +1,48 @@
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
 
-namespace Jint.Extensions
+namespace Jint.Extensions;
+
+internal static class Character
 {
-    internal static class Character
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static bool IsInRange(this char c, ushort min, ushort max)
     {
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static bool IsInRange(this char c, ushort min, ushort max)
-        {
-            Debug.Assert(min <= max);
-            return c - (uint) min <= max - (uint) min;
-        }
+        Debug.Assert(min <= max);
+        return c - (uint) min <= max - (uint) min;
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsOctalDigit(this char c) => c.IsInRange('0', '7');
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public static bool IsOctalDigit(this char c) => c.IsInRange('0', '7');
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsDecimalDigit(this char c) => c.IsInRange('0', '9');
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public static bool IsDecimalDigit(this char c) => c.IsInRange('0', '9');
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsHexDigit(this char c)
-        {
-            // NOTE: On 32-bit architectures this is not optimal, lookup is supposed to be faster.
-            // But to keep it simple, we use this method regardless of CPU architecture, and if performance
-            // needs to be improved further, the lookup approach can be ported from Esprima.HexConverter.
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public static bool IsHexDigit(this char c)
+    {
+        // NOTE: On 32-bit architectures this is not optimal, lookup is supposed to be faster.
+        // But to keep it simple, we use this method regardless of CPU architecture, and if performance
+        // needs to be improved further, the lookup approach can be ported from Esprima.HexConverter.
 
-            // This code path, when used, has no branches and doesn't depend on cache hits,
-            // so it's faster and does not vary in speed depending on input data distribution.
-            // The magic constant 18428868213665201664 is a 64 bit value containing 1s at the
-            // indices corresponding to all the valid hex characters (ie. "0123456789ABCDEFabcdef")
-            // minus 48 (ie. '0'), and backwards (so from the most significant bit and downwards).
-            // The offset of 48 for each bit is necessary so that the entire range fits in 64 bits.
-            // First, we subtract '0' to the input digit (after casting to uint to account for any
-            // negative inputs). Note that even if this subtraction underflows, this happens before
-            // the result is zero-extended to ulong, meaning that `i` will always have upper 32 bits
-            // equal to 0. We then left shift the constant with this offset, and apply a bitmask that
-            // has the highest bit set (the sign bit) if and only if `c` is in the ['0', '0' + 64) range.
-            // Then we only need to check whether this final result is less than 0: this will only be
-            // the case if both `i` was in fact the index of a set bit in the magic constant, and also
-            // `c` was in the allowed range (this ensures that false positive bit shifts are ignored).
-            ulong i = (uint) c - '0';
-            ulong shift = 18428868213665201664UL << (int) i;
-            ulong mask = i - 64;
+        // This code path, when used, has no branches and doesn't depend on cache hits,
+        // so it's faster and does not vary in speed depending on input data distribution.
+        // The magic constant 18428868213665201664 is a 64 bit value containing 1s at the
+        // indices corresponding to all the valid hex characters (ie. "0123456789ABCDEFabcdef")
+        // minus 48 (ie. '0'), and backwards (so from the most significant bit and downwards).
+        // The offset of 48 for each bit is necessary so that the entire range fits in 64 bits.
+        // First, we subtract '0' to the input digit (after casting to uint to account for any
+        // negative inputs). Note that even if this subtraction underflows, this happens before
+        // the result is zero-extended to ulong, meaning that `i` will always have upper 32 bits
+        // equal to 0. We then left shift the constant with this offset, and apply a bitmask that
+        // has the highest bit set (the sign bit) if and only if `c` is in the ['0', '0' + 64) range.
+        // Then we only need to check whether this final result is less than 0: this will only be
+        // the case if both `i` was in fact the index of a set bit in the magic constant, and also
+        // `c` was in the allowed range (this ensures that false positive bit shifts are ignored).
+        ulong i = (uint) c - '0';
+        ulong shift = 18428868213665201664UL << (int) i;
+        ulong mask = i - 64;
 
-            return (long) (shift & mask) < 0 ? true : false;
-        }
+        return (long) (shift & mask) < 0 ? true : false;
     }
 }

+ 10 - 11
Jint/Extensions/JavascriptExtensions.cs

@@ -1,17 +1,16 @@
-namespace Jint.Extensions
+namespace Jint.Extensions;
+
+internal static class JavascriptExtensions
 {
-    internal static class JavascriptExtensions
+    internal static string UpperToLowerCamelCase(this string str)
     {
-        internal static string UpperToLowerCamelCase(this string str)
+        if (char.IsLower(str[0]))
         {
-            if (char.IsLower(str[0]))
-            {
-                return str;
-            }
-
-            var arr = str.ToCharArray();
-            arr[0] = char.ToLowerInvariant(arr[0]);
-            return new string(arr);
+            return str;
         }
+
+        var arr = str.ToCharArray();
+        arr[0] = char.ToLowerInvariant(arr[0]);
+        return new string(arr);
     }
 }

+ 126 - 127
Jint/Extensions/ReflectionExtensions.cs

@@ -5,167 +5,166 @@ using System.Runtime.CompilerServices;
 using Jint.Native;
 using Jint.Runtime;
 
-namespace Jint.Extensions
+namespace Jint.Extensions;
+
+internal static class ReflectionExtensions
 {
-    internal static class ReflectionExtensions
-    {
-        private static readonly Type nullableType = typeof(Nullable<>);
+    private static readonly Type nullableType = typeof(Nullable<>);
 
-        internal static void SetValue(this MemberInfo memberInfo, object forObject, object? value)
+    internal static void SetValue(this MemberInfo memberInfo, object forObject, object? value)
+    {
+        if (memberInfo.MemberType == MemberTypes.Field)
         {
-            if (memberInfo.MemberType == MemberTypes.Field)
-            {
-                var fieldInfo = (FieldInfo) memberInfo;
-                if (value != null && fieldInfo.FieldType.IsInstanceOfType(value))
-                {
-                    fieldInfo.SetValue(forObject, value);
-                }
-            }
-            else if (memberInfo.MemberType == MemberTypes.Property)
+            var fieldInfo = (FieldInfo) memberInfo;
+            if (value != null && fieldInfo.FieldType.IsInstanceOfType(value))
             {
-                var propertyInfo = (PropertyInfo) memberInfo;
-                if (value != null && propertyInfo.PropertyType.IsInstanceOfType(value))
-                {
-                    propertyInfo.SetValue(forObject, value);
-                }
+                fieldInfo.SetValue(forObject, value);
             }
         }
-
-        internal static Type GetDefinedType(this MemberInfo memberInfo)
+        else if (memberInfo.MemberType == MemberTypes.Property)
         {
-            return memberInfo switch
+            var propertyInfo = (PropertyInfo) memberInfo;
+            if (value != null && propertyInfo.PropertyType.IsInstanceOfType(value))
             {
-                PropertyInfo propertyInfo => propertyInfo.PropertyType,
-                FieldInfo fieldInfo => fieldInfo.FieldType,
-                _ => null!
-            };
+                propertyInfo.SetValue(forObject, value);
+            }
         }
+    }
 
-        internal static IEnumerable<MethodInfo> GetExtensionMethods([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] this Type type)
+    internal static Type GetDefinedType(this MemberInfo memberInfo)
+    {
+        return memberInfo switch
         {
-            return type.GetMethods(BindingFlags.Public | BindingFlags.Static)
-                .Where(static m => m.IsExtensionMethod());
-        }
+            PropertyInfo propertyInfo => propertyInfo.PropertyType,
+            FieldInfo fieldInfo => fieldInfo.FieldType,
+            _ => null!
+        };
+    }
+
+    internal static IEnumerable<MethodInfo> GetExtensionMethods([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] this Type type)
+    {
+        return type.GetMethods(BindingFlags.Public | BindingFlags.Static)
+            .Where(static m => m.IsExtensionMethod());
+    }
+
+    internal static IEnumerable<MethodInfo> GetOperatorOverloadMethods([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] this Type type)
+    {
+        return type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
+            .Where(static m => m.IsSpecialName);
+    }
 
-        internal static IEnumerable<MethodInfo> GetOperatorOverloadMethods([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] this Type type)
+    private static bool IsExtensionMethod(this MethodBase methodInfo)
+    {
+        return methodInfo.IsDefined(typeof(ExtensionAttribute), inherit: true);
+    }
+
+    public static bool IsNullable(this Type type)
+    {
+        return type is { IsGenericType: true } && type.GetGenericTypeDefinition() == nullableType;
+    }
+
+    public static bool IsNumeric(this Type type)
+    {
+        if (type == null || type.IsEnum)
         {
-            return type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
-                .Where(static m => m.IsSpecialName);
+            return false;
         }
 
-        private static bool IsExtensionMethod(this MethodBase methodInfo)
+        switch (Type.GetTypeCode(type))
         {
-            return methodInfo.IsDefined(typeof(ExtensionAttribute), inherit: true);
+            case TypeCode.Byte:
+            case TypeCode.Decimal:
+            case TypeCode.Double:
+            case TypeCode.Int16:
+            case TypeCode.Int32:
+            case TypeCode.Int64:
+            case TypeCode.SByte:
+            case TypeCode.Single:
+            case TypeCode.UInt16:
+            case TypeCode.UInt32:
+            case TypeCode.UInt64:
+                return true;
+            default:
+                return false;
         }
+    }
 
-        public static bool IsNullable(this Type type)
+    public static bool IsClrNumericCoercible(this Type type)
+    {
+        if (type == null || type.IsEnum)
         {
-            return type is { IsGenericType: true } && type.GetGenericTypeDefinition() == nullableType;
+            return false;
         }
 
-        public static bool IsNumeric(this Type type)
+        switch (Type.GetTypeCode(type))
         {
-            if (type == null || type.IsEnum)
-            {
+            case TypeCode.Decimal:
+            case TypeCode.Double:
+            case TypeCode.Int32:
+            case TypeCode.Int64:
+                return true;
+            default:
                 return false;
-            }
-
-            switch (Type.GetTypeCode(type))
-            {
-                case TypeCode.Byte:
-                case TypeCode.Decimal:
-                case TypeCode.Double:
-                case TypeCode.Int16:
-                case TypeCode.Int32:
-                case TypeCode.Int64:
-                case TypeCode.SByte:
-                case TypeCode.Single:
-                case TypeCode.UInt16:
-                case TypeCode.UInt32:
-                case TypeCode.UInt64:
-                    return true;
-                default:
-                    return false;
-            }
         }
+    }
 
-        public static bool IsClrNumericCoercible(this Type type)
+    public static object AsNumberOfType(this double d, TypeCode type)
+    {
+        switch (type)
         {
-            if (type == null || type.IsEnum)
-            {
-                return false;
-            }
-
-            switch (Type.GetTypeCode(type))
-            {
-                case TypeCode.Decimal:
-                case TypeCode.Double:
-                case TypeCode.Int32:
-                case TypeCode.Int64:
-                    return true;
-                default:
-                    return false;
-            }
+            case TypeCode.Decimal:
+                return (decimal) d;
+            case TypeCode.Double:
+                return d;
+            case TypeCode.Int32:
+                return (int) d;
+            case TypeCode.Int64:
+                return (long) d;
+            default:
+                ExceptionHelper.ThrowArgumentException("Cannot convert " + type);
+                return null;
         }
+    }
 
-        public static object AsNumberOfType(this double d, TypeCode type)
+    public static bool TryConvertViaTypeCoercion(
+        Type? memberType,
+        ValueCoercionType valueCoercionType,
+        JsValue value,
+        [NotNullWhen(true)] out object? converted)
+    {
+        if (value.IsInteger() && (memberType == typeof(int) || memberType == typeof(long)))
         {
-            switch (type)
-            {
-                case TypeCode.Decimal:
-                    return (decimal) d;
-                case TypeCode.Double:
-                    return d;
-                case TypeCode.Int32:
-                    return (int) d;
-                case TypeCode.Int64:
-                    return (long) d;
-                default:
-                    ExceptionHelper.ThrowArgumentException("Cannot convert " + type);
-                    return null;
-            }
+            // safe and doesn't require configuration
+            converted = value.AsInteger();
+            return true;
         }
 
-        public static bool TryConvertViaTypeCoercion(
-            Type? memberType,
-            ValueCoercionType valueCoercionType,
-            JsValue value,
-            [NotNullWhen(true)] out object? converted)
+        if (memberType == typeof(bool) && (valueCoercionType & ValueCoercionType.Boolean) != ValueCoercionType.None)
         {
-            if (value.IsInteger() && (memberType == typeof(int) || memberType == typeof(long)))
-            {
-                // safe and doesn't require configuration
-                converted = value.AsInteger();
-                return true;
-            }
-
-            if (memberType == typeof(bool) && (valueCoercionType & ValueCoercionType.Boolean) != ValueCoercionType.None)
-            {
-                converted = TypeConverter.ToBoolean(value);
-                return true;
-            }
-
-            if (memberType == typeof(string)
-                && !value.IsNullOrUndefined()
-                && (valueCoercionType & ValueCoercionType.String) != ValueCoercionType.None)
-            {
-                // we know how to print out correct string presentation for primitives
-                // that are non-null and non-undefined
-                converted = TypeConverter.ToString(value);
-                return true;
-            }
+            converted = TypeConverter.ToBoolean(value);
+            return true;
+        }
 
-            if (memberType is not null && memberType.IsClrNumericCoercible() && (valueCoercionType & ValueCoercionType.Number) != ValueCoercionType.None)
-            {
-                // we know how to print out correct string presentation for primitives
-                // that are non-null and non-undefined
-                var number = TypeConverter.ToNumber(value);
-                converted = number.AsNumberOfType(Type.GetTypeCode(memberType));
-                return true;
-            }
+        if (memberType == typeof(string)
+            && !value.IsNullOrUndefined()
+            && (valueCoercionType & ValueCoercionType.String) != ValueCoercionType.None)
+        {
+            // we know how to print out correct string presentation for primitives
+            // that are non-null and non-undefined
+            converted = TypeConverter.ToString(value);
+            return true;
+        }
 
-            converted = null;
-            return false;
+        if (memberType is not null && memberType.IsClrNumericCoercible() && (valueCoercionType & ValueCoercionType.Number) != ValueCoercionType.None)
+        {
+            // we know how to print out correct string presentation for primitives
+            // that are non-null and non-undefined
+            var number = TypeConverter.ToNumber(value);
+            converted = number.AsNumberOfType(Type.GetTypeCode(memberType));
+            return true;
         }
+
+        converted = null;
+        return false;
     }
 }

+ 244 - 245
Jint/HoistingScope.cs

@@ -1,330 +1,329 @@
 using Jint.Runtime.Modules;
 
-namespace Jint
+namespace Jint;
+
+internal sealed class HoistingScope
 {
-    internal sealed class HoistingScope
-    {
-        internal readonly List<FunctionDeclaration>? _functionDeclarations;
+    internal readonly List<FunctionDeclaration>? _functionDeclarations;
 
-        internal readonly List<VariableDeclaration>? _variablesDeclarations;
-        internal readonly List<Key>? _varNames;
+    internal readonly List<VariableDeclaration>? _variablesDeclarations;
+    internal readonly List<Key>? _varNames;
 
-        internal readonly List<Declaration>? _lexicalDeclarations;
-        internal readonly List<string>? _lexicalNames;
+    internal readonly List<Declaration>? _lexicalDeclarations;
+    internal readonly List<string>? _lexicalNames;
 
-        private HoistingScope(
-            List<FunctionDeclaration>? functionDeclarations,
-            List<Key>? varNames,
-            List<VariableDeclaration>? variableDeclarations,
-            List<Declaration>? lexicalDeclarations,
-            List<string>? lexicalNames)
-        {
-            _functionDeclarations = functionDeclarations;
-            _varNames = varNames;
-            _variablesDeclarations = variableDeclarations;
-            _lexicalDeclarations = lexicalDeclarations;
-            _lexicalNames = lexicalNames;
-        }
+    private HoistingScope(
+        List<FunctionDeclaration>? functionDeclarations,
+        List<Key>? varNames,
+        List<VariableDeclaration>? variableDeclarations,
+        List<Declaration>? lexicalDeclarations,
+        List<string>? lexicalNames)
+    {
+        _functionDeclarations = functionDeclarations;
+        _varNames = varNames;
+        _variablesDeclarations = variableDeclarations;
+        _lexicalDeclarations = lexicalDeclarations;
+        _lexicalNames = lexicalNames;
+    }
 
-        public static HoistingScope GetProgramLevelDeclarations(
-            Program script,
-            bool collectVarNames = false,
-            bool collectLexicalNames = false)
-        {
-            var treeWalker = new ScriptWalker(collectVarNames, collectLexicalNames);
-            treeWalker.Visit(script, null);
-
-            return new HoistingScope(
-                treeWalker._functions,
-                treeWalker._varNames,
-                treeWalker._variableDeclarations,
-                treeWalker._lexicalDeclarations,
-                treeWalker._lexicalNames);
-        }
+    public static HoistingScope GetProgramLevelDeclarations(
+        Program script,
+        bool collectVarNames = false,
+        bool collectLexicalNames = false)
+    {
+        var treeWalker = new ScriptWalker(collectVarNames, collectLexicalNames);
+        treeWalker.Visit(script, null);
+
+        return new HoistingScope(
+            treeWalker._functions,
+            treeWalker._varNames,
+            treeWalker._variableDeclarations,
+            treeWalker._lexicalDeclarations,
+            treeWalker._lexicalNames);
+    }
 
-        public static HoistingScope GetFunctionLevelDeclarations(bool strict, IFunction node)
-        {
-            var treeWalker = new ScriptWalker(collectVarNames: true, collectLexicalNames: true);
-            treeWalker.Visit(node.Body, null);
-
-            return new HoistingScope(
-                treeWalker._functions,
-                treeWalker._varNames,
-                treeWalker._variableDeclarations,
-                treeWalker._lexicalDeclarations,
-                treeWalker._lexicalNames);
-        }
+    public static HoistingScope GetFunctionLevelDeclarations(bool strict, IFunction node)
+    {
+        var treeWalker = new ScriptWalker(collectVarNames: true, collectLexicalNames: true);
+        treeWalker.Visit(node.Body, null);
+
+        return new HoistingScope(
+            treeWalker._functions,
+            treeWalker._varNames,
+            treeWalker._variableDeclarations,
+            treeWalker._lexicalDeclarations,
+            treeWalker._lexicalNames);
+    }
 
-        public static HoistingScope GetModuleLevelDeclarations(
-            AstModule module,
-            bool collectVarNames = false,
-            bool collectLexicalNames = false)
-        {
-            // modules area always strict
-            var treeWalker = new ScriptWalker(collectVarNames, collectLexicalNames);
-            treeWalker.Visit(module, null);
-            return new HoistingScope(
-                treeWalker._functions,
-                treeWalker._varNames,
-                treeWalker._variableDeclarations,
-                treeWalker._lexicalDeclarations,
-                treeWalker._lexicalNames);
-        }
+    public static HoistingScope GetModuleLevelDeclarations(
+        AstModule module,
+        bool collectVarNames = false,
+        bool collectLexicalNames = false)
+    {
+        // modules area always strict
+        var treeWalker = new ScriptWalker(collectVarNames, collectLexicalNames);
+        treeWalker.Visit(module, null);
+        return new HoistingScope(
+            treeWalker._functions,
+            treeWalker._varNames,
+            treeWalker._variableDeclarations,
+            treeWalker._lexicalDeclarations,
+            treeWalker._lexicalNames);
+    }
 
-        public static List<Declaration>? GetLexicalDeclarations(BlockStatement statement)
+    public static List<Declaration>? GetLexicalDeclarations(BlockStatement statement)
+    {
+        List<Declaration>? lexicalDeclarations = null;
+        ref readonly var statementListItems = ref statement.Body;
+        for (var i = 0; i < statementListItems.Count; i++)
         {
-            List<Declaration>? lexicalDeclarations = null;
-            ref readonly var statementListItems = ref statement.Body;
-            for (var i = 0; i < statementListItems.Count; i++)
+            var node = statementListItems[i];
+            if (node.Type != NodeType.VariableDeclaration && node.Type != NodeType.FunctionDeclaration && node.Type != NodeType.ClassDeclaration)
             {
-                var node = statementListItems[i];
-                if (node.Type != NodeType.VariableDeclaration && node.Type != NodeType.FunctionDeclaration && node.Type != NodeType.ClassDeclaration)
-                {
-                    continue;
-                }
-
-                if (node is VariableDeclaration { Kind: VariableDeclarationKind.Var })
-                {
-                    continue;
-                }
+                continue;
+            }
 
-                lexicalDeclarations ??= new List<Declaration>();
-                lexicalDeclarations.Add((Declaration)node);
+            if (node is VariableDeclaration { Kind: VariableDeclarationKind.Var })
+            {
+                continue;
             }
 
-            return lexicalDeclarations;
+            lexicalDeclarations ??= new List<Declaration>();
+            lexicalDeclarations.Add((Declaration)node);
         }
 
-        public static List<Declaration>? GetLexicalDeclarations(SwitchCase statement)
+        return lexicalDeclarations;
+    }
+
+    public static List<Declaration>? GetLexicalDeclarations(SwitchCase statement)
+    {
+        List<Declaration>? lexicalDeclarations = null;
+        ref readonly var statementListItems = ref statement.Consequent;
+        for (var i = 0; i < statementListItems.Count; i++)
         {
-            List<Declaration>? lexicalDeclarations = null;
-            ref readonly var statementListItems = ref statement.Consequent;
-            for (var i = 0; i < statementListItems.Count; i++)
+            var node = statementListItems[i];
+            if (node.Type != NodeType.VariableDeclaration)
             {
-                var node = statementListItems[i];
-                if (node.Type != NodeType.VariableDeclaration)
-                {
-                    continue;
-                }
-
-                var rootVariable = (VariableDeclaration)node;
-                if (rootVariable.Kind == VariableDeclarationKind.Var)
-                {
-                    continue;
-                }
+                continue;
+            }
 
-                lexicalDeclarations ??= new List<Declaration>();
-                lexicalDeclarations.Add(rootVariable);
+            var rootVariable = (VariableDeclaration)node;
+            if (rootVariable.Kind == VariableDeclarationKind.Var)
+            {
+                continue;
             }
 
-            return lexicalDeclarations;
+            lexicalDeclarations ??= new List<Declaration>();
+            lexicalDeclarations.Add(rootVariable);
         }
 
-        public static void GetImportsAndExports(
-            AstModule module,
-            out HashSet<ModuleRequest> requestedModules,
-            out List<ImportEntry>? importEntries,
-            out List<ExportEntry> localExportEntries,
-            out List<ExportEntry> indirectExportEntries,
-            out List<ExportEntry> starExportEntries)
-        {
-            var treeWalker = new ModuleWalker();
-            treeWalker.Visit(module);
+        return lexicalDeclarations;
+    }
 
-            importEntries = treeWalker._importEntries;
-            requestedModules = treeWalker._requestedModules ?? [];
-            var importedBoundNames = new HashSet<string?>(StringComparer.Ordinal);
+    public static void GetImportsAndExports(
+        AstModule module,
+        out HashSet<ModuleRequest> requestedModules,
+        out List<ImportEntry>? importEntries,
+        out List<ExportEntry> localExportEntries,
+        out List<ExportEntry> indirectExportEntries,
+        out List<ExportEntry> starExportEntries)
+    {
+        var treeWalker = new ModuleWalker();
+        treeWalker.Visit(module);
+
+        importEntries = treeWalker._importEntries;
+        requestedModules = treeWalker._requestedModules ?? [];
+        var importedBoundNames = new HashSet<string?>(StringComparer.Ordinal);
 
-            if (importEntries != null)
+        if (importEntries != null)
+        {
+            for (var i = 0; i < importEntries.Count; i++)
             {
-                for (var i = 0; i < importEntries.Count; i++)
-                {
-                    var ie = importEntries[i];
+                var ie = importEntries[i];
 
-                    if (ie.LocalName is not null)
-                    {
-                        importedBoundNames.Add(ie.LocalName);
-                    }
+                if (ie.LocalName is not null)
+                {
+                    importedBoundNames.Add(ie.LocalName);
                 }
             }
+        }
 
-            var exportEntries = treeWalker._exportEntries;
-            localExportEntries = new();
-            indirectExportEntries = new();
-            starExportEntries = new();
+        var exportEntries = treeWalker._exportEntries;
+        localExportEntries = new();
+        indirectExportEntries = new();
+        starExportEntries = new();
 
-            if (exportEntries != null)
+        if (exportEntries != null)
+        {
+            for (var i = 0; i < exportEntries.Count; i++)
             {
-                for (var i = 0; i < exportEntries.Count; i++)
-                {
-                    var ee = exportEntries[i];
+                var ee = exportEntries[i];
 
-                    if (ee.ModuleRequest is null)
+                if (ee.ModuleRequest is null)
+                {
+                    if (!importedBoundNames.Contains(ee.LocalName))
                     {
-                        if (!importedBoundNames.Contains(ee.LocalName))
-                        {
-                            localExportEntries.Add(ee);
-                        }
-                        else
+                        localExportEntries.Add(ee);
+                    }
+                    else
+                    {
+                        for (var j = 0; j < importEntries!.Count; j++)
                         {
-                            for (var j = 0; j < importEntries!.Count; j++)
+                            var ie = importEntries[j];
+                            if (string.Equals(ie.LocalName, ee.LocalName, StringComparison.Ordinal))
                             {
-                                var ie = importEntries[j];
-                                if (string.Equals(ie.LocalName, ee.LocalName, StringComparison.Ordinal))
+                                if (string.Equals(ie.ImportName, "*", StringComparison.Ordinal))
                                 {
-                                    if (string.Equals(ie.ImportName, "*", StringComparison.Ordinal))
-                                    {
-                                        localExportEntries.Add(ee);
-                                    }
-                                    else
-                                    {
-                                        indirectExportEntries.Add(new(ee.ExportName, ie.ModuleRequest, ie.ImportName, null));
-                                    }
-
-                                    break;
+                                    localExportEntries.Add(ee);
                                 }
+                                else
+                                {
+                                    indirectExportEntries.Add(new(ee.ExportName, ie.ModuleRequest, ie.ImportName, null));
+                                }
+
+                                break;
                             }
                         }
                     }
-                    else if (string.Equals(ee.ImportName, "*", StringComparison.Ordinal) && ee.ExportName is null)
-                    {
-                        starExportEntries.Add(ee);
-                    }
-                    else
-                    {
-                        indirectExportEntries.Add(ee);
-                    }
+                }
+                else if (string.Equals(ee.ImportName, "*", StringComparison.Ordinal) && ee.ExportName is null)
+                {
+                    starExportEntries.Add(ee);
+                }
+                else
+                {
+                    indirectExportEntries.Add(ee);
                 }
             }
         }
+    }
 
-        private sealed class ScriptWalker
-        {
-            internal List<FunctionDeclaration>? _functions;
+    private sealed class ScriptWalker
+    {
+        internal List<FunctionDeclaration>? _functions;
 
-            private readonly bool _collectVarNames;
-            internal List<VariableDeclaration>? _variableDeclarations;
-            internal List<Key>? _varNames;
+        private readonly bool _collectVarNames;
+        internal List<VariableDeclaration>? _variableDeclarations;
+        internal List<Key>? _varNames;
 
-            private readonly bool _collectLexicalNames;
-            internal List<Declaration>? _lexicalDeclarations;
-            internal List<string>? _lexicalNames;
+        private readonly bool _collectLexicalNames;
+        internal List<Declaration>? _lexicalDeclarations;
+        internal List<string>? _lexicalNames;
 
-            public ScriptWalker(bool collectVarNames, bool collectLexicalNames)
-            {
-                _collectVarNames = collectVarNames;
-                _collectLexicalNames = collectLexicalNames;
-            }
+        public ScriptWalker(bool collectVarNames, bool collectLexicalNames)
+        {
+            _collectVarNames = collectVarNames;
+            _collectLexicalNames = collectLexicalNames;
+        }
 
-            public void Visit(Node node, Node? parent)
+        public void Visit(Node node, Node? parent)
+        {
+            foreach (var childNode in node.ChildNodes)
             {
-                foreach (var childNode in node.ChildNodes)
+                var childType = childNode.Type;
+                if (childType == NodeType.VariableDeclaration)
                 {
-                    var childType = childNode.Type;
-                    if (childType == NodeType.VariableDeclaration)
+                    var variableDeclaration = (VariableDeclaration)childNode;
+                    if (variableDeclaration.Kind == VariableDeclarationKind.Var)
                     {
-                        var variableDeclaration = (VariableDeclaration)childNode;
-                        if (variableDeclaration.Kind == VariableDeclarationKind.Var)
+                        _variableDeclarations ??= new List<VariableDeclaration>();
+                        _variableDeclarations.Add(variableDeclaration);
+                        if (_collectVarNames)
                         {
-                            _variableDeclarations ??= new List<VariableDeclaration>();
-                            _variableDeclarations.Add(variableDeclaration);
-                            if (_collectVarNames)
+                            _varNames ??= new List<Key>();
+                            ref readonly var nodeList = ref variableDeclaration.Declarations;
+                            foreach (var declaration in nodeList)
                             {
-                                _varNames ??= new List<Key>();
-                                ref readonly var nodeList = ref variableDeclaration.Declarations;
-                                foreach (var declaration in nodeList)
+                                if (declaration.Id is Identifier identifier)
                                 {
-                                    if (declaration.Id is Identifier identifier)
-                                    {
-                                        _varNames.Add(identifier.Name);
-                                    }
+                                    _varNames.Add(identifier.Name);
                                 }
                             }
                         }
+                    }
 
-                        if (parent is null or AstModule && variableDeclaration.Kind != VariableDeclarationKind.Var)
+                    if (parent is null or AstModule && variableDeclaration.Kind != VariableDeclarationKind.Var)
+                    {
+                        _lexicalDeclarations ??= new List<Declaration>();
+                        _lexicalDeclarations.Add(variableDeclaration);
+                        if (_collectLexicalNames)
                         {
-                            _lexicalDeclarations ??= new List<Declaration>();
-                            _lexicalDeclarations.Add(variableDeclaration);
-                            if (_collectLexicalNames)
+                            _lexicalNames ??= new List<string>();
+                            ref readonly var nodeList = ref variableDeclaration.Declarations;
+                            foreach (var declaration in nodeList)
                             {
-                                _lexicalNames ??= new List<string>();
-                                ref readonly var nodeList = ref variableDeclaration.Declarations;
-                                foreach (var declaration in nodeList)
+                                if (declaration.Id is Identifier identifier)
                                 {
-                                    if (declaration.Id is Identifier identifier)
-                                    {
-                                        _lexicalNames.Add(identifier.Name);
-                                    }
+                                    _lexicalNames.Add(identifier.Name);
                                 }
                             }
                         }
                     }
-                    else if (childType == NodeType.FunctionDeclaration)
-                    {
-                        // function declarations are not hoisted if they are under block or case clauses
-                        if (parent is null || (node.Type != NodeType.BlockStatement && node.Type != NodeType.SwitchCase))
-                        {
-                            _functions ??= new List<FunctionDeclaration>();
-                            _functions.Add((FunctionDeclaration)childNode);
-                        }
-                    }
-                    else if (childType == NodeType.ClassDeclaration && parent is null or AstModule)
+                }
+                else if (childType == NodeType.FunctionDeclaration)
+                {
+                    // function declarations are not hoisted if they are under block or case clauses
+                    if (parent is null || (node.Type != NodeType.BlockStatement && node.Type != NodeType.SwitchCase))
                     {
-                        _lexicalDeclarations ??= new List<Declaration>();
-                        _lexicalDeclarations.Add((Declaration) childNode);
+                        _functions ??= new List<FunctionDeclaration>();
+                        _functions.Add((FunctionDeclaration)childNode);
                     }
+                }
+                else if (childType == NodeType.ClassDeclaration && parent is null or AstModule)
+                {
+                    _lexicalDeclarations ??= new List<Declaration>();
+                    _lexicalDeclarations.Add((Declaration) childNode);
+                }
 
-                    if (childType != NodeType.FunctionDeclaration
-                        && childType != NodeType.ArrowFunctionExpression
-                        && childType != NodeType.FunctionExpression
-                        && !childNode.ChildNodes.IsEmpty())
-                    {
-                        Visit(childNode, node);
-                    }
+                if (childType != NodeType.FunctionDeclaration
+                    && childType != NodeType.ArrowFunctionExpression
+                    && childType != NodeType.FunctionExpression
+                    && !childNode.ChildNodes.IsEmpty())
+                {
+                    Visit(childNode, node);
                 }
             }
         }
+    }
 
-        private sealed class ModuleRequestRecordComparer : IComparer<ModuleRequest>
+    private sealed class ModuleRequestRecordComparer : IComparer<ModuleRequest>
+    {
+        public int Compare(ModuleRequest x, ModuleRequest y)
         {
-            public int Compare(ModuleRequest x, ModuleRequest y)
-            {
-                return string.Compare(x.Specifier, y.Specifier, StringComparison.Ordinal);
-            }
+            return string.Compare(x.Specifier, y.Specifier, StringComparison.Ordinal);
         }
+    }
 
-        private sealed class ModuleWalker
-        {
-            internal List<ImportEntry>? _importEntries;
-            internal List<ExportEntry>? _exportEntries;
-            internal HashSet<ModuleRequest>? _requestedModules;
+    private sealed class ModuleWalker
+    {
+        internal List<ImportEntry>? _importEntries;
+        internal List<ExportEntry>? _exportEntries;
+        internal HashSet<ModuleRequest>? _requestedModules;
 
-            internal void Visit(Node node)
+        internal void Visit(Node node)
+        {
+            foreach (var childNode in node.ChildNodes)
             {
-                foreach (var childNode in node.ChildNodes)
+                if (childNode.Type == NodeType.ImportDeclaration)
                 {
-                    if (childNode.Type == NodeType.ImportDeclaration)
-                    {
-                        _importEntries ??= [];
-                        _requestedModules ??= [];
-                        var import = (ImportDeclaration) childNode;
-                        import.GetImportEntries(_importEntries, _requestedModules);
-                    }
-                    else if (childNode.Type is NodeType.ExportAllDeclaration or NodeType.ExportDefaultDeclaration or NodeType.ExportNamedDeclaration)
-                    {
-                        _exportEntries ??= [];
-                        _requestedModules ??= [];
-                        var export = (ExportDeclaration) childNode;
-                        export.GetExportEntries(_exportEntries, _requestedModules);
-                    }
+                    _importEntries ??= [];
+                    _requestedModules ??= [];
+                    var import = (ImportDeclaration) childNode;
+                    import.GetImportEntries(_importEntries, _requestedModules);
+                }
+                else if (childNode.Type is NodeType.ExportAllDeclaration or NodeType.ExportDefaultDeclaration or NodeType.ExportNamedDeclaration)
+                {
+                    _exportEntries ??= [];
+                    _requestedModules ??= [];
+                    var export = (ExportDeclaration) childNode;
+                    export.GetExportEntries(_exportEntries, _requestedModules);
+                }
 
-                    if (!childNode.ChildNodes.IsEmpty())
-                    {
-                        Visit(childNode);
-                    }
+                if (!childNode.ChildNodes.IsEmpty())
+                {
+                    Visit(childNode);
                 }
             }
         }
     }
-}
+}

+ 48 - 49
Jint/Key.cs

@@ -2,55 +2,54 @@ using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using Jint.Extensions;
 
-namespace Jint
+namespace Jint;
+
+/// <summary>
+/// Represents a key that Jint uses with pre-calculated hash code
+/// as runtime does a lot of repetitive dictionary lookups.
+/// </summary>
+[DebuggerDisplay("{" + nameof(Name) + "}")]
+internal readonly struct Key : IEquatable<Key>
 {
-    /// <summary>
-    /// Represents a key that Jint uses with pre-calculated hash code
-    /// as runtime does a lot of repetitive dictionary lookups.
-    /// </summary>
-    [DebuggerDisplay("{" + nameof(Name) + "}")]
-    internal readonly struct Key : IEquatable<Key>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private Key(string name)
     {
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private Key(string name)
-        {
-            Name = name;
-            HashCode = Hash.GetFNVHashCode(name);
-        }
-
-        internal readonly string Name;
-        internal readonly int HashCode;
-
-        [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)]
-        public static bool operator ==(in Key a, in Key b)
-        {
-            return a.HashCode == b.HashCode && string.Equals(a.Name, b.Name, StringComparison.Ordinal);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool operator !=(in Key a, in Key b)
-        {
-            return a.HashCode != b.HashCode || !string.Equals(a.Name, b.Name, StringComparison.Ordinal);
-        }
-
-        public bool Equals(Key other)
-        {
-            return HashCode == other.HashCode && string.Equals(Name, other.Name, StringComparison.Ordinal);
-        }
-
-        public override bool Equals(object? obj)
-        {
-            return obj is Key other && Equals(other);
-        }
-
-        public override int GetHashCode() => HashCode;
-
-        public override string ToString() => Name;
+        Name = name;
+        HashCode = Hash.GetFNVHashCode(name);
     }
-}
+
+    internal readonly string Name;
+    internal readonly int HashCode;
+
+    [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)]
+    public static bool operator ==(in Key a, in Key b)
+    {
+        return a.HashCode == b.HashCode && string.Equals(a.Name, b.Name, StringComparison.Ordinal);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public static bool operator !=(in Key a, in Key b)
+    {
+        return a.HashCode != b.HashCode || !string.Equals(a.Name, b.Name, StringComparison.Ordinal);
+    }
+
+    public bool Equals(Key other)
+    {
+        return HashCode == other.HashCode && string.Equals(Name, other.Name, StringComparison.Ordinal);
+    }
+
+    public override bool Equals(object? obj)
+    {
+        return obj is Key other && Equals(other);
+    }
+
+    public override int GetHashCode() => HashCode;
+
+    public override string ToString() => Name;
+}

+ 344 - 345
Jint/Native/Array/ArrayConstructor.cs

@@ -10,463 +10,462 @@ using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
-namespace Jint.Native.Array
+namespace Jint.Native.Array;
+
+public sealed class ArrayConstructor : Constructor
 {
-    public sealed class ArrayConstructor : Constructor
+    private static readonly JsString _functionName = new JsString("Array");
+
+    internal ArrayConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype)
+        : base(engine, realm, _functionName)
     {
-        private static readonly JsString _functionName = new JsString("Array");
+        _prototype = functionPrototype;
+        PrototypeObject = new ArrayPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(1, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
 
-        internal ArrayConstructor(
-            Engine engine,
-            Realm realm,
-            FunctionPrototype functionPrototype,
-            ObjectPrototype objectPrototype)
-            : base(engine, realm, _functionName)
-        {
-            _prototype = functionPrototype;
-            PrototypeObject = new ArrayPrototype(engine, realm, this, objectPrototype);
-            _length = new PropertyDescriptor(1, PropertyFlag.Configurable);
-            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
-        }
+    public ArrayPrototype PrototypeObject { get; }
 
-        public ArrayPrototype PrototypeObject { get; }
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(3, checkExistingKeys: false)
+        {
+            ["from"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunction(Engine, "from", From, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable)),
+            ["isArray"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunction(Engine, "isArray", IsArray, 1), PropertyFlag.NonEnumerable)),
+            ["of"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunction(Engine, "of", Of, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable))
+        };
+        SetProperties(properties);
 
-        protected override void Initialize()
+        var symbols = new SymbolDictionary(1)
         {
-            var properties = new PropertyDictionary(3, checkExistingKeys: false)
-            {
-                ["from"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunction(Engine, "from", From, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable)),
-                ["isArray"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunction(Engine, "isArray", IsArray, 1), PropertyFlag.NonEnumerable)),
-                ["of"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunction(Engine, "of", Of, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable))
-            };
-            SetProperties(properties);
+            [GlobalSymbolRegistry.Species] = new GetSetPropertyDescriptor(get: new ClrFunction(Engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable), set: Undefined,PropertyFlag.Configurable),
+        };
+        SetSymbols(symbols);
+    }
 
-            var symbols = new SymbolDictionary(1)
-            {
-                [GlobalSymbolRegistry.Species] = new GetSetPropertyDescriptor(get: new ClrFunction(Engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable), set: Undefined,PropertyFlag.Configurable),
-            };
-            SetSymbols(symbols);
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-array.from
+    /// </summary>
+    private JsValue From(JsValue thisObject, JsValue[] arguments)
+    {
+        var items = arguments.At(0);
+        var mapFunction = arguments.At(1);
+        var callable = !mapFunction.IsUndefined() ? GetCallable(mapFunction) : null;
+        var thisArg = arguments.At(2);
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-array.from
-        /// </summary>
-        private JsValue From(JsValue thisObject, JsValue[] arguments)
+        if (items.IsNullOrUndefined())
         {
-            var items = arguments.At(0);
-            var mapFunction = arguments.At(1);
-            var callable = !mapFunction.IsUndefined() ? GetCallable(mapFunction) : null;
-            var thisArg = arguments.At(2);
-
-            if (items.IsNullOrUndefined())
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Cannot convert undefined or null to object");
-            }
+            ExceptionHelper.ThrowTypeError(_realm, "Cannot convert undefined or null to object");
+        }
 
-            var usingIterator = GetMethod(_realm, items, GlobalSymbolRegistry.Iterator);
-            if (usingIterator is not null)
+        var usingIterator = GetMethod(_realm, items, GlobalSymbolRegistry.Iterator);
+        if (usingIterator is not null)
+        {
+            ObjectInstance instance;
+            if (!ReferenceEquals(this, thisObject) && thisObject is IConstructor constructor)
             {
-                ObjectInstance instance;
-                if (!ReferenceEquals(this, thisObject) && thisObject is IConstructor constructor)
-                {
-                    instance = constructor.Construct(System.Array.Empty<JsValue>(), thisObject);
-                }
-                else
-                {
-                    instance = ArrayCreate(0);
-                }
-
-                var iterator = items.GetIterator(_realm, method: usingIterator);
-                var protocol = new ArrayProtocol(_engine, thisArg, instance, iterator, callable);
-                protocol.Execute();
-                return instance;
+                instance = constructor.Construct(System.Array.Empty<JsValue>(), thisObject);
             }
-
-            if (items is IObjectWrapper { Target: IEnumerable enumerable })
+            else
             {
-                return ConstructArrayFromIEnumerable(enumerable);
+                instance = ArrayCreate(0);
             }
 
-            var source = ArrayOperations.For(_realm, items, forWrite: false);
-            return ConstructArrayFromArrayLike(thisObject, source, callable, thisArg);
+            var iterator = items.GetIterator(_realm, method: usingIterator);
+            var protocol = new ArrayProtocol(_engine, thisArg, instance, iterator, callable);
+            protocol.Execute();
+            return instance;
         }
 
-        private ObjectInstance ConstructArrayFromArrayLike(
-            JsValue thisObj,
-            ArrayOperations source,
-            ICallable? callable,
-            JsValue thisArg)
+        if (items is IObjectWrapper { Target: IEnumerable enumerable })
         {
-            var length = source.GetLength();
-
-            ObjectInstance a;
-            if (!ReferenceEquals(thisObj, this) && thisObj is IConstructor constructor)
-            {
-                var argumentsList = new JsValue[] { length };
-                a = Construct(constructor, argumentsList);
-            }
-            else
-            {
-                a = ArrayCreate(length);
-            }
+            return ConstructArrayFromIEnumerable(enumerable);
+        }
 
-            var args = callable is not null
-                ? _engine._jsValueArrayPool.RentArray(2)
-                : null;
+        var source = ArrayOperations.For(_realm, items, forWrite: false);
+        return ConstructArrayFromArrayLike(thisObject, source, callable, thisArg);
+    }
 
-            var target = ArrayOperations.For(a, forWrite: true);
-            uint n = 0;
-            for (uint i = 0; i < length; i++)
-            {
-                var value = source.Get(i);
-                if (callable is not null)
-                {
-                    args![0] = value;
-                    args[1] = i;
-                    value = callable.Call(thisArg, args);
+    private ObjectInstance ConstructArrayFromArrayLike(
+        JsValue thisObj,
+        ArrayOperations source,
+        ICallable? callable,
+        JsValue thisArg)
+    {
+        var length = source.GetLength();
 
-                    // function can alter data
-                    length = source.GetLength();
-                }
+        ObjectInstance a;
+        if (!ReferenceEquals(thisObj, this) && thisObj is IConstructor constructor)
+        {
+            var argumentsList = new JsValue[] { length };
+            a = Construct(constructor, argumentsList);
+        }
+        else
+        {
+            a = ArrayCreate(length);
+        }
 
-                target.CreateDataPropertyOrThrow(i, value);
-                n++;
-            }
+        var args = callable is not null
+            ? _engine._jsValueArrayPool.RentArray(2)
+            : null;
 
+        var target = ArrayOperations.For(a, forWrite: true);
+        uint n = 0;
+        for (uint i = 0; i < length; i++)
+        {
+            var value = source.Get(i);
             if (callable is not null)
             {
-                _engine._jsValueArrayPool.ReturnArray(args!);
+                args![0] = value;
+                args[1] = i;
+                value = callable.Call(thisArg, args);
+
+                // function can alter data
+                length = source.GetLength();
             }
 
-            target.SetLength(length);
-            return a;
+            target.CreateDataPropertyOrThrow(i, value);
+            n++;
         }
 
-        private sealed class ArrayProtocol : IteratorProtocol
+        if (callable is not null)
         {
-            private readonly JsValue _thisArg;
-            private readonly ArrayOperations _instance;
-            private readonly ICallable? _callable;
-            private long _index = -1;
-
-            public ArrayProtocol(
-                Engine engine,
-                JsValue thisArg,
-                ObjectInstance instance,
-                IteratorInstance iterator,
-                ICallable? callable) : base(engine, iterator, 2)
-            {
-                _thisArg = thisArg;
-                _instance = ArrayOperations.For(instance, forWrite: true);
-                _callable = callable;
-            }
+            _engine._jsValueArrayPool.ReturnArray(args!);
+        }
 
-            protected override void ProcessItem(JsValue[] arguments, JsValue currentValue)
-            {
-                _index++;
-                JsValue jsValue;
-                if (_callable is not null)
-                {
-                    arguments[0] = currentValue;
-                    arguments[1] = _index;
-                    jsValue = _callable.Call(_thisArg, arguments);
-                }
-                else
-                {
-                    jsValue = currentValue;
-                }
+        target.SetLength(length);
+        return a;
+    }
 
-                _instance.CreateDataPropertyOrThrow((ulong) _index, jsValue);
-            }
+    private sealed class ArrayProtocol : IteratorProtocol
+    {
+        private readonly JsValue _thisArg;
+        private readonly ArrayOperations _instance;
+        private readonly ICallable? _callable;
+        private long _index = -1;
 
-            protected override void IterationEnd()
-            {
-                _instance.SetLength((ulong) (_index + 1));
-            }
+        public ArrayProtocol(
+            Engine engine,
+            JsValue thisArg,
+            ObjectInstance instance,
+            IteratorInstance iterator,
+            ICallable? callable) : base(engine, iterator, 2)
+        {
+            _thisArg = thisArg;
+            _instance = ArrayOperations.For(instance, forWrite: true);
+            _callable = callable;
         }
 
-        private JsValue Of(JsValue thisObject, JsValue[] arguments)
+        protected override void ProcessItem(JsValue[] arguments, JsValue currentValue)
         {
-            var len = arguments.Length;
-            ObjectInstance a;
-            if (thisObject.IsConstructor)
+            _index++;
+            JsValue jsValue;
+            if (_callable is not null)
             {
-                a = ((IConstructor) thisObject).Construct(new JsValue[] { len }, thisObject);
+                arguments[0] = currentValue;
+                arguments[1] = _index;
+                jsValue = _callable.Call(_thisArg, arguments);
             }
             else
             {
-                a = _realm.Intrinsics.Array.Construct(len);
-            }
-
-            if (a is JsArray ai)
-            {
-                // faster for real arrays
-                for (uint k = 0; k < arguments.Length; k++)
-                {
-                    var kValue = arguments[k];
-                    ai.SetIndexValue(k, kValue, updateLength: k == arguments.Length - 1);
-                }
-            }
-            else
-            {
-                // slower version
-                for (uint k = 0; k < arguments.Length; k++)
-                {
-                    var kValue = arguments[k];
-                    var key = JsString.Create(k);
-                    a.CreateDataPropertyOrThrow(key, kValue);
-                }
-
-                a.Set(CommonProperties.Length, len, true);
+                jsValue = currentValue;
             }
 
-            return a;
+            _instance.CreateDataPropertyOrThrow((ulong) _index, jsValue);
         }
 
-        private static JsValue Species(JsValue thisObject, JsValue[] arguments)
+        protected override void IterationEnd()
         {
-            return thisObject;
+            _instance.SetLength((ulong) (_index + 1));
         }
+    }
 
-        private static JsValue IsArray(JsValue thisObject, JsValue[] arguments)
+    private JsValue Of(JsValue thisObject, JsValue[] arguments)
+    {
+        var len = arguments.Length;
+        ObjectInstance a;
+        if (thisObject.IsConstructor)
         {
-            var o = arguments.At(0);
-
-            return IsArray(o);
+            a = ((IConstructor) thisObject).Construct(new JsValue[] { len }, thisObject);
+        }
+        else
+        {
+            a = _realm.Intrinsics.Array.Construct(len);
         }
 
-        private static JsValue IsArray(JsValue o)
+        if (a is JsArray ai)
         {
-            if (!(o is ObjectInstance oi))
+            // faster for real arrays
+            for (uint k = 0; k < arguments.Length; k++)
             {
-                return JsBoolean.False;
+                var kValue = arguments[k];
+                ai.SetIndexValue(k, kValue, updateLength: k == arguments.Length - 1);
             }
-
-            return oi.IsArray();
         }
-
-        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+        else
         {
-            return Construct(arguments, thisObject);
-        }
+            // slower version
+            for (uint k = 0; k < arguments.Length; k++)
+            {
+                var kValue = arguments[k];
+                var key = JsString.Create(k);
+                a.CreateDataPropertyOrThrow(key, kValue);
+            }
 
-        public JsArray Construct(JsValue[] arguments)
-        {
-            return (JsArray) Construct(arguments, this);
+            a.Set(CommonProperties.Length, len, true);
         }
 
-        public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
-        {
-            if (newTarget.IsUndefined())
-            {
-                newTarget = this;
-            }
+        return a;
+    }
 
-            var proto = _realm.Intrinsics.Function.GetPrototypeFromConstructor(
-                newTarget,
-                static intrinsics => intrinsics.Array.PrototypeObject);
+    private static JsValue Species(JsValue thisObject, JsValue[] arguments)
+    {
+        return thisObject;
+    }
 
-            // check if we can figure out good size
-            var capacity = arguments.Length > 0 ? (ulong) arguments.Length : 0;
-            if (arguments.Length == 1 && arguments[0].IsNumber())
-            {
-                var number = ((JsNumber) arguments[0])._value;
-                ValidateLength(number);
-                capacity = (ulong) number;
-            }
-            return Construct(arguments, capacity, proto);
-        }
+    private static JsValue IsArray(JsValue thisObject, JsValue[] arguments)
+    {
+        var o = arguments.At(0);
+
+        return IsArray(o);
+    }
 
-        public JsArray Construct(int capacity)
+    private static JsValue IsArray(JsValue o)
+    {
+        if (!(o is ObjectInstance oi))
         {
-            return Construct(System.Array.Empty<JsValue>(), (uint) capacity);
+            return JsBoolean.False;
         }
 
-        public JsArray Construct(uint capacity)
+        return oi.IsArray();
+    }
+
+    protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+    {
+        return Construct(arguments, thisObject);
+    }
+
+    public JsArray Construct(JsValue[] arguments)
+    {
+        return (JsArray) Construct(arguments, this);
+    }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        if (newTarget.IsUndefined())
         {
-            return Construct(System.Array.Empty<JsValue>(), capacity);
+            newTarget = this;
         }
 
-        public JsArray Construct(JsValue[] arguments, uint capacity)
+        var proto = _realm.Intrinsics.Function.GetPrototypeFromConstructor(
+            newTarget,
+            static intrinsics => intrinsics.Array.PrototypeObject);
+
+        // check if we can figure out good size
+        var capacity = arguments.Length > 0 ? (ulong) arguments.Length : 0;
+        if (arguments.Length == 1 && arguments[0].IsNumber())
         {
-            return Construct(arguments, capacity, PrototypeObject);
+            var number = ((JsNumber) arguments[0])._value;
+            ValidateLength(number);
+            capacity = (ulong) number;
         }
+        return Construct(arguments, capacity, proto);
+    }
 
-        private JsArray Construct(JsValue[] arguments, ulong capacity, ObjectInstance prototypeObject)
+    public JsArray Construct(int capacity)
+    {
+        return Construct(System.Array.Empty<JsValue>(), (uint) capacity);
+    }
+
+    public JsArray Construct(uint capacity)
+    {
+        return Construct(System.Array.Empty<JsValue>(), capacity);
+    }
+
+    public JsArray Construct(JsValue[] arguments, uint capacity)
+    {
+        return Construct(arguments, capacity, PrototypeObject);
+    }
+
+    private JsArray Construct(JsValue[] arguments, ulong capacity, ObjectInstance prototypeObject)
+    {
+        JsArray instance;
+        if (arguments.Length == 1)
         {
-            JsArray instance;
-            if (arguments.Length == 1)
-            {
-                switch (arguments[0])
-                {
-                    case JsNumber number:
-                        ValidateLength(number._value);
-                        instance = ArrayCreate((ulong) number._value, prototypeObject);
-                        break;
-                    case IObjectWrapper objectWrapper:
-                        instance = objectWrapper.Target is IEnumerable enumerable
-                            ? ConstructArrayFromIEnumerable(enumerable)
-                            : ArrayCreate(0, prototypeObject);
-                        break;
-                    case JsArray array:
-                        // direct copy
-                        instance = (JsArray) ConstructArrayFromArrayLike(Undefined, ArrayOperations.For(array, forWrite: false), callable: null, this);
-                        break;
-                    default:
-                        instance = ArrayCreate(capacity, prototypeObject);
-                        instance._length!._value = JsNumber.PositiveZero;
-                        instance.Push(arguments);
-                        break;
-                }
-            }
-            else
-            {
-                instance = ArrayCreate((ulong) arguments.Length, prototypeObject);
-                instance._length!._value = JsNumber.PositiveZero;
-                if (arguments.Length > 0)
-                {
+            switch (arguments[0])
+            {
+                case JsNumber number:
+                    ValidateLength(number._value);
+                    instance = ArrayCreate((ulong) number._value, prototypeObject);
+                    break;
+                case IObjectWrapper objectWrapper:
+                    instance = objectWrapper.Target is IEnumerable enumerable
+                        ? ConstructArrayFromIEnumerable(enumerable)
+                        : ArrayCreate(0, prototypeObject);
+                    break;
+                case JsArray array:
+                    // direct copy
+                    instance = (JsArray) ConstructArrayFromArrayLike(Undefined, ArrayOperations.For(array, forWrite: false), callable: null, this);
+                    break;
+                default:
+                    instance = ArrayCreate(capacity, prototypeObject);
+                    instance._length!._value = JsNumber.PositiveZero;
                     instance.Push(arguments);
-                }
+                    break;
             }
-
-            return instance;
         }
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-arraycreate
-        /// </summary>
-        internal JsArray ArrayCreate(ulong length, ObjectInstance? proto = null)
+        else
         {
-            if (length > ArrayOperations.MaxArrayLength)
+            instance = ArrayCreate((ulong) arguments.Length, prototypeObject);
+            instance._length!._value = JsNumber.PositiveZero;
+            if (arguments.Length > 0)
             {
-                ExceptionHelper.ThrowRangeError(_realm, "Invalid array length " + length);
+                instance.Push(arguments);
             }
+        }
 
-            proto ??= PrototypeObject;
-            var instance = new JsArray(Engine, (uint) length, (uint) length)
-            {
-                _prototype = proto
-            };
-            return instance;
+        return instance;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-arraycreate
+    /// </summary>
+    internal JsArray ArrayCreate(ulong length, ObjectInstance? proto = null)
+    {
+        if (length > ArrayOperations.MaxArrayLength)
+        {
+            ExceptionHelper.ThrowRangeError(_realm, "Invalid array length " + length);
         }
 
-        private JsArray ConstructArrayFromIEnumerable(IEnumerable enumerable)
+        proto ??= PrototypeObject;
+        var instance = new JsArray(Engine, (uint) length, (uint) length)
         {
-            var jsArray = Construct(Arguments.Empty);
-            var tempArray = _engine._jsValueArrayPool.RentArray(1);
-            foreach (var item in enumerable)
-            {
-                var jsItem = FromObject(Engine, item);
-                tempArray[0] = jsItem;
-                _realm.Intrinsics.Array.PrototypeObject.Push(jsArray, tempArray);
-            }
+            _prototype = proto
+        };
+        return instance;
+    }
 
-            _engine._jsValueArrayPool.ReturnArray(tempArray);
-            return jsArray;
+    private JsArray ConstructArrayFromIEnumerable(IEnumerable enumerable)
+    {
+        var jsArray = Construct(Arguments.Empty);
+        var tempArray = _engine._jsValueArrayPool.RentArray(1);
+        foreach (var item in enumerable)
+        {
+            var jsItem = FromObject(Engine, item);
+            tempArray[0] = jsItem;
+            _realm.Intrinsics.Array.PrototypeObject.Push(jsArray, tempArray);
         }
 
-        public JsArray ConstructFast(JsValue[] contents)
+        _engine._jsValueArrayPool.ReturnArray(tempArray);
+        return jsArray;
+    }
+
+    public JsArray ConstructFast(JsValue[] contents)
+    {
+        var instance = ArrayCreate((ulong) contents.Length);
+        for (var i = 0; i < contents.Length; i++)
         {
-            var instance = ArrayCreate((ulong) contents.Length);
-            for (var i = 0; i < contents.Length; i++)
-            {
-                instance.SetIndexValue((uint) i, contents[i], updateLength: false);
-            }
-            return instance;
+            instance.SetIndexValue((uint) i, contents[i], updateLength: false);
         }
+        return instance;
+    }
 
-        internal JsArray ConstructFast(List<JsValue> contents)
+    internal JsArray ConstructFast(List<JsValue> contents)
+    {
+        var instance = ArrayCreate((ulong) contents.Count);
+        for (var i = 0; i < contents.Count; i++)
         {
-            var instance = ArrayCreate((ulong) contents.Count);
-            for (var i = 0; i < contents.Count; i++)
-            {
-                instance.SetIndexValue((uint) i, contents[i], updateLength: false);
-            }
-            return instance;
+            instance.SetIndexValue((uint) i, contents[i], updateLength: false);
         }
+        return instance;
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-arrayspeciescreate
-        /// </summary>
-        internal ObjectInstance ArraySpeciesCreate(ObjectInstance originalArray, ulong length)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-arrayspeciescreate
+    /// </summary>
+    internal ObjectInstance ArraySpeciesCreate(ObjectInstance originalArray, ulong length)
+    {
+        var isArray = originalArray.IsArray();
+        if (!isArray)
         {
-            var isArray = originalArray.IsArray();
-            if (!isArray)
-            {
-                return ArrayCreate(length);
-            }
+            return ArrayCreate(length);
+        }
 
-            var c = originalArray.Get(CommonProperties.Constructor);
+        var c = originalArray.Get(CommonProperties.Constructor);
 
-            if (c.IsConstructor)
-            {
-                var thisRealm = _engine.ExecutionContext.Realm;
-                var realmC = GetFunctionRealm(c);
-                if (!ReferenceEquals(thisRealm, realmC))
-                {
-                    if (ReferenceEquals(c, realmC.Intrinsics.Array))
-                    {
-                        c = Undefined;
-                    }
-                }
-            }
-
-            if (c.IsObject())
+        if (c.IsConstructor)
+        {
+            var thisRealm = _engine.ExecutionContext.Realm;
+            var realmC = GetFunctionRealm(c);
+            if (!ReferenceEquals(thisRealm, realmC))
             {
-                c = c.Get(GlobalSymbolRegistry.Species);
-                if (c.IsNull())
+                if (ReferenceEquals(c, realmC.Intrinsics.Array))
                 {
                     c = Undefined;
                 }
             }
+        }
 
-            if (c.IsUndefined())
-            {
-                return ArrayCreate(length);
-            }
-
-            if (!c.IsConstructor)
+        if (c.IsObject())
+        {
+            c = c.Get(GlobalSymbolRegistry.Species);
+            if (c.IsNull())
             {
-                ExceptionHelper.ThrowTypeError(_realm, $"{c} is not a constructor");
+                c = Undefined;
             }
-
-            return ((IConstructor) c).Construct(new JsValue[] { JsNumber.Create(length) }, c);
         }
 
-        internal JsArray CreateArrayFromList<T>(List<T> values) where T : JsValue
+        if (c.IsUndefined())
         {
-            var jsArray = ArrayCreate((uint) values.Count);
-            var index = 0;
-            for (; index < values.Count; index++)
-            {
-                var item = values[index];
-                jsArray.SetIndexValue((uint) index, item, false);
-            }
+            return ArrayCreate(length);
+        }
 
-            jsArray.SetLength((uint) index);
-            return jsArray;
+        if (!c.IsConstructor)
+        {
+            ExceptionHelper.ThrowTypeError(_realm, $"{c} is not a constructor");
         }
 
-        internal JsArray CreateArrayFromList<T>(T[] values) where T : JsValue
+        return ((IConstructor) c).Construct(new JsValue[] { JsNumber.Create(length) }, c);
+    }
+
+    internal JsArray CreateArrayFromList<T>(List<T> values) where T : JsValue
+    {
+        var jsArray = ArrayCreate((uint) values.Count);
+        var index = 0;
+        for (; index < values.Count; index++)
         {
-            var jsArray = ArrayCreate((uint) values.Length);
-            var index = 0;
-            for (; index < values.Length; index++)
-            {
-                var item = values[index];
-                jsArray.SetIndexValue((uint) index, item, false);
-            }
+            var item = values[index];
+            jsArray.SetIndexValue((uint) index, item, false);
+        }
+
+        jsArray.SetLength((uint) index);
+        return jsArray;
+    }
 
-            jsArray.SetLength((uint) index);
-            return jsArray;
+    internal JsArray CreateArrayFromList<T>(T[] values) where T : JsValue
+    {
+        var jsArray = ArrayCreate((uint) values.Length);
+        var index = 0;
+        for (; index < values.Length; index++)
+        {
+            var item = values[index];
+            jsArray.SetIndexValue((uint) index, item, false);
         }
 
-        private void ValidateLength(double length)
+        jsArray.SetLength((uint) index);
+        return jsArray;
+    }
+
+    private void ValidateLength(double length)
+    {
+        if (length < 0 || length > ArrayOperations.MaxArrayLikeLength || ((long) length) != length)
         {
-            if (length < 0 || length > ArrayOperations.MaxArrayLikeLength || ((long) length) != length)
-            {
-                ExceptionHelper.ThrowRangeError(_realm, "Invalid array length");
-            }
+            ExceptionHelper.ThrowRangeError(_realm, "Invalid array length");
         }
     }
 }

+ 979 - 980
Jint/Native/Array/ArrayInstance.cs

@@ -6,1372 +6,1371 @@ using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 
-namespace Jint.Native.Array
+namespace Jint.Native.Array;
+
+public class ArrayInstance : ObjectInstance, IEnumerable<JsValue>
 {
-    public class ArrayInstance : ObjectInstance, IEnumerable<JsValue>
-    {
-        internal PropertyDescriptor? _length;
+    internal PropertyDescriptor? _length;
+
+    private const int MaxDenseArrayLength = 10_000_000;
+
+    // we have dense and sparse, we usually can start with dense and fall back to sparse when necessary
+    // when we have plain JsValues, _denseValues is used - if any operation occurs which requires setting more property flags
+    // we convert to _sparse and _denseValues is set to null - it will be a slow array
+    internal JsValue?[]? _dense;
 
-        private const int MaxDenseArrayLength = 10_000_000;
+    private Dictionary<uint, PropertyDescriptor?>? _sparse;
 
-        // we have dense and sparse, we usually can start with dense and fall back to sparse when necessary
-        // when we have plain JsValues, _denseValues is used - if any operation occurs which requires setting more property flags
-        // we convert to _sparse and _denseValues is set to null - it will be a slow array
-        internal JsValue?[]? _dense;
+    private ObjectChangeFlags _objectChangeFlags;
 
-        private Dictionary<uint, PropertyDescriptor?>? _sparse;
+    private ArrayConstructor? _constructor;
 
-        private ObjectChangeFlags _objectChangeFlags;
+    private protected ArrayInstance(Engine engine, InternalTypes type) : base(engine, type: type)
+    {
+        _dense = System.Array.Empty<JsValue?>();
+    }
 
-        private ArrayConstructor? _constructor;
+    private protected ArrayInstance(Engine engine, uint capacity = 0, uint length = 0) : base(engine, type: InternalTypes.Object | InternalTypes.Array)
+    {
+        InitializePrototypeAndValidateCapacity(engine, capacity);
 
-        private protected ArrayInstance(Engine engine, InternalTypes type) : base(engine, type: type)
+        if (capacity < MaxDenseArrayLength)
         {
-            _dense = System.Array.Empty<JsValue?>();
+            _dense = capacity > 0 ? new JsValue?[capacity] : System.Array.Empty<JsValue?>();
         }
-
-        private protected ArrayInstance(Engine engine, uint capacity = 0, uint length = 0) : base(engine, type: InternalTypes.Object | InternalTypes.Array)
+        else
         {
-            InitializePrototypeAndValidateCapacity(engine, capacity);
+            _sparse = new Dictionary<uint, PropertyDescriptor?>(1024);
+        }
 
-            if (capacity < MaxDenseArrayLength)
-            {
-                _dense = capacity > 0 ? new JsValue?[capacity] : System.Array.Empty<JsValue?>();
-            }
-            else
-            {
-                _sparse = new Dictionary<uint, PropertyDescriptor?>(1024);
-            }
+        _length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable);
+    }
 
-            _length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable);
-        }
+    private protected ArrayInstance(Engine engine, JsValue[] items) : base(engine, type: InternalTypes.Object | InternalTypes.Array)
+    {
+        InitializePrototypeAndValidateCapacity(engine, capacity: 0);
 
-        private protected ArrayInstance(Engine engine, JsValue[] items) : base(engine, type: InternalTypes.Object | InternalTypes.Array)
-        {
-            InitializePrototypeAndValidateCapacity(engine, capacity: 0);
+        _dense = items;
+        _length = new PropertyDescriptor(items.Length, PropertyFlag.OnlyWritable);
+    }
 
-            _dense = items;
-            _length = new PropertyDescriptor(items.Length, PropertyFlag.OnlyWritable);
-        }
+    private void InitializePrototypeAndValidateCapacity(Engine engine, uint capacity)
+    {
+        _constructor = engine.Realm.Intrinsics.Array;
+        _prototype = _constructor.PrototypeObject;
 
-        private void InitializePrototypeAndValidateCapacity(Engine engine, uint capacity)
+        if (capacity > 0 && capacity > engine.Options.Constraints.MaxArraySize)
         {
-            _constructor = engine.Realm.Intrinsics.Array;
-            _prototype = _constructor.PrototypeObject;
-
-            if (capacity > 0 && capacity > engine.Options.Constraints.MaxArraySize)
-            {
-                ThrowMaximumArraySizeReachedException(engine, capacity);
-            }
+            ThrowMaximumArraySizeReachedException(engine, capacity);
         }
+    }
 
-        internal sealed override bool IsArrayLike => true;
+    internal sealed override bool IsArrayLike => true;
 
-        internal sealed override bool IsArray() => true;
+    internal sealed override bool IsArray() => true;
 
-        internal sealed override bool HasOriginalIterator
-            => ReferenceEquals(Get(GlobalSymbolRegistry.Iterator), _constructor?.PrototypeObject._originalIteratorFunction);
+    internal sealed override bool HasOriginalIterator
+        => ReferenceEquals(Get(GlobalSymbolRegistry.Iterator), _constructor?.PrototypeObject._originalIteratorFunction);
 
-        /// <summary>
-        /// Checks whether there have been changes to object prototype chain which could render fast access patterns impossible.
-        /// </summary>
-        internal bool CanUseFastAccess
+    /// <summary>
+    /// Checks whether there have been changes to object prototype chain which could render fast access patterns impossible.
+    /// </summary>
+    internal bool CanUseFastAccess
+    {
+        get
         {
-            get
+            if ((_objectChangeFlags & ObjectChangeFlags.NonDefaultDataDescriptorUsage) != ObjectChangeFlags.None)
             {
-                if ((_objectChangeFlags & ObjectChangeFlags.NonDefaultDataDescriptorUsage) != ObjectChangeFlags.None)
-                {
-                    // could be a mutating property for example, length might change, not safe anymore
-                    return false;
-                }
-
-                if (_prototype is not ArrayPrototype arrayPrototype
-                    || !ReferenceEquals(_prototype, _constructor?.PrototypeObject))
-                {
-                    // somebody has switched prototype
-                    return false;
-                }
-
-                if ((arrayPrototype._objectChangeFlags & ObjectChangeFlags.ArrayIndex) != ObjectChangeFlags.None)
-                {
-                    // maybe somebody moved integer property to prototype? not safe anymore
-                    return false;
-                }
-
-                if (arrayPrototype.Prototype is not ObjectPrototype arrayPrototypePrototype
-                    || !ReferenceEquals(arrayPrototypePrototype, _constructor.PrototypeObject.Prototype))
-                {
-                    return false;
-                }
-
-                return (arrayPrototypePrototype._objectChangeFlags & ObjectChangeFlags.ArrayIndex) == ObjectChangeFlags.None;
+                // could be a mutating property for example, length might change, not safe anymore
+                return false;
             }
-        }
 
-        public sealed override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
-        {
-            if (CommonProperties.Length.Equals(property))
+            if (_prototype is not ArrayPrototype arrayPrototype
+                || !ReferenceEquals(_prototype, _constructor?.PrototypeObject))
             {
-                return DefineLength(desc);
+                // somebody has switched prototype
+                return false;
             }
 
-            var isArrayIndex = IsArrayIndex(property, out var index);
-            TrackChanges(property, desc, isArrayIndex);
+            if ((arrayPrototype._objectChangeFlags & ObjectChangeFlags.ArrayIndex) != ObjectChangeFlags.None)
+            {
+                // maybe somebody moved integer property to prototype? not safe anymore
+                return false;
+            }
 
-            if (isArrayIndex)
+            if (arrayPrototype.Prototype is not ObjectPrototype arrayPrototypePrototype
+                || !ReferenceEquals(arrayPrototypePrototype, _constructor.PrototypeObject.Prototype))
             {
-                ConvertToSparse();
-                return DefineOwnProperty(index, desc);
+                return false;
             }
 
-            return base.DefineOwnProperty(property, desc);
+            return (arrayPrototypePrototype._objectChangeFlags & ObjectChangeFlags.ArrayIndex) == ObjectChangeFlags.None;
         }
+    }
 
-        private bool DefineLength(PropertyDescriptor desc)
+    public sealed override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
+    {
+        if (CommonProperties.Length.Equals(property))
         {
-            var value = desc.Value;
-            if (value is null)
-            {
-                return base.DefineOwnProperty(CommonProperties.Length, desc);
-            }
+            return DefineLength(desc);
+        }
 
-            var newLenDesc = new PropertyDescriptor(desc);
-            uint newLen = TypeConverter.ToUint32(value);
-            if (newLen != TypeConverter.ToNumber(value))
-            {
-                ExceptionHelper.ThrowRangeError(_engine.Realm);
-            }
+        var isArrayIndex = IsArrayIndex(property, out var index);
+        TrackChanges(property, desc, isArrayIndex);
 
-            var oldLenDesc = _length;
-            var oldLen = (uint) TypeConverter.ToNumber(oldLenDesc!.Value);
+        if (isArrayIndex)
+        {
+            ConvertToSparse();
+            return DefineOwnProperty(index, desc);
+        }
 
-            newLenDesc.Value = newLen;
-            if (newLen >= oldLen)
-            {
-                return base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
-            }
+        return base.DefineOwnProperty(property, desc);
+    }
 
-            if (!oldLenDesc.Writable)
-            {
-                return false;
-            }
+    private bool DefineLength(PropertyDescriptor desc)
+    {
+        var value = desc.Value;
+        if (value is null)
+        {
+            return base.DefineOwnProperty(CommonProperties.Length, desc);
+        }
 
-            bool newWritable;
-            if (!newLenDesc.WritableSet || newLenDesc.Writable)
-            {
-                newWritable = true;
-            }
-            else
-            {
-                newWritable = false;
-                newLenDesc.Writable = true;
-            }
+        var newLenDesc = new PropertyDescriptor(desc);
+        uint newLen = TypeConverter.ToUint32(value);
+        if (newLen != TypeConverter.ToNumber(value))
+        {
+            ExceptionHelper.ThrowRangeError(_engine.Realm);
+        }
 
-            var succeeded = base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
-            if (!succeeded)
-            {
-                return false;
-            }
+        var oldLenDesc = _length;
+        var oldLen = (uint) TypeConverter.ToNumber(oldLenDesc!.Value);
+
+        newLenDesc.Value = newLen;
+        if (newLen >= oldLen)
+        {
+            return base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
+        }
+
+        if (!oldLenDesc.Writable)
+        {
+            return false;
+        }
+
+        bool newWritable;
+        if (!newLenDesc.WritableSet || newLenDesc.Writable)
+        {
+            newWritable = true;
+        }
+        else
+        {
+            newWritable = false;
+            newLenDesc.Writable = true;
+        }
+
+        var succeeded = base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
+        if (!succeeded)
+        {
+            return false;
+        }
 
-            var count = _dense?.Length ?? _sparse!.Count;
-            if (count < oldLen - newLen)
+        var count = _dense?.Length ?? _sparse!.Count;
+        if (count < oldLen - newLen)
+        {
+            if (_dense != null)
             {
-                if (_dense != null)
+                for (uint keyIndex = 0; keyIndex < _dense.Length; ++keyIndex)
                 {
-                    for (uint keyIndex = 0; keyIndex < _dense.Length; ++keyIndex)
+                    if (_dense[keyIndex] is null)
                     {
-                        if (_dense[keyIndex] is null)
-                        {
-                            continue;
-                        }
+                        continue;
+                    }
 
-                        // is it the index of the array
-                        if (keyIndex >= newLen && keyIndex < oldLen)
+                    // is it the index of the array
+                    if (keyIndex >= newLen && keyIndex < oldLen)
+                    {
+                        var deleteSucceeded = Delete(keyIndex);
+                        if (!deleteSucceeded)
                         {
-                            var deleteSucceeded = Delete(keyIndex);
-                            if (!deleteSucceeded)
+                            newLenDesc.Value = keyIndex + 1;
+                            if (!newWritable)
                             {
-                                newLenDesc.Value = keyIndex + 1;
-                                if (!newWritable)
-                                {
-                                    newLenDesc.Writable = false;
-                                }
-
-                                base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
-                                return false;
+                                newLenDesc.Writable = false;
                             }
+
+                            base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
+                            return false;
                         }
                     }
                 }
-                else
+            }
+            else
+            {
+                // in the case of sparse arrays, treat each concrete element instead of
+                // iterating over all indexes
+                var keys = new List<uint>(_sparse!.Keys);
+                var keysCount = keys.Count;
+                for (var i = 0; i < keysCount; i++)
                 {
-                    // in the case of sparse arrays, treat each concrete element instead of
-                    // iterating over all indexes
-                    var keys = new List<uint>(_sparse!.Keys);
-                    var keysCount = keys.Count;
-                    for (var i = 0; i < keysCount; i++)
-                    {
-                        var keyIndex = keys[i];
+                    var keyIndex = keys[i];
 
-                        // is it the index of the array
-                        if (keyIndex >= newLen && keyIndex < oldLen)
+                    // is it the index of the array
+                    if (keyIndex >= newLen && keyIndex < oldLen)
+                    {
+                        var deleteSucceeded = Delete(TypeConverter.ToString(keyIndex));
+                        if (!deleteSucceeded)
                         {
-                            var deleteSucceeded = Delete(TypeConverter.ToString(keyIndex));
-                            if (!deleteSucceeded)
+                            newLenDesc.Value = JsNumber.Create(keyIndex + 1);
+                            if (!newWritable)
                             {
-                                newLenDesc.Value = JsNumber.Create(keyIndex + 1);
-                                if (!newWritable)
-                                {
-                                    newLenDesc.Writable = false;
-                                }
-
-                                base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
-                                return false;
+                                newLenDesc.Writable = false;
                             }
+
+                            base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
+                            return false;
                         }
                     }
                 }
             }
-            else
+        }
+        else
+        {
+            while (newLen < oldLen)
             {
-                while (newLen < oldLen)
+                // algorithm as per the spec
+                oldLen--;
+                var deleteSucceeded = Delete(oldLen);
+                if (!deleteSucceeded)
                 {
-                    // algorithm as per the spec
-                    oldLen--;
-                    var deleteSucceeded = Delete(oldLen);
-                    if (!deleteSucceeded)
+                    newLenDesc.Value = oldLen + 1;
+                    if (!newWritable)
                     {
-                        newLenDesc.Value = oldLen + 1;
-                        if (!newWritable)
-                        {
-                            newLenDesc.Writable = false;
-                        }
-
-                        base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
-                        return false;
+                        newLenDesc.Writable = false;
                     }
-                }
-            }
 
-            if (!newWritable)
-            {
-                base.DefineOwnProperty(CommonProperties.Length, new PropertyDescriptor(value: null, PropertyFlag.WritableSet));
+                    base.DefineOwnProperty(CommonProperties.Length, newLenDesc);
+                    return false;
+                }
             }
-
-            return true;
         }
 
-        private bool DefineOwnProperty(uint index, PropertyDescriptor desc)
+        if (!newWritable)
         {
-            var oldLenDesc = _length;
-            var oldLen = (uint) TypeConverter.ToNumber(oldLenDesc!.Value);
+            base.DefineOwnProperty(CommonProperties.Length, new PropertyDescriptor(value: null, PropertyFlag.WritableSet));
+        }
 
-            if (index >= oldLen && !oldLenDesc.Writable)
-            {
-                return false;
-            }
+        return true;
+    }
 
-            var succeeded = base.DefineOwnProperty(index, desc);
-            if (!succeeded)
-            {
-                return false;
-            }
+    private bool DefineOwnProperty(uint index, PropertyDescriptor desc)
+    {
+        var oldLenDesc = _length;
+        var oldLen = (uint) TypeConverter.ToNumber(oldLenDesc!.Value);
 
-            if (index >= oldLen)
-            {
-                oldLenDesc.Value = index + 1;
-                base.DefineOwnProperty(CommonProperties.Length, oldLenDesc);
-            }
+        if (index >= oldLen && !oldLenDesc.Writable)
+        {
+            return false;
+        }
 
-            return true;
+        var succeeded = base.DefineOwnProperty(index, desc);
+        if (!succeeded)
+        {
+            return false;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal override uint GetLength() => (uint) GetJsNumberLength()._value;
+        if (index >= oldLen)
+        {
+            oldLenDesc.Value = index + 1;
+            base.DefineOwnProperty(CommonProperties.Length, oldLenDesc);
+        }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private JsNumber GetJsNumberLength() => _length is null ? JsNumber.PositiveZero : (JsNumber) _length._value!;
+        return true;
+    }
 
-        protected sealed override bool TryGetProperty(JsValue property, [NotNullWhen(true)] out PropertyDescriptor? descriptor)
-        {
-            if (CommonProperties.Length.Equals(property))
-            {
-                descriptor = _length;
-                return _length != null;
-            }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal override uint GetLength() => (uint) GetJsNumberLength()._value;
 
-            return base.TryGetProperty(property, out descriptor);
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private JsNumber GetJsNumberLength() => _length is null ? JsNumber.PositiveZero : (JsNumber) _length._value!;
+
+    protected sealed override bool TryGetProperty(JsValue property, [NotNullWhen(true)] out PropertyDescriptor? descriptor)
+    {
+        if (CommonProperties.Length.Equals(property))
+        {
+            descriptor = _length;
+            return _length != null;
         }
 
-        public sealed override List<JsValue> GetOwnPropertyKeys(Types types = Types.Empty | Types.String | Types.Symbol)
+        return base.TryGetProperty(property, out descriptor);
+    }
+
+    public sealed override List<JsValue> GetOwnPropertyKeys(Types types = Types.Empty | Types.String | Types.Symbol)
+    {
+        if ((types & Types.String) == Types.Empty)
         {
-            if ((types & Types.String) == Types.Empty)
-            {
-                return base.GetOwnPropertyKeys(types);
-            }
+            return base.GetOwnPropertyKeys(types);
+        }
 
-            var temp = _dense;
-            var properties = new List<JsValue>(temp?.Length ?? 0 + 1);
-            if (temp != null)
+        var temp = _dense;
+        var properties = new List<JsValue>(temp?.Length ?? 0 + 1);
+        if (temp != null)
+        {
+            var length = System.Math.Min(temp.Length, GetLength());
+            for (var i = 0; i < length; i++)
             {
-                var length = System.Math.Min(temp.Length, GetLength());
-                for (var i = 0; i < length; i++)
+                if (temp[i] is not null)
                 {
-                    if (temp[i] is not null)
-                    {
-                        properties.Add(JsString.Create(i));
-                    }
+                    properties.Add(JsString.Create(i));
                 }
             }
-            else
+        }
+        else
+        {
+            foreach (var entry in _sparse!)
             {
-                foreach (var entry in _sparse!)
-                {
-                    properties.Add(JsString.Create(entry.Key));
-                }
+                properties.Add(JsString.Create(entry.Key));
             }
+        }
 
-            if (_length != null)
-            {
-                properties.Add(CommonProperties.Length);
-            }
+        if (_length != null)
+        {
+            properties.Add(CommonProperties.Length);
+        }
 
-            properties.AddRange(base.GetOwnPropertyKeys(types));
+        properties.AddRange(base.GetOwnPropertyKeys(types));
 
-            return properties;
-        }
+        return properties;
+    }
 
-        /// <summary>
-        /// Returns key and value pairs for actual array entries, excludes parent and optionally length.
-        /// </summary>
-        /// <param name="includeLength">Whether to return length and it's value.</param>
-        public IEnumerable<KeyValuePair<string, JsValue>> GetEntries(bool includeLength = false)
+    /// <summary>
+    /// Returns key and value pairs for actual array entries, excludes parent and optionally length.
+    /// </summary>
+    /// <param name="includeLength">Whether to return length and it's value.</param>
+    public IEnumerable<KeyValuePair<string, JsValue>> GetEntries(bool includeLength = false)
+    {
+        foreach (var (index, value) in this.Enumerate())
         {
-            foreach (var (index, value) in this.Enumerate())
-            {
-                yield return new KeyValuePair<string, JsValue>(TypeConverter.ToString(index), value);
-            }
+            yield return new KeyValuePair<string, JsValue>(TypeConverter.ToString(index), value);
+        }
 
-            if (includeLength && _length != null)
-            {
-                yield return new KeyValuePair<string, JsValue>(CommonProperties.Length._value, _length.Value);
-            }
+        if (includeLength && _length != null)
+        {
+            yield return new KeyValuePair<string, JsValue>(CommonProperties.Length._value, _length.Value);
         }
+    }
 
-        public sealed override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
+    public sealed override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
+    {
+        var temp = _dense;
+        if (temp != null)
         {
-            var temp = _dense;
-            if (temp != null)
+            var length = System.Math.Min(temp.Length, GetLength());
+            for (uint i = 0; i < length; i++)
             {
-                var length = System.Math.Min(temp.Length, GetLength());
-                for (uint i = 0; i < length; i++)
+                var value = temp[i];
+                if (value is not null)
                 {
-                    var value = temp[i];
-                    if (value is not null)
+                    if (_sparse is null || !_sparse.TryGetValue(i, out var descriptor) || descriptor is null)
                     {
-                        if (_sparse is null || !_sparse.TryGetValue(i, out var descriptor) || descriptor is null)
-                        {
-                            _sparse ??= new Dictionary<uint, PropertyDescriptor?>();
-                            _sparse[i] = descriptor = new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
-                        }
-                        yield return new KeyValuePair<JsValue, PropertyDescriptor>(TypeConverter.ToString(i), descriptor);
+                        _sparse ??= new Dictionary<uint, PropertyDescriptor?>();
+                        _sparse[i] = descriptor = new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
                     }
+                    yield return new KeyValuePair<JsValue, PropertyDescriptor>(TypeConverter.ToString(i), descriptor);
                 }
             }
-            else if (_sparse != null)
+        }
+        else if (_sparse != null)
+        {
+            foreach (var entry in _sparse)
             {
-                foreach (var entry in _sparse)
+                var value = entry.Value;
+                if (value is not null)
                 {
-                    var value = entry.Value;
-                    if (value is not null)
-                    {
-                        yield return new KeyValuePair<JsValue, PropertyDescriptor>(TypeConverter.ToString(entry.Key), value);
-                    }
+                    yield return new KeyValuePair<JsValue, PropertyDescriptor>(TypeConverter.ToString(entry.Key), value);
                 }
             }
+        }
 
-            if (_length != null)
-            {
-                yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Length, _length);
-            }
+        if (_length != null)
+        {
+            yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Length, _length);
+        }
 
-            foreach (var entry in base.GetOwnProperties())
-            {
-                yield return entry;
-            }
+        foreach (var entry in base.GetOwnProperties())
+        {
+            yield return entry;
+        }
+    }
+
+    public sealed override PropertyDescriptor GetOwnProperty(JsValue property)
+    {
+        if (CommonProperties.Length.Equals(property))
+        {
+            return _length ?? PropertyDescriptor.Undefined;
         }
 
-        public sealed override PropertyDescriptor GetOwnProperty(JsValue property)
+        if (IsArrayIndex(property, out var index))
         {
-            if (CommonProperties.Length.Equals(property))
+            if (TryGetDescriptor(index, createIfMissing: true, out var result))
             {
-                return _length ?? PropertyDescriptor.Undefined;
+                return result;
             }
 
-            if (IsArrayIndex(property, out var index))
-            {
-                if (TryGetDescriptor(index, createIfMissing: true, out var result))
-                {
-                    return result;
-                }
+            return PropertyDescriptor.Undefined;
+        }
 
-                return PropertyDescriptor.Undefined;
-            }
+        return base.GetOwnProperty(property);
+    }
+
+    internal JsValue Get(uint index)
+    {
+        if (!TryGetValue(index, out var value))
+        {
+            value = Prototype?.Get(JsString.Create(index)) ?? Undefined;
+        }
+
+        return value;
+    }
 
-            return base.GetOwnProperty(property);
+    public sealed override JsValue Get(JsValue property, JsValue receiver)
+    {
+        if (IsSafeSelfTarget(receiver) && IsArrayIndex(property, out var index) && TryGetValue(index, out var value))
+        {
+            return value;
         }
 
-        internal JsValue Get(uint index)
+        if (CommonProperties.Length.Equals(property))
         {
-            if (!TryGetValue(index, out var value))
+            var length = _length?._value;
+            if (length is not null)
             {
-                value = Prototype?.Get(JsString.Create(index)) ?? Undefined;
+                return length;
             }
-
-            return value;
         }
 
-        public sealed override JsValue Get(JsValue property, JsValue receiver)
+        return base.Get(property, receiver);
+    }
+
+    public sealed override bool Set(JsValue property, JsValue value, JsValue receiver)
+    {
+        var isSafeSelfTarget = IsSafeSelfTarget(receiver);
+        if (isSafeSelfTarget && CanUseFastAccess)
         {
-            if (IsSafeSelfTarget(receiver) && IsArrayIndex(property, out var index) && TryGetValue(index, out var value))
+            if (!ReferenceEquals(property, CommonProperties.Length) && IsArrayIndex(property, out var index))
             {
-                return value;
+                SetIndexValue(index, value, updateLength: true);
+                return true;
             }
 
-            if (CommonProperties.Length.Equals(property))
+            if (CommonProperties.Length.Equals(property)
+                && _length is { Writable: true }
+                && value is JsNumber jsNumber
+                && jsNumber.IsInteger()
+                && jsNumber._value <= MaxDenseArrayLength
+                && jsNumber._value >= GetLength())
             {
-                var length = _length?._value;
-                if (length is not null)
-                {
-                    return length;
-                }
+                // we don't need explicit resize
+                _length.Value = jsNumber;
+                return true;
             }
+        }
+
+        // slow path
+        return base.Set(property, value, receiver);
+    }
 
-            return base.Get(property, receiver);
+    private bool IsSafeSelfTarget(JsValue receiver) => ReferenceEquals(receiver, this) && Extensible;
+
+    public sealed override bool HasProperty(JsValue property)
+    {
+        if (IsArrayIndex(property, out var index) && GetValue(index, unwrapFromNonDataDescriptor: false) is not null)
+        {
+            return true;
         }
 
-        public sealed override bool Set(JsValue property, JsValue value, JsValue receiver)
+        return base.HasProperty(property);
+    }
+
+    internal bool HasProperty(ulong index)
+    {
+        if (index < uint.MaxValue)
         {
-            var isSafeSelfTarget = IsSafeSelfTarget(receiver);
-            if (isSafeSelfTarget && CanUseFastAccess)
+            var temp = _dense;
+            if (temp != null)
             {
-                if (!ReferenceEquals(property, CommonProperties.Length) && IsArrayIndex(property, out var index))
-                {
-                    SetIndexValue(index, value, updateLength: true);
-                    return true;
-                }
-
-                if (CommonProperties.Length.Equals(property)
-                    && _length is { Writable: true }
-                    && value is JsNumber jsNumber
-                    && jsNumber.IsInteger()
-                    && jsNumber._value <= MaxDenseArrayLength
-                    && jsNumber._value >= GetLength())
+                if (index < (uint) temp.Length && temp[index] is not null)
                 {
-                    // we don't need explicit resize
-                    _length.Value = jsNumber;
                     return true;
                 }
             }
-
-            // slow path
-            return base.Set(property, value, receiver);
-        }
-
-        private bool IsSafeSelfTarget(JsValue receiver) => ReferenceEquals(receiver, this) && Extensible;
-
-        public sealed override bool HasProperty(JsValue property)
-        {
-            if (IsArrayIndex(property, out var index) && GetValue(index, unwrapFromNonDataDescriptor: false) is not null)
+            else if (_sparse!.ContainsKey((uint) index))
             {
                 return true;
             }
-
-            return base.HasProperty(property);
         }
 
-        internal bool HasProperty(ulong index)
+        return base.HasProperty(index);
+    }
+
+    protected internal sealed override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
+    {
+        var isArrayIndex = IsArrayIndex(property, out var index);
+        TrackChanges(property, desc, isArrayIndex);
+        if (isArrayIndex)
         {
-            if (index < uint.MaxValue)
-            {
-                var temp = _dense;
-                if (temp != null)
-                {
-                    if (index < (uint) temp.Length && temp[index] is not null)
-                    {
-                        return true;
-                    }
-                }
-                else if (_sparse!.ContainsKey((uint) index))
-                {
-                    return true;
-                }
-            }
-
-            return base.HasProperty(index);
+            WriteArrayValue(index, desc);
         }
-
-        protected internal sealed override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
+        else if (CommonProperties.Length.Equals(property))
         {
-            var isArrayIndex = IsArrayIndex(property, out var index);
-            TrackChanges(property, desc, isArrayIndex);
-            if (isArrayIndex)
-            {
-                WriteArrayValue(index, desc);
-            }
-            else if (CommonProperties.Length.Equals(property))
-            {
-                _length = desc;
-            }
-            else
-            {
-                base.SetOwnProperty(property, desc);
-            }
+            _length = desc;
         }
-
-        private void TrackChanges(JsValue property, PropertyDescriptor desc, bool isArrayIndex)
+        else
         {
-            EnsureInitialized();
-
-            if (isArrayIndex)
-            {
-                if (!desc.IsDefaultArrayValueDescriptor() && desc.Flags != PropertyFlag.None)
-                {
-                    _objectChangeFlags |= ObjectChangeFlags.NonDefaultDataDescriptorUsage;
-                }
-
-                if (GetType() != typeof(JsArray))
-                {
-                    _objectChangeFlags |= ObjectChangeFlags.ArrayIndex;
-                }
-            }
-            else
-            {
-                _objectChangeFlags |= property.IsSymbol() ? ObjectChangeFlags.Symbol : ObjectChangeFlags.Property;
-            }
+            base.SetOwnProperty(property, desc);
         }
+    }
+
+    private void TrackChanges(JsValue property, PropertyDescriptor desc, bool isArrayIndex)
+    {
+        EnsureInitialized();
 
-        public sealed override void RemoveOwnProperty(JsValue property)
+        if (isArrayIndex)
         {
-            if (IsArrayIndex(property, out var index))
+            if (!desc.IsDefaultArrayValueDescriptor() && desc.Flags != PropertyFlag.None)
             {
-                Delete(index);
+                _objectChangeFlags |= ObjectChangeFlags.NonDefaultDataDescriptorUsage;
             }
 
-            if (CommonProperties.Length.Equals(property))
+            if (GetType() != typeof(JsArray))
             {
-                _length = null;
+                _objectChangeFlags |= ObjectChangeFlags.ArrayIndex;
             }
-
-            base.RemoveOwnProperty(property);
         }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsArrayIndex(JsValue p, out uint index)
+        else
         {
-            if (p.IsNumber())
-            {
-                var value = ((JsNumber) p)._value;
-                var intValue = (uint) value;
-                index = intValue;
-                return value == intValue && intValue != uint.MaxValue;
-            }
-
-            index = !p.IsSymbol() ? ParseArrayIndex(p.ToString()) : uint.MaxValue;
-            return index != uint.MaxValue;
-
-            // 15.4 - Use an optimized version of the specification
-            // return TypeConverter.ToString(index) == TypeConverter.ToString(p) && index != uint.MaxValue;
+            _objectChangeFlags |= property.IsSymbol() ? ObjectChangeFlags.Symbol : ObjectChangeFlags.Property;
         }
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static uint ParseArrayIndex(string p)
+    public sealed override void RemoveOwnProperty(JsValue property)
+    {
+        if (IsArrayIndex(property, out var index))
         {
-            if (p.Length == 0 || p.Length > 1 && !IsInRange(p[0], '1', '9') || !uint.TryParse(p, out var d))
-            {
-                return uint.MaxValue;
-            }
+            Delete(index);
+        }
 
-            return d;
+        if (CommonProperties.Length.Equals(property))
+        {
+            _length = null;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static bool IsInRange(char c, char min, char max) => c - (uint) min <= max - (uint) min;
+        base.RemoveOwnProperty(property);
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void SetIndexValue(uint index, JsValue? value, bool updateLength)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool IsArrayIndex(JsValue p, out uint index)
+    {
+        if (p.IsNumber())
         {
-            if (updateLength)
-            {
-                EnsureCorrectLength(index);
-            }
-
-            WriteArrayValue(index, value);
+            var value = ((JsNumber) p)._value;
+            var intValue = (uint) value;
+            index = intValue;
+            return value == intValue && intValue != uint.MaxValue;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private void EnsureCorrectLength(uint index)
+        index = !p.IsSymbol() ? ParseArrayIndex(p.ToString()) : uint.MaxValue;
+        return index != uint.MaxValue;
+
+        // 15.4 - Use an optimized version of the specification
+        // return TypeConverter.ToString(index) == TypeConverter.ToString(p) && index != uint.MaxValue;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static uint ParseArrayIndex(string p)
+    {
+        if (p.Length == 0 || p.Length > 1 && !IsInRange(p[0], '1', '9') || !uint.TryParse(p, out var d))
         {
-            var length = GetLength();
-            if (index >= length)
-            {
-                SetLength(index + 1);
-            }
+            return uint.MaxValue;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void SetLength(ulong length) => SetLength(JsNumber.Create(length));
+        return d;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static bool IsInRange(char c, char min, char max) => c - (uint) min <= max - (uint) min;
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void SetLength(JsNumber length)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void SetIndexValue(uint index, JsValue? value, bool updateLength)
+    {
+        if (updateLength)
         {
-            if (Extensible && _length!._flags == PropertyFlag.OnlyWritable)
-            {
-                _length!.Value = length;
-            }
-            else
-            {
-                // slow path
-                Set(CommonProperties.Length, length, true);
-            }
+            EnsureCorrectLength(index);
         }
 
-        internal uint GetSmallestIndex()
+        WriteArrayValue(index, value);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void EnsureCorrectLength(uint index)
+    {
+        var length = GetLength();
+        if (index >= length)
         {
-            if (_dense != null)
-            {
-                return 0;
-            }
+            SetLength(index + 1);
+        }
+    }
 
-            uint smallest = 0;
-            // only try to help if collection reasonable small
-            if (_sparse!.Count > 0 && _sparse.Count < 100 && !_sparse.ContainsKey(0))
-            {
-                smallest = uint.MaxValue;
-                foreach (var key in _sparse.Keys)
-                {
-                    smallest = System.Math.Min(key, smallest);
-                }
-            }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void SetLength(ulong length) => SetLength(JsNumber.Create(length));
 
-            return smallest;
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void SetLength(JsNumber length)
+    {
+        if (Extensible && _length!._flags == PropertyFlag.OnlyWritable)
+        {
+            _length!.Value = length;
         }
-
-        internal bool DeletePropertyOrThrow(uint index)
+        else
         {
-            if (!Delete(index))
-            {
-                ExceptionHelper.ThrowTypeError(_engine.Realm);
-            }
-            return true;
+            // slow path
+            Set(CommonProperties.Length, length, true);
         }
+    }
 
-        private bool Delete(uint index) => Delete(index, unwrapFromNonDataDescriptor: false, out _);
-
-        private bool Delete(uint index, bool unwrapFromNonDataDescriptor, out JsValue? deletedValue)
+    internal uint GetSmallestIndex()
+    {
+        if (_dense != null)
         {
-            TryGetDescriptor(index, createIfMissing: false, out var desc);
+            return 0;
+        }
 
-            // check fast path
-            var temp = _dense;
-            if (temp != null)
+        uint smallest = 0;
+        // only try to help if collection reasonable small
+        if (_sparse!.Count > 0 && _sparse.Count < 100 && !_sparse.ContainsKey(0))
+        {
+            smallest = uint.MaxValue;
+            foreach (var key in _sparse.Keys)
             {
-                if (index < (uint) temp.Length)
-                {
-                    if (desc is null || desc.Configurable)
-                    {
-                        deletedValue = temp[index];
-                        temp[index] = null;
-                        return true;
-                    }
-                }
+                smallest = System.Math.Min(key, smallest);
             }
+        }
 
-            if (desc is null)
-            {
-                deletedValue = null;
-                return true;
-            }
+        return smallest;
+    }
 
-            if (desc.Configurable)
-            {
-                _sparse!.Remove(index);
-                deletedValue = desc.IsDataDescriptor() || unwrapFromNonDataDescriptor
-                    ? UnwrapJsValue(desc)
-                    : null;
+    internal bool DeletePropertyOrThrow(uint index)
+    {
+        if (!Delete(index))
+        {
+            ExceptionHelper.ThrowTypeError(_engine.Realm);
+        }
+        return true;
+    }
 
-                return true;
-            }
+    private bool Delete(uint index) => Delete(index, unwrapFromNonDataDescriptor: false, out _);
 
-            deletedValue = null;
-            return false;
-        }
+    private bool Delete(uint index, bool unwrapFromNonDataDescriptor, out JsValue? deletedValue)
+    {
+        TryGetDescriptor(index, createIfMissing: false, out var desc);
 
-        internal bool DeleteAt(uint index)
+        // check fast path
+        var temp = _dense;
+        if (temp != null)
         {
-            var temp = _dense;
-            if (temp != null)
+            if (index < (uint) temp.Length)
             {
-                if (index < (uint) temp.Length)
+                if (desc is null || desc.Configurable)
                 {
+                    deletedValue = temp[index];
                     temp[index] = null;
                     return true;
                 }
             }
-            else
-            {
-                return _sparse!.Remove(index);
-            }
-
-            return false;
         }
 
-        private bool TryGetDescriptor(uint index, bool createIfMissing, [NotNullWhen(true)] out PropertyDescriptor? descriptor)
+        if (desc is null)
         {
-            if (!createIfMissing && _sparse is null)
-            {
-                descriptor = null;
-                return false;
-            }
-
-            descriptor = null;
-            var temp = _dense;
-            if (temp != null)
-            {
-                if (index < (uint) temp.Length)
-                {
-                    var value = temp[index];
-                    if (value is not null)
-                    {
-                        if (_sparse is null || !_sparse.TryGetValue(index, out descriptor) || descriptor is null)
-                        {
-                            _sparse ??= new Dictionary<uint, PropertyDescriptor?>();
-                            _sparse[index] = descriptor = new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
-                        }
+            deletedValue = null;
+            return true;
+        }
 
-                        descriptor.Value = value;
-                        return true;
-                    }
-                }
-                return false;
-            }
+        if (desc.Configurable)
+        {
+            _sparse!.Remove(index);
+            deletedValue = desc.IsDataDescriptor() || unwrapFromNonDataDescriptor
+                ? UnwrapJsValue(desc)
+                : null;
 
-            _sparse?.TryGetValue(index, out descriptor);
-            return descriptor is not null;
+            return true;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal bool TryGetValue(uint index, out JsValue value)
-        {
-            value = GetValue(index, unwrapFromNonDataDescriptor: true)!;
+        deletedValue = null;
+        return false;
+    }
 
-            if (value is not null)
+    internal bool DeleteAt(uint index)
+    {
+        var temp = _dense;
+        if (temp != null)
+        {
+            if (index < (uint) temp.Length)
             {
+                temp[index] = null;
                 return true;
             }
+        }
+        else
+        {
+            return _sparse!.Remove(index);
+        }
 
-            return TryGetValueUnlikely(index, out value);
+        return false;
+    }
+
+    private bool TryGetDescriptor(uint index, bool createIfMissing, [NotNullWhen(true)] out PropertyDescriptor? descriptor)
+    {
+        if (!createIfMissing && _sparse is null)
+        {
+            descriptor = null;
+            return false;
         }
 
-        [MethodImpl(MethodImplOptions.NoInlining)]
-        private bool TryGetValueUnlikely(uint index, out JsValue value)
+        descriptor = null;
+        var temp = _dense;
+        if (temp != null)
         {
-            if (!CanUseFastAccess)
+            if (index < (uint) temp.Length)
             {
-                // slow path must be checked for prototype
-                var prototype = Prototype;
-                JsValue key = index;
-                while (prototype is not null)
+                var value = temp[index];
+                if (value is not null)
                 {
-                    var desc = prototype.GetOwnProperty(key);
-                    if (desc != PropertyDescriptor.Undefined)
+                    if (_sparse is null || !_sparse.TryGetValue(index, out descriptor) || descriptor is null)
                     {
-                        value = UnwrapJsValue(desc);
-                        return true;
+                        _sparse ??= new Dictionary<uint, PropertyDescriptor?>();
+                        _sparse[index] = descriptor = new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
                     }
 
-                    prototype = prototype.Prototype;
+                    descriptor.Value = value;
+                    return true;
                 }
             }
-
-            value = Undefined;
             return false;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private JsValue? GetValue(uint index, bool unwrapFromNonDataDescriptor)
-        {
-            var temp = _dense;
-            if (temp != null)
-            {
-                if (index < (uint) temp.Length)
-                {
-                    return temp[index];
-                }
-                return null;
-            }
+        _sparse?.TryGetValue(index, out descriptor);
+        return descriptor is not null;
+    }
 
-            return GetValueUnlikely(index, unwrapFromNonDataDescriptor);
-        }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal bool TryGetValue(uint index, out JsValue value)
+    {
+        value = GetValue(index, unwrapFromNonDataDescriptor: true)!;
 
-        [MethodImpl(MethodImplOptions.NoInlining)]
-        private JsValue? GetValueUnlikely(uint index, bool unwrapFromNonDataDescriptor)
+        if (value is not null)
         {
-            JsValue? value = null;
-            if (_sparse!.TryGetValue(index, out var descriptor) && descriptor != null)
-            {
-                value = descriptor.IsDataDescriptor() || unwrapFromNonDataDescriptor
-                    ? UnwrapJsValue(descriptor)
-                    : null;
-            }
-
-            return value;
+            return true;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private void WriteArrayValue(uint index, PropertyDescriptor descriptor)
+        return TryGetValueUnlikely(index, out value);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private bool TryGetValueUnlikely(uint index, out JsValue value)
+    {
+        if (!CanUseFastAccess)
         {
-            var temp = _dense;
-            if (temp != null && descriptor.IsDefaultArrayValueDescriptor())
+            // slow path must be checked for prototype
+            var prototype = Prototype;
+            JsValue key = index;
+            while (prototype is not null)
             {
-                if (index < (uint) temp.Length)
+                var desc = prototype.GetOwnProperty(key);
+                if (desc != PropertyDescriptor.Undefined)
                 {
-                    temp[index] = descriptor.Value;
-                }
-                else
-                {
-                    WriteArrayValueUnlikely(index, descriptor.Value);
+                    value = UnwrapJsValue(desc);
+                    return true;
                 }
-            }
-            else
-            {
-                WriteArrayValueUnlikely(index, descriptor);
+
+                prototype = prototype.Prototype;
             }
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private void WriteArrayValue(uint index, JsValue? value)
+        value = Undefined;
+        return false;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private JsValue? GetValue(uint index, bool unwrapFromNonDataDescriptor)
+    {
+        var temp = _dense;
+        if (temp != null)
         {
-            var temp = _dense;
-            if (temp != null)
+            if (index < (uint) temp.Length)
             {
-                if (index < (uint) temp.Length)
-                {
-                    temp[index] = value;
-                    return;
-                }
+                return temp[index];
             }
-
-            WriteArrayValueUnlikely(index, value);
+            return null;
         }
 
-        [MethodImpl(MethodImplOptions.NoInlining)]
-        private void WriteArrayValueUnlikely(uint index, JsValue? value)
+        return GetValueUnlikely(index, unwrapFromNonDataDescriptor);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private JsValue? GetValueUnlikely(uint index, bool unwrapFromNonDataDescriptor)
+    {
+        JsValue? value = null;
+        if (_sparse!.TryGetValue(index, out var descriptor) && descriptor != null)
         {
-            // calculate eagerly so we know if we outgrow
-            var dense = _dense;
-            var newSize = dense != null && index >= (uint) dense.Length
-                ? System.Math.Max(index, System.Math.Max(dense.Length, 2)) * 2
-                : 0;
+            value = descriptor.IsDataDescriptor() || unwrapFromNonDataDescriptor
+                ? UnwrapJsValue(descriptor)
+                : null;
+        }
 
-            var canUseDense = dense != null
-                              && index < MaxDenseArrayLength
-                              && newSize < MaxDenseArrayLength
-                              && index < dense.Length + 50; // looks sparse
+        return value;
+    }
 
-            if (canUseDense)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void WriteArrayValue(uint index, PropertyDescriptor descriptor)
+    {
+        var temp = _dense;
+        if (temp != null && descriptor.IsDefaultArrayValueDescriptor())
+        {
+            if (index < (uint) temp.Length)
             {
-                EnsureCapacity((uint) newSize);
-                _dense![index] = value;
+                temp[index] = descriptor.Value;
             }
             else
             {
-                ConvertToSparse();
-                _sparse![index] = new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
+                WriteArrayValueUnlikely(index, descriptor.Value);
             }
         }
+        else
+        {
+            WriteArrayValueUnlikely(index, descriptor);
+        }
+    }
 
-        private void WriteArrayValueUnlikely(uint index, PropertyDescriptor? value)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void WriteArrayValue(uint index, JsValue? value)
+    {
+        var temp = _dense;
+        if (temp != null)
         {
-            if (_sparse == null)
+            if (index < (uint) temp.Length)
             {
-                ConvertToSparse();
+                temp[index] = value;
+                return;
             }
+        }
+
+        WriteArrayValueUnlikely(index, value);
+    }
 
-            _sparse![index] = value;
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private void WriteArrayValueUnlikely(uint index, JsValue? value)
+    {
+        // calculate eagerly so we know if we outgrow
+        var dense = _dense;
+        var newSize = dense != null && index >= (uint) dense.Length
+            ? System.Math.Max(index, System.Math.Max(dense.Length, 2)) * 2
+            : 0;
+
+        var canUseDense = dense != null
+                          && index < MaxDenseArrayLength
+                          && newSize < MaxDenseArrayLength
+                          && index < dense.Length + 50; // looks sparse
+
+        if (canUseDense)
+        {
+            EnsureCapacity((uint) newSize);
+            _dense![index] = value;
+        }
+        else
+        {
+            ConvertToSparse();
+            _sparse![index] = new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
         }
+    }
 
-        private void ConvertToSparse()
+    private void WriteArrayValueUnlikely(uint index, PropertyDescriptor? value)
+    {
+        if (_sparse == null)
         {
-            // need to move data
-            var temp = _dense;
+            ConvertToSparse();
+        }
 
-            if (temp is null)
-            {
-                return;
-            }
+        _sparse![index] = value;
+    }
 
-            _sparse ??= new Dictionary<uint, PropertyDescriptor?>();
-            for (uint i = 0; i < (uint) temp.Length; ++i)
-            {
-                var value = temp[i];
-                if (value is not null)
-                {
-                    _sparse.TryGetValue(i, out var descriptor);
-                    descriptor ??= new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
-                    descriptor.Value = value;
-                    _sparse[i] = descriptor;
-                }
-                else
-                {
-                    _sparse.Remove(i);
-                }
-            }
+    private void ConvertToSparse()
+    {
+        // need to move data
+        var temp = _dense;
 
-            _dense = null;
+        if (temp is null)
+        {
+            return;
         }
 
-        internal void EnsureCapacity(uint capacity, bool force = false)
+        _sparse ??= new Dictionary<uint, PropertyDescriptor?>();
+        for (uint i = 0; i < (uint) temp.Length; ++i)
         {
-            var dense = _dense;
-
-            if (dense is null)
+            var value = temp[i];
+            if (value is not null)
             {
-                return;
+                _sparse.TryGetValue(i, out var descriptor);
+                descriptor ??= new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
+                descriptor.Value = value;
+                _sparse[i] = descriptor;
             }
-
-            if (!force && (capacity > MaxDenseArrayLength || capacity <= (uint) dense.Length))
+            else
             {
-                return;
+                _sparse.Remove(i);
             }
+        }
 
-            if (capacity > _engine.Options.Constraints.MaxArraySize)
-            {
-                ThrowMaximumArraySizeReachedException(_engine, capacity);
-            }
+        _dense = null;
+    }
+
+    internal void EnsureCapacity(uint capacity, bool force = false)
+    {
+        var dense = _dense;
 
-            // need to grow
-            var newArray = new JsValue[capacity];
-            System.Array.Copy(dense, newArray, dense.Length);
-            _dense = newArray;
+        if (dense is null)
+        {
+            return;
         }
 
-        public JsValue[] ToArray()
+        if (!force && (capacity > MaxDenseArrayLength || capacity <= (uint) dense.Length))
         {
-            var length = GetLength();
-            var array = new JsValue[length];
-            for (uint i = 0; i < length; i++)
-            {
-                TryGetValue(i, out var outValue);
-                array[i] = outValue;
-            }
+            return;
+        }
 
-            return array;
+        if (capacity > _engine.Options.Constraints.MaxArraySize)
+        {
+            ThrowMaximumArraySizeReachedException(_engine, capacity);
         }
 
-        IEnumerator IEnumerable.GetEnumerator()
+        // need to grow
+        var newArray = new JsValue[capacity];
+        System.Array.Copy(dense, newArray, dense.Length);
+        _dense = newArray;
+    }
+
+    public JsValue[] ToArray()
+    {
+        var length = GetLength();
+        var array = new JsValue[length];
+        for (uint i = 0; i < length; i++)
         {
-            return GetEnumerator();
+            TryGetValue(i, out var outValue);
+            array[i] = outValue;
         }
 
-        public IEnumerator<JsValue> GetEnumerator()
+        return array;
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    public IEnumerator<JsValue> GetEnumerator()
+    {
+        foreach (var (_, value) in this.Enumerate())
         {
-            foreach (var (_, value) in this.Enumerate())
-            {
-                yield return value;
-            }
+            yield return value;
         }
+    }
 
-        private readonly record struct IndexedEntry(int Index, JsValue Value);
+    private readonly record struct IndexedEntry(int Index, JsValue Value);
 
-        private IEnumerable<IndexedEntry> Enumerate()
+    private IEnumerable<IndexedEntry> Enumerate()
+    {
+        if (!CanUseFastAccess)
         {
-            if (!CanUseFastAccess)
+            // slow path where prototype is also checked
+            var length = GetLength();
+            for (uint i = 0; i < length; i++)
             {
-                // slow path where prototype is also checked
-                var length = GetLength();
-                for (uint i = 0; i < length; i++)
-                {
-                    TryGetValue(i, out var outValue);
-                    yield return new IndexedEntry((int) i, outValue);
-                }
-
-                yield break;
+                TryGetValue(i, out var outValue);
+                yield return new IndexedEntry((int) i, outValue);
             }
 
-            var temp = _dense;
-            if (temp != null)
+            yield break;
+        }
+
+        var temp = _dense;
+        if (temp != null)
+        {
+            var length = System.Math.Min(temp.Length, GetLength());
+            for (var i = 0; i < length; i++)
             {
-                var length = System.Math.Min(temp.Length, GetLength());
-                for (var i = 0; i < length; i++)
+                var value = temp[i];
+                if (value is not null)
                 {
-                    var value = temp[i];
-                    if (value is not null)
-                    {
-                        yield return new IndexedEntry(i, value);
-                    }
+                    yield return new IndexedEntry(i, value);
                 }
             }
-            else
+        }
+        else
+        {
+            foreach (var entry in _sparse!)
             {
-                foreach (var entry in _sparse!)
+                var descriptor = entry.Value;
+                if (descriptor is not null)
                 {
-                    var descriptor = entry.Value;
-                    if (descriptor is not null)
-                    {
-                        yield return new IndexedEntry((int) entry.Key, descriptor.Value);
-                    }
+                    yield return new IndexedEntry((int) entry.Key, descriptor.Value);
                 }
             }
         }
+    }
 
-        /// <summary>
-        /// Pushes the value to the end of the array instance.
-        /// </summary>
-        public void Push(JsValue value)
-        {
-            var initialLength = GetLength();
-            var newLength = initialLength + 1;
-
-            var temp = _dense;
-            var canUseDirectIndexSet = temp != null && newLength <= temp.Length;
+    /// <summary>
+    /// Pushes the value to the end of the array instance.
+    /// </summary>
+    public void Push(JsValue value)
+    {
+        var initialLength = GetLength();
+        var newLength = initialLength + 1;
 
-            double n = initialLength;
-            if (canUseDirectIndexSet)
-            {
-                temp![(uint) n] = value;
-            }
-            else
-            {
-                WriteValueSlow(n, value);
-            }
+        var temp = _dense;
+        var canUseDirectIndexSet = temp != null && newLength <= temp.Length;
 
-            // check if we can set length fast without breaking ECMA specification
-            if (n < uint.MaxValue && CanSetLength())
-            {
-                _length!.Value = newLength;
-            }
-            else
-            {
-                if (!Set(CommonProperties.Length, newLength))
-                {
-                    ExceptionHelper.ThrowTypeError(_engine.Realm);
-                }
-            }
+        double n = initialLength;
+        if (canUseDirectIndexSet)
+        {
+            temp![(uint) n] = value;
         }
-
-        /// <summary>
-        /// Pushes the given values to the end of the array.
-        /// </summary>
-        public uint Push(JsValue[] values)
+        else
         {
-            var initialLength = GetLength();
-            var newLength = initialLength + values.Length;
+            WriteValueSlow(n, value);
+        }
 
-            // if we see that we are bringing more than normal growth algorithm handles, ensure capacity eagerly
-            if (_dense != null
-                && initialLength != 0
-                && values.Length > initialLength * 2
-                && newLength <= MaxDenseArrayLength)
+        // check if we can set length fast without breaking ECMA specification
+        if (n < uint.MaxValue && CanSetLength())
+        {
+            _length!.Value = newLength;
+        }
+        else
+        {
+            if (!Set(CommonProperties.Length, newLength))
             {
-                EnsureCapacity((uint) newLength);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
+        }
+    }
 
-            var temp = _dense;
-            ulong n = initialLength;
-            foreach (var argument in values)
-            {
-                if (n < ArrayOperations.MaxArrayLength)
-                {
-                    WriteArrayValue((uint) n, argument);
-                }
-                else
-                {
-                    DefineOwnProperty(n, new PropertyDescriptor(argument, PropertyFlag.ConfigurableEnumerableWritable));
-                }
-
-                n++;
-            }
+    /// <summary>
+    /// Pushes the given values to the end of the array.
+    /// </summary>
+    public uint Push(JsValue[] values)
+    {
+        var initialLength = GetLength();
+        var newLength = initialLength + values.Length;
+
+        // if we see that we are bringing more than normal growth algorithm handles, ensure capacity eagerly
+        if (_dense != null
+            && initialLength != 0
+            && values.Length > initialLength * 2
+            && newLength <= MaxDenseArrayLength)
+        {
+            EnsureCapacity((uint) newLength);
+        }
 
-            // check if we can set length fast without breaking ECMA specification
-            if (n < ArrayOperations.MaxArrayLength && CanSetLength())
+        var temp = _dense;
+        ulong n = initialLength;
+        foreach (var argument in values)
+        {
+            if (n < ArrayOperations.MaxArrayLength)
             {
-                _length!.Value = n;
+                WriteArrayValue((uint) n, argument);
             }
             else
             {
-                if (!Set(CommonProperties.Length, newLength))
-                {
-                    ExceptionHelper.ThrowTypeError(_engine.Realm);
-                }
+                DefineOwnProperty(n, new PropertyDescriptor(argument, PropertyFlag.ConfigurableEnumerableWritable));
             }
 
-            return (uint) n;
+            n++;
         }
 
-        public JsValue Pop()
+        // check if we can set length fast without breaking ECMA specification
+        if (n < ArrayOperations.MaxArrayLength && CanSetLength())
         {
-            var len = GetJsNumberLength();
-            if (JsNumber.PositiveZero.Equals(len))
-            {
-                SetLength(len);
-                return Undefined;
-            }
-
-            var newLength = (uint) len._value - 1;
-
-            if (!Delete(newLength, unwrapFromNonDataDescriptor: true, out var element))
+            _length!.Value = n;
+        }
+        else
+        {
+            if (!Set(CommonProperties.Length, newLength))
             {
                 ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
+        }
 
-            SetLength(newLength);
+        return (uint) n;
+    }
 
-            return element ?? Undefined;
+    public JsValue Pop()
+    {
+        var len = GetJsNumberLength();
+        if (JsNumber.PositiveZero.Equals(len))
+        {
+            SetLength(len);
+            return Undefined;
         }
 
-        private bool CanSetLength()
+        var newLength = (uint) len._value - 1;
+
+        if (!Delete(newLength, unwrapFromNonDataDescriptor: true, out var element))
         {
-            if (!_length!.IsAccessorDescriptor())
-            {
-                return _length.Writable;
-            }
-            var set = _length.Set;
-            return set is not null && !set.IsUndefined();
+            ExceptionHelper.ThrowTypeError(_engine.Realm);
         }
 
-        [MethodImpl(MethodImplOptions.NoInlining)]
-        private void WriteValueSlow(double n, JsValue value)
+        SetLength(newLength);
+
+        return element ?? Undefined;
+    }
+
+    private bool CanSetLength()
+    {
+        if (!_length!.IsAccessorDescriptor())
         {
-            if (n < ArrayOperations.MaxArrayLength)
-            {
-                WriteArrayValue((uint) n, value);
-            }
-            else
-            {
-                DefinePropertyOrThrow((uint) n, new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable));
-            }
+            return _length.Writable;
         }
+        var set = _length.Set;
+        return set is not null && !set.IsUndefined();
+    }
 
-        internal JsArray Map(JsValue[] arguments)
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private void WriteValueSlow(double n, JsValue value)
+    {
+        if (n < ArrayOperations.MaxArrayLength)
+        {
+            WriteArrayValue((uint) n, value);
+        }
+        else
         {
-            var callbackfn = arguments.At(0);
-            var thisArg = arguments.At(1);
+            DefinePropertyOrThrow((uint) n, new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable));
+        }
+    }
 
-            var len = GetLength();
+    internal JsArray Map(JsValue[] arguments)
+    {
+        var callbackfn = arguments.At(0);
+        var thisArg = arguments.At(1);
 
-            var callable = GetCallable(callbackfn);
-            var a = _engine.Realm.Intrinsics.Array.ArrayCreate(len);
-            var args = _engine._jsValueArrayPool.RentArray(3);
-            args[2] = this;
-            for (uint k = 0; k < len; k++)
+        var len = GetLength();
+
+        var callable = GetCallable(callbackfn);
+        var a = _engine.Realm.Intrinsics.Array.ArrayCreate(len);
+        var args = _engine._jsValueArrayPool.RentArray(3);
+        args[2] = this;
+        for (uint k = 0; k < len; k++)
+        {
+            if (TryGetValue(k, out var kvalue))
             {
-                if (TryGetValue(k, out var kvalue))
+                args[0] = kvalue;
+                args[1] = k;
+                var mappedValue = callable.Call(thisArg, args);
+                if (a._dense != null && k < (uint) a._dense.Length)
                 {
-                    args[0] = kvalue;
-                    args[1] = k;
-                    var mappedValue = callable.Call(thisArg, args);
-                    if (a._dense != null && k < (uint) a._dense.Length)
-                    {
-                        a._dense[k] = mappedValue;
-                    }
-                    else
-                    {
-                        a.WriteArrayValue(k, mappedValue);
-                    }
+                    a._dense[k] = mappedValue;
+                }
+                else
+                {
+                    a.WriteArrayValue(k, mappedValue);
                 }
             }
-
-            _engine._jsValueArrayPool.ReturnArray(args);
-            return a;
         }
 
-        /// <inheritdoc />
-        internal sealed override bool FindWithCallback(
-            JsValue[] arguments,
-            out ulong index,
-            out JsValue value,
-            bool visitUnassigned,
-            bool fromEnd = false)
-        {
-            var thisArg = arguments.At(1);
-            var callbackfn = arguments.At(0);
-            var callable = GetCallable(callbackfn);
+        _engine._jsValueArrayPool.ReturnArray(args);
+        return a;
+    }
 
-            var len = GetLength();
-            if (len == 0)
-            {
-                index = 0;
-                value = Undefined;
-                return false;
-            }
+    /// <inheritdoc />
+    internal sealed override bool FindWithCallback(
+        JsValue[] arguments,
+        out ulong index,
+        out JsValue value,
+        bool visitUnassigned,
+        bool fromEnd = false)
+    {
+        var thisArg = arguments.At(1);
+        var callbackfn = arguments.At(0);
+        var callable = GetCallable(callbackfn);
+
+        var len = GetLength();
+        if (len == 0)
+        {
+            index = 0;
+            value = Undefined;
+            return false;
+        }
 
-            var args = _engine._jsValueArrayPool.RentArray(3);
-            args[2] = this;
+        var args = _engine._jsValueArrayPool.RentArray(3);
+        args[2] = this;
 
-            if (!fromEnd)
+        if (!fromEnd)
+        {
+            for (uint k = 0; k < len; k++)
             {
-                for (uint k = 0; k < len; k++)
+                if (TryGetValue(k, out var kvalue) || visitUnassigned)
                 {
-                    if (TryGetValue(k, out var kvalue) || visitUnassigned)
+                    kvalue ??= Undefined;
+                    args[0] = kvalue;
+                    args[1] = k;
+                    var testResult = callable.Call(thisArg, args);
+                    if (TypeConverter.ToBoolean(testResult))
                     {
-                        kvalue ??= Undefined;
-                        args[0] = kvalue;
-                        args[1] = k;
-                        var testResult = callable.Call(thisArg, args);
-                        if (TypeConverter.ToBoolean(testResult))
-                        {
-                            index = k;
-                            value = kvalue;
-                            return true;
-                        }
+                        index = k;
+                        value = kvalue;
+                        return true;
                     }
                 }
             }
-            else
+        }
+        else
+        {
+            for (long k = len - 1; k >= 0; k--)
             {
-                for (long k = len - 1; k >= 0; k--)
+                var idx = (uint) k;
+                if (TryGetValue(idx, out var kvalue) || visitUnassigned)
                 {
-                    var idx = (uint) k;
-                    if (TryGetValue(idx, out var kvalue) || visitUnassigned)
+                    kvalue ??= Undefined;
+                    args[0] = kvalue;
+                    args[1] = idx;
+                    var testResult = callable.Call(thisArg, args);
+                    if (TypeConverter.ToBoolean(testResult))
                     {
-                        kvalue ??= Undefined;
-                        args[0] = kvalue;
-                        args[1] = idx;
-                        var testResult = callable.Call(thisArg, args);
-                        if (TypeConverter.ToBoolean(testResult))
-                        {
-                            index = idx;
-                            value = kvalue;
-                            return true;
-                        }
+                        index = idx;
+                        value = kvalue;
+                        return true;
                     }
                 }
             }
+        }
 
-            _engine._jsValueArrayPool.ReturnArray(args);
+        _engine._jsValueArrayPool.ReturnArray(args);
 
-            index = 0;
-            value = Undefined;
-            return false;
-        }
+        index = 0;
+        value = Undefined;
+        return false;
+    }
+
+    internal sealed override bool IsIntegerIndexedArray => true;
 
-        internal sealed override bool IsIntegerIndexedArray => true;
+    public JsValue this[uint index]
+    {
+        get
+        {
+            TryGetValue(index, out var kValue);
+            return kValue;
+        }
+        set
+        {
+            SetIndexValue(index, value, updateLength: true);
+        }
+    }
 
-        public JsValue this[uint index]
+    public JsValue this[int index]
+    {
+        get
         {
-            get
+            JsValue? kValue;
+            if (index >= 0)
             {
-                TryGetValue(index, out var kValue);
-                return kValue;
+                TryGetValue((uint) index, out kValue);
             }
-            set
+            else
             {
-                SetIndexValue(index, value, updateLength: true);
+                // slow path
+                TryGetValue(JsNumber.Create(index), out kValue);
             }
+            return kValue;
         }
-
-        public JsValue this[int index]
+        set
         {
-            get
+            if (index >= 0)
             {
-                JsValue? kValue;
-                if (index >= 0)
-                {
-                    TryGetValue((uint) index, out kValue);
-                }
-                else
-                {
-                    // slow path
-                    TryGetValue(JsNumber.Create(index), out kValue);
-                }
-                return kValue;
+                SetIndexValue((uint) index, value, updateLength: true);
             }
-            set
+            else
             {
-                if (index >= 0)
-                {
-                    SetIndexValue((uint) index, value, updateLength: true);
-                }
-                else
-                {
-                    Set(index, value);
-                }
+                Set(index, value);
             }
         }
+    }
 
-        /// <summary>
-        /// Fast path for concatenating sane-sized arrays, we assume size has been calculated.
-        /// </summary>
-        internal void CopyValues(JsArray source, uint sourceStartIndex, uint targetStartIndex, uint length)
+    /// <summary>
+    /// Fast path for concatenating sane-sized arrays, we assume size has been calculated.
+    /// </summary>
+    internal void CopyValues(JsArray source, uint sourceStartIndex, uint targetStartIndex, uint length)
+    {
+        if (length == 0)
         {
-            if (length == 0)
-            {
-                return;
-            }
+            return;
+        }
 
-            var sourceDense = source._dense;
+        var sourceDense = source._dense;
 
-            if (sourceDense is not null)
-            {
-                EnsureCapacity((uint) (targetStartIndex + sourceDense.LongLength));
-            }
+        if (sourceDense is not null)
+        {
+            EnsureCapacity((uint) (targetStartIndex + sourceDense.LongLength));
+        }
 
-            var dense = _dense;
-            if (dense != null
-                && sourceDense != null
-                && (uint) dense.Length >= targetStartIndex + length
-                && dense[targetStartIndex] is null)
+        var dense = _dense;
+        if (dense != null
+            && sourceDense != null
+            && (uint) dense.Length >= targetStartIndex + length
+            && dense[targetStartIndex] is null)
+        {
+            uint j = 0;
+            for (var i = sourceStartIndex; i < sourceStartIndex + length; ++i, j++)
             {
-                uint j = 0;
-                for (var i = sourceStartIndex; i < sourceStartIndex + length; ++i, j++)
+                JsValue? sourceValue;
+                if (i < (uint) sourceDense.Length)
                 {
-                    JsValue? sourceValue;
-                    if (i < (uint) sourceDense.Length)
-                    {
-                        sourceValue = sourceDense[i];
-                    }
-                    else
-                    {
-                        source.TryGetValue(i, out sourceValue);
-                    }
-
-                    dense[targetStartIndex + j] = sourceValue;
+                    sourceValue = sourceDense[i];
                 }
-            }
-            else
-            {
-                // slower version
-                for (uint k = sourceStartIndex; k < length; k++)
+                else
                 {
-                    if (source.TryGetValue(k, out var subElement))
-                    {
-                        SetIndexValue(targetStartIndex, subElement, updateLength: false);
-                    }
-
-                    targetStartIndex++;
+                    source.TryGetValue(i, out sourceValue);
                 }
+
+                dense[targetStartIndex + j] = sourceValue;
             }
         }
-
-        public sealed override string ToString()
+        else
         {
-            // debugger can make things hard when evaluates computed values
-            return "(" + (_length?._value!.AsNumber() ?? 0) + ")[]";
-        }
+            // slower version
+            for (uint k = sourceStartIndex; k < length; k++)
+            {
+                if (source.TryGetValue(k, out var subElement))
+                {
+                    SetIndexValue(targetStartIndex, subElement, updateLength: false);
+                }
 
-        private static void ThrowMaximumArraySizeReachedException(Engine engine, uint capacity)
-        {
-            ExceptionHelper.ThrowMemoryLimitExceededException(
-                $"The array size {capacity} is larger than maximum allowed ({engine.Options.Constraints.MaxArraySize})"
-            );
+                targetStartIndex++;
+            }
         }
     }
 
-    internal static class ArrayPropertyDescriptorExtensions
+    public sealed override string ToString()
+    {
+        // debugger can make things hard when evaluates computed values
+        return "(" + (_length?._value!.AsNumber() ?? 0) + ")[]";
+    }
+
+    private static void ThrowMaximumArraySizeReachedException(Engine engine, uint capacity)
     {
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsDefaultArrayValueDescriptor(this PropertyDescriptor propertyDescriptor)
-            => propertyDescriptor.Flags == PropertyFlag.ConfigurableEnumerableWritable && propertyDescriptor.IsDataDescriptor();
+        ExceptionHelper.ThrowMemoryLimitExceededException(
+            $"The array size {capacity} is larger than maximum allowed ({engine.Options.Constraints.MaxArraySize})"
+        );
     }
 }
+
+internal static class ArrayPropertyDescriptorExtensions
+{
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal static bool IsDefaultArrayValueDescriptor(this PropertyDescriptor propertyDescriptor)
+        => propertyDescriptor.Flags == PropertyFlag.ConfigurableEnumerableWritable && propertyDescriptor.IsDataDescriptor();
+}

+ 440 - 441
Jint/Native/Array/ArrayOperations.cs

@@ -5,651 +5,650 @@ using Jint.Native.String;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
 
-namespace Jint.Native.Array
+namespace Jint.Native.Array;
+
+internal abstract class ArrayOperations : IEnumerable<JsValue>
 {
-    internal abstract class ArrayOperations : IEnumerable<JsValue>
-    {
-        protected internal const ulong MaxArrayLength = 4294967295;
-        protected internal const ulong MaxArrayLikeLength = NumberConstructor.MaxSafeInteger;
+    protected internal const ulong MaxArrayLength = 4294967295;
+    protected internal const ulong MaxArrayLikeLength = NumberConstructor.MaxSafeInteger;
 
-        public static ArrayOperations For(Realm realm, JsValue value, bool forWrite)
+    public static ArrayOperations For(Realm realm, JsValue value, bool forWrite)
+    {
+        if (!forWrite)
         {
-            if (!forWrite)
+            if (value.IsString())
             {
-                if (value.IsString())
-                {
-                    return new JsStringOperations(realm, (JsString) value);
-                }
-
-                if (value is StringInstance stringInstance)
-                {
-                    return new JsStringOperations(realm, stringInstance);
-                }
-
-                if (value is JsArray { CanUseFastAccess: true } array && array.Length <= (array._dense?.Length ?? -1))
-                {
-                    return new ArrayReadOperations(array);
-                }
+                return new JsStringOperations(realm, (JsString) value);
             }
 
-            return For(TypeConverter.ToObject(realm, value), forWrite);
-        }
-
-        public static ArrayOperations For(ObjectInstance instance, bool forWrite)
-        {
-            if (instance is JsArray { CanUseFastAccess: true } arrayInstance)
+            if (value is StringInstance stringInstance)
             {
-                return new JsArrayOperations(arrayInstance);
+                return new JsStringOperations(realm, stringInstance);
             }
 
-            if (instance is JsTypedArray typedArrayInstance)
+            if (value is JsArray { CanUseFastAccess: true } array && array.Length <= (array._dense?.Length ?? -1))
             {
-                return new JsTypedArrayOperations(typedArrayInstance);
+                return new ArrayReadOperations(array);
             }
+        }
 
-            if (instance is ArrayLikeWrapper arrayWrapper)
-            {
-                return new ArrayLikeOperations(arrayWrapper);
-            }
+        return For(TypeConverter.ToObject(realm, value), forWrite);
+    }
+
+    public static ArrayOperations For(ObjectInstance instance, bool forWrite)
+    {
+        if (instance is JsArray { CanUseFastAccess: true } arrayInstance)
+        {
+            return new JsArrayOperations(arrayInstance);
+        }
+
+        if (instance is JsTypedArray typedArrayInstance)
+        {
+            return new JsTypedArrayOperations(typedArrayInstance);
+        }
 
-            if (instance is ObjectWrapper wrapper)
+        if (instance is ArrayLikeWrapper arrayWrapper)
+        {
+            return new ArrayLikeOperations(arrayWrapper);
+        }
+
+        if (instance is ObjectWrapper wrapper)
+        {
+            var descriptor = wrapper._typeDescriptor;
+            if (descriptor.IsArrayLike && wrapper.Target is ICollection)
             {
-                var descriptor = wrapper._typeDescriptor;
-                if (descriptor.IsArrayLike && wrapper.Target is ICollection)
-                {
-                    return new IndexWrappedOperations(wrapper);
-                }
+                return new IndexWrappedOperations(wrapper);
             }
-
-            return new ObjectOperations(instance);
         }
 
-        public abstract ObjectInstance Target { get; }
+        return new ObjectOperations(instance);
+    }
 
-        public abstract ulong GetSmallestIndex(ulong length);
+    public abstract ObjectInstance Target { get; }
 
-        public abstract uint GetLength();
+    public abstract ulong GetSmallestIndex(ulong length);
 
-        public abstract ulong GetLongLength();
+    public abstract uint GetLength();
 
-        public abstract void SetLength(ulong length);
+    public abstract ulong GetLongLength();
 
-        public abstract void EnsureCapacity(ulong capacity);
+    public abstract void SetLength(ulong length);
 
-        public abstract JsValue Get(ulong index);
+    public abstract void EnsureCapacity(ulong capacity);
 
-        public virtual JsValue[] GetAll(
-            Types elementTypes = Types.Undefined | Types.Null | Types.Boolean | Types.String | Types.Symbol | Types.Number | Types.Object,
-            bool skipHoles = false)
+    public abstract JsValue Get(ulong index);
+
+    public virtual JsValue[] GetAll(
+        Types elementTypes = Types.Undefined | Types.Null | Types.Boolean | Types.String | Types.Symbol | Types.Number | Types.Object,
+        bool skipHoles = false)
+    {
+        uint writeIndex = 0;
+        var n = (int) GetLength();
+        var jsValues = new JsValue[n];
+        for (uint i = 0; i < (uint) jsValues.Length; i++)
         {
-            uint writeIndex = 0;
-            var n = (int) GetLength();
-            var jsValues = new JsValue[n];
-            for (uint i = 0; i < (uint) jsValues.Length; i++)
+            var jsValue = skipHoles && !HasProperty(i) ? JsValue.Undefined : Get(i);
+            if ((jsValue.Type & elementTypes) == Types.Empty)
             {
-                var jsValue = skipHoles && !HasProperty(i) ? JsValue.Undefined : Get(i);
-                if ((jsValue.Type & elementTypes) == Types.Empty)
-                {
-                    ExceptionHelper.ThrowTypeErrorNoEngine("invalid type");
-                }
-
-                jsValues[writeIndex++] = jsValue;
+                ExceptionHelper.ThrowTypeErrorNoEngine("invalid type");
             }
 
-            return jsValues;
+            jsValues[writeIndex++] = jsValue;
         }
 
-        public abstract bool TryGetValue(ulong index, out JsValue value);
+        return jsValues;
+    }
 
-        public abstract bool HasProperty(ulong index);
+    public abstract bool TryGetValue(ulong index, out JsValue value);
 
-        public abstract void CreateDataPropertyOrThrow(ulong index, JsValue value);
+    public abstract bool HasProperty(ulong index);
 
-        public abstract void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true);
+    public abstract void CreateDataPropertyOrThrow(ulong index, JsValue value);
 
-        public abstract void DeletePropertyOrThrow(ulong index);
+    public abstract void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true);
 
-        public ArrayLikeIterator GetEnumerator() => new ArrayLikeIterator(this);
+    public abstract void DeletePropertyOrThrow(ulong index);
 
-        IEnumerator<JsValue> IEnumerable<JsValue>.GetEnumerator() => new ArrayLikeIterator(this);
+    public ArrayLikeIterator GetEnumerator() => new ArrayLikeIterator(this);
 
-        IEnumerator IEnumerable.GetEnumerator() => new ArrayLikeIterator(this);
+    IEnumerator<JsValue> IEnumerable<JsValue>.GetEnumerator() => new ArrayLikeIterator(this);
 
-        internal sealed class ArrayLikeIterator : IEnumerator<JsValue>
-        {
-            private readonly ArrayOperations _obj;
-            private ulong _current;
-            private bool _initialized;
-            private readonly uint _length;
+    IEnumerator IEnumerable.GetEnumerator() => new ArrayLikeIterator(this);
 
-            public ArrayLikeIterator(ArrayOperations obj)
-            {
-                _obj = obj;
-                _length = obj.GetLength();
+    internal sealed class ArrayLikeIterator : IEnumerator<JsValue>
+    {
+        private readonly ArrayOperations _obj;
+        private ulong _current;
+        private bool _initialized;
+        private readonly uint _length;
 
-                Reset();
-            }
+        public ArrayLikeIterator(ArrayOperations obj)
+        {
+            _obj = obj;
+            _length = obj.GetLength();
 
-            public JsValue Current
+            Reset();
+        }
+
+        public JsValue Current
+        {
+            get
             {
-                get
-                {
-                    return !_initialized
-                        ? JsValue.Undefined
-                        : _obj.TryGetValue(_current, out var temp)
-                            ? temp
-                            : JsValue.Undefined;
-                }
+                return !_initialized
+                    ? JsValue.Undefined
+                    : _obj.TryGetValue(_current, out var temp)
+                        ? temp
+                        : JsValue.Undefined;
             }
+        }
 
-            object? IEnumerator.Current => Current;
+        object? IEnumerator.Current => Current;
 
-            public void Dispose()
-            {
-            }
+        public void Dispose()
+        {
+        }
 
-            public bool MoveNext()
+        public bool MoveNext()
+        {
+            if (!_initialized)
             {
-                if (!_initialized)
-                {
-                    _initialized = true;
-                }
-                else
-                {
-                    _current++;
-                }
-
-                return _current < _length;
+                _initialized = true;
             }
-
-            public void Reset()
+            else
             {
-                _initialized = false;
-                _current = 0;
+                _current++;
             }
+
+            return _current < _length;
         }
 
-        private sealed class ObjectOperations : ArrayOperations<ObjectInstance>
+        public void Reset()
         {
-            public ObjectOperations(ObjectInstance target) : base(target)
+            _initialized = false;
+            _current = 0;
+        }
+    }
+
+    private sealed class ObjectOperations : ArrayOperations<ObjectInstance>
+    {
+        public ObjectOperations(ObjectInstance target) : base(target)
+        {
+        }
+
+        private double GetIntegerLength()
+        {
+            var descValue = _target.Get(CommonProperties.Length);
+            if (descValue is not null)
             {
+                return TypeConverter.ToInteger(descValue);
             }
 
-            private double GetIntegerLength()
-            {
-                var descValue = _target.Get(CommonProperties.Length);
-                if (descValue is not null)
-                {
-                    return TypeConverter.ToInteger(descValue);
-                }
+            return 0;
+        }
 
-                return 0;
-            }
+        public override ulong GetSmallestIndex(ulong length)
+        {
+            return _target.GetSmallestIndex(length);
+        }
 
-            public override ulong GetSmallestIndex(ulong length)
-            {
-                return _target.GetSmallestIndex(length);
-            }
+        public override uint GetLength()
+        {
+            var integerLength = GetIntegerLength();
+            return (uint) (integerLength >= 0 ? integerLength : 0);
+        }
 
-            public override uint GetLength()
+        public override ulong GetLongLength()
+        {
+            var integerLength = GetIntegerLength();
+            if (integerLength <= 0)
             {
-                var integerLength = GetIntegerLength();
-                return (uint) (integerLength >= 0 ? integerLength : 0);
+                return 0;
             }
 
-            public override ulong GetLongLength()
-            {
-                var integerLength = GetIntegerLength();
-                if (integerLength <= 0)
-                {
-                    return 0;
-                }
+            return (ulong) System.Math.Min(integerLength, MaxArrayLikeLength);
+        }
 
-                return (ulong) System.Math.Min(integerLength, MaxArrayLikeLength);
-            }
+        public override void SetLength(ulong length)
+            => _target.Set(CommonProperties.Length, length, true);
 
-            public override void SetLength(ulong length)
-                => _target.Set(CommonProperties.Length, length, true);
+        public override void EnsureCapacity(ulong capacity)
+        {
+        }
 
-            public override void EnsureCapacity(ulong capacity)
-            {
-            }
+        public override JsValue Get(ulong index)
+            => _target.Get(JsString.Create(index));
 
-            public override JsValue Get(ulong index)
-                => _target.Get(JsString.Create(index));
+        public override bool TryGetValue(ulong index, out JsValue value)
+        {
+            var propertyName = JsString.Create(index);
+            var kPresent = _target.HasProperty(propertyName);
+            value = kPresent ? _target.Get(propertyName) : JsValue.Undefined;
+            return kPresent;
+        }
 
-            public override bool TryGetValue(ulong index, out JsValue value)
-            {
-                var propertyName = JsString.Create(index);
-                var kPresent = _target.HasProperty(propertyName);
-                value = kPresent ? _target.Get(propertyName) : JsValue.Undefined;
-                return kPresent;
-            }
+        public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
+            => _target.CreateDataPropertyOrThrow(JsString.Create(index), value);
 
-            public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
-                => _target.CreateDataPropertyOrThrow(JsString.Create(index), value);
+        public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
+            => _target.Set(JsString.Create(index), value, throwOnError);
 
-            public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
-                => _target.Set(JsString.Create(index), value, throwOnError);
+        public override void DeletePropertyOrThrow(ulong index)
+            => _target.DeletePropertyOrThrow(JsString.Create(index));
 
-            public override void DeletePropertyOrThrow(ulong index)
-                => _target.DeletePropertyOrThrow(JsString.Create(index));
+        public override bool HasProperty(ulong index) => Target.HasProperty(index);
+    }
 
-            public override bool HasProperty(ulong index) => Target.HasProperty(index);
+    private sealed class JsArrayOperations : ArrayOperations<JsArray>
+    {
+        public JsArrayOperations(JsArray target) : base(target)
+        {
         }
 
-        private sealed class JsArrayOperations : ArrayOperations<JsArray>
-        {
-            public JsArrayOperations(JsArray target) : base(target)
-            {
-            }
+        public override ulong GetSmallestIndex(ulong length)
+            => _target.GetSmallestIndex();
 
-            public override ulong GetSmallestIndex(ulong length)
-                => _target.GetSmallestIndex();
+        public override uint GetLength()
+            => (uint) ((JsNumber) _target._length!._value!)._value;
 
-            public override uint GetLength()
-                => (uint) ((JsNumber) _target._length!._value!)._value;
+        public override ulong GetLongLength()
+            => (ulong) ((JsNumber) _target._length!._value!)._value;
 
-            public override ulong GetLongLength()
-                => (ulong) ((JsNumber) _target._length!._value!)._value;
+        public override void SetLength(ulong length)
+            => _target.SetLength(length);
 
-            public override void SetLength(ulong length)
-                => _target.SetLength(length);
+        public override void EnsureCapacity(ulong capacity)
+            => _target.EnsureCapacity((uint) capacity);
 
-            public override void EnsureCapacity(ulong capacity)
-                => _target.EnsureCapacity((uint) capacity);
+        public override bool TryGetValue(ulong index, out JsValue value)
+            // array max size is uint
+            => _target.TryGetValue((uint) index, out value);
 
-            public override bool TryGetValue(ulong index, out JsValue value)
-                // array max size is uint
-                => _target.TryGetValue((uint) index, out value);
+        public override JsValue Get(ulong index) => _target.Get((uint) index);
 
-            public override JsValue Get(ulong index) => _target.Get((uint) index);
+        public override JsValue[] GetAll(Types elementTypes = Types.Undefined | Types.Null | Types.Boolean | Types.String | Types.Symbol | Types.Number | Types.Object, bool skipHoles = false)
+        {
+            var n = _target.GetLength();
 
-            public override JsValue[] GetAll(Types elementTypes = Types.Undefined | Types.Null | Types.Boolean | Types.String | Types.Symbol | Types.Number | Types.Object, bool skipHoles = false)
+            if (_target._dense == null || _target._dense.Length < n)
             {
-                var n = _target.GetLength();
+                return base.GetAll(elementTypes);
+            }
 
-                if (_target._dense == null || _target._dense.Length < n)
+            // optimized
+            uint writeIndex = 0;
+            var jsValues = new JsValue[n];
+            for (uint i = 0; i < (uint) jsValues.Length; i++)
+            {
+                var value = _target._dense[i];
+                if (value is null)
                 {
-                    return base.GetAll(elementTypes);
+                    value = _target.Prototype?.Get(i) ?? JsValue.Undefined;
                 }
 
-                // optimized
-                uint writeIndex = 0;
-                var jsValues = new JsValue[n];
-                for (uint i = 0; i < (uint) jsValues.Length; i++)
+                if ((value.Type & elementTypes) == Types.Empty)
                 {
-                    var value = _target._dense[i];
-                    if (value is null)
-                    {
-                        value = _target.Prototype?.Get(i) ?? JsValue.Undefined;
-                    }
-
-                    if ((value.Type & elementTypes) == Types.Empty)
-                    {
-                        ExceptionHelper.ThrowTypeErrorNoEngine("invalid type");
-                    }
-
-                    jsValues[writeIndex++] = (JsValue?) value ?? JsValue.Undefined;
+                    ExceptionHelper.ThrowTypeErrorNoEngine("invalid type");
                 }
 
-                return jsValues;
+                jsValues[writeIndex++] = (JsValue?) value ?? JsValue.Undefined;
             }
 
-            public override void DeletePropertyOrThrow(ulong index)
-                => _target.DeletePropertyOrThrow((uint) index);
+            return jsValues;
+        }
 
-            public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
-                => _target.SetIndexValue((uint) index, value, updateLength: false);
+        public override void DeletePropertyOrThrow(ulong index)
+            => _target.DeletePropertyOrThrow((uint) index);
 
-            public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
-                => _target.SetIndexValue((uint) index, value, updateLength);
+        public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
+            => _target.SetIndexValue((uint) index, value, updateLength: false);
 
-            public override bool HasProperty(ulong index) => _target.HasProperty(index);
-        }
+        public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
+            => _target.SetIndexValue((uint) index, value, updateLength);
+
+        public override bool HasProperty(ulong index) => _target.HasProperty(index);
+    }
+
+    private sealed class JsTypedArrayOperations : ArrayOperations
+    {
+        private readonly JsTypedArray _target;
 
-        private sealed class JsTypedArrayOperations : ArrayOperations
+        public JsTypedArrayOperations(JsTypedArray target)
         {
-            private readonly JsTypedArray _target;
+            _target = target;
+        }
 
-            public JsTypedArrayOperations(JsTypedArray target)
-            {
-                _target = target;
-            }
+        public override ObjectInstance Target => _target;
 
-            public override ObjectInstance Target => _target;
+        public override ulong GetSmallestIndex(ulong length) => 0;
 
-            public override ulong GetSmallestIndex(ulong length) => 0;
+        public override uint GetLength()
+        {
+            if (!_target.IsConcatSpreadable)
+            {
+                return _target.GetLength();
+            }
 
-            public override uint GetLength()
+            var descValue = _target.Get(CommonProperties.Length);
+            if (descValue is not null)
             {
-                if (!_target.IsConcatSpreadable)
-                {
-                    return _target.GetLength();
-                }
+                return (uint) TypeConverter.ToInteger(descValue);
+            }
 
-                var descValue = _target.Get(CommonProperties.Length);
-                if (descValue is not null)
-                {
-                    return (uint) TypeConverter.ToInteger(descValue);
-                }
+            return 0;
+        }
 
-                return 0;
-            }
+        public override ulong GetLongLength() => GetLength();
 
-            public override ulong GetLongLength() => GetLength();
+        public override void SetLength(ulong length)
+        {
+        }
 
-            public override void SetLength(ulong length)
-            {
-            }
+        public override void EnsureCapacity(ulong capacity)
+        {
+        }
+
+        public override JsValue Get(ulong index) => _target[(int) index];
 
-            public override void EnsureCapacity(ulong capacity)
+        public override bool TryGetValue(ulong index, out JsValue value)
+        {
+            if (_target.IsValidIntegerIndex(index))
             {
+                value = _target[(int) index];
+                return true;
             }
 
-            public override JsValue Get(ulong index) => _target[(int) index];
+            value = JsValue.Undefined;
+            return false;
+        }
 
-            public override bool TryGetValue(ulong index, out JsValue value)
-            {
-                if (_target.IsValidIntegerIndex(index))
-                {
-                    value = _target[(int) index];
-                    return true;
-                }
+        public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
+            => _target.CreateDataPropertyOrThrow(index, value);
 
-                value = JsValue.Undefined;
-                return false;
-            }
+        public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
+            => _target[(int) index] = value;
 
-            public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
-                => _target.CreateDataPropertyOrThrow(index, value);
+        public override void DeletePropertyOrThrow(ulong index)
+            => _target.DeletePropertyOrThrow(index);
 
-            public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
-                => _target[(int) index] = value;
+        public override bool HasProperty(ulong index) => _target.HasProperty(index);
+    }
 
-            public override void DeletePropertyOrThrow(ulong index)
-                => _target.DeletePropertyOrThrow(index);
+    private sealed class JsStringOperations : ArrayOperations
+    {
+        private readonly Realm _realm;
+        private readonly JsString _target;
+        private ObjectInstance? _wrappedTarget;
 
-            public override bool HasProperty(ulong index) => _target.HasProperty(index);
+        public JsStringOperations(Realm realm, JsString target)
+        {
+            _realm = realm;
+            _target = target;
         }
 
-        private sealed class JsStringOperations : ArrayOperations
+        public JsStringOperations(Realm realm, StringInstance stringInstance) : this(realm, stringInstance.StringData)
         {
-            private readonly Realm _realm;
-            private readonly JsString _target;
-            private ObjectInstance? _wrappedTarget;
+            _wrappedTarget = stringInstance;
+        }
 
-            public JsStringOperations(Realm realm, JsString target)
-            {
-                _realm = realm;
-                _target = target;
-            }
+        public override ObjectInstance Target => _wrappedTarget ??= _realm.Intrinsics.String.Construct(_target);
 
-            public JsStringOperations(Realm realm, StringInstance stringInstance) : this(realm, stringInstance.StringData)
-            {
-                _wrappedTarget = stringInstance;
-            }
+        public override ulong GetSmallestIndex(ulong length) => 0;
 
-            public override ObjectInstance Target => _wrappedTarget ??= _realm.Intrinsics.String.Construct(_target);
+        public override uint GetLength() => (uint) _target.Length;
 
-            public override ulong GetSmallestIndex(ulong length) => 0;
+        public override ulong GetLongLength() => GetLength();
 
-            public override uint GetLength() => (uint) _target.Length;
+        public override void SetLength(ulong length) => throw new NotSupportedException();
 
-            public override ulong GetLongLength() => GetLength();
+        public override void EnsureCapacity(ulong capacity)
+        {
+        }
 
-            public override void SetLength(ulong length) => throw new NotSupportedException();
+        public override JsValue Get(ulong index) => index < (ulong) _target.Length ? _target[(int) index] : JsValue.Undefined;
 
-            public override void EnsureCapacity(ulong capacity)
+        public override bool TryGetValue(ulong index, out JsValue value)
+        {
+            if (index < (ulong) _target.Length)
             {
+                value = _target[(int) index];
+                return true;
             }
 
-            public override JsValue Get(ulong index) => index < (ulong) _target.Length ? _target[(int) index] : JsValue.Undefined;
+            value = JsValue.Undefined;
+            return false;
+        }
 
-            public override bool TryGetValue(ulong index, out JsValue value)
-            {
-                if (index < (ulong) _target.Length)
-                {
-                    value = _target[(int) index];
-                    return true;
-                }
+        public override bool HasProperty(ulong index) => index < (ulong) _target.Length;
 
-                value = JsValue.Undefined;
-                return false;
-            }
+        public override void CreateDataPropertyOrThrow(ulong index, JsValue value) => throw new NotSupportedException();
 
-            public override bool HasProperty(ulong index) => index < (ulong) _target.Length;
+        public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true) => throw new NotSupportedException();
 
-            public override void CreateDataPropertyOrThrow(ulong index, JsValue value) => throw new NotSupportedException();
+        public override void DeletePropertyOrThrow(ulong index) => throw new NotSupportedException();
+    }
 
-            public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true) => throw new NotSupportedException();
+    private sealed class ArrayReadOperations : ArrayOperations
+    {
+        private readonly JsArray _target;
+        private readonly JsValue?[] _data;
+        private readonly uint _length;
 
-            public override void DeletePropertyOrThrow(ulong index) => throw new NotSupportedException();
+        public ArrayReadOperations(JsArray target)
+        {
+            _target = target;
+            _data = target._dense ?? System.Array.Empty<JsValue>();
+            _length = target.Length;
         }
 
-        private sealed class ArrayReadOperations : ArrayOperations
-        {
-            private readonly JsArray _target;
-            private readonly JsValue?[] _data;
-            private readonly uint _length;
+        public override ObjectInstance Target => _target;
 
-            public ArrayReadOperations(JsArray target)
-            {
-                _target = target;
-                _data = target._dense ?? System.Array.Empty<JsValue>();
-                _length = target.Length;
-            }
+        public override ulong GetSmallestIndex(ulong length) => 0;
 
-            public override ObjectInstance Target => _target;
+        public override uint GetLength() => _length;
 
-            public override ulong GetSmallestIndex(ulong length) => 0;
+        public override ulong GetLongLength() => _length;
 
-            public override uint GetLength() => _length;
+        public override void SetLength(ulong length) => throw new NotSupportedException();
 
-            public override ulong GetLongLength() => _length;
+        public override void EnsureCapacity(ulong capacity)
+        {
+        }
 
-            public override void SetLength(ulong length) => throw new NotSupportedException();
+        public override JsValue Get(ulong index) => (index < (ulong) _data.Length ? _data[(int) index] : JsValue.Undefined) ?? JsValue.Undefined;
 
-            public override void EnsureCapacity(ulong capacity)
+        public override bool TryGetValue(ulong index, out JsValue value)
+        {
+            if (index < _length)
             {
+                value = _data[(int) index]!;
+                return value is not null;
             }
 
-            public override JsValue Get(ulong index) => (index < (ulong) _data.Length ? _data[(int) index] : JsValue.Undefined) ?? JsValue.Undefined;
-
-            public override bool TryGetValue(ulong index, out JsValue value)
-            {
-                if (index < _length)
-                {
-                    value = _data[(int) index]!;
-                    return value is not null;
-                }
+            value = JsValue.Undefined;
+            return false;
+        }
 
-                value = JsValue.Undefined;
-                return false;
-            }
+        public override bool HasProperty(ulong index) => index < _length && _data[index] is not null;
 
-            public override bool HasProperty(ulong index) => index < _length && _data[index] is not null;
+        public override void CreateDataPropertyOrThrow(ulong index, JsValue value) => throw new NotSupportedException();
 
-            public override void CreateDataPropertyOrThrow(ulong index, JsValue value) => throw new NotSupportedException();
+        public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true) => throw new NotSupportedException();
 
-            public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true) => throw new NotSupportedException();
+        public override void DeletePropertyOrThrow(ulong index) => throw new NotSupportedException();
+    }
 
-            public override void DeletePropertyOrThrow(ulong index) => throw new NotSupportedException();
-        }
+    private sealed class IndexWrappedOperations : ArrayOperations
+    {
+        private readonly ObjectWrapper _target;
+        private readonly ICollection _collection;
+        private readonly IList _list;
 
-        private sealed class IndexWrappedOperations : ArrayOperations
+        public IndexWrappedOperations(ObjectWrapper wrapper)
         {
-            private readonly ObjectWrapper _target;
-            private readonly ICollection _collection;
-            private readonly IList _list;
-
-            public IndexWrappedOperations(ObjectWrapper wrapper)
-            {
-                _target = wrapper;
-                _collection = (ICollection) wrapper.Target;
-                _list = (IList) wrapper.Target;
-            }
+            _target = wrapper;
+            _collection = (ICollection) wrapper.Target;
+            _list = (IList) wrapper.Target;
+        }
 
-            public override ObjectInstance Target => _target;
+        public override ObjectInstance Target => _target;
 
-            public override ulong GetSmallestIndex(ulong length) => 0;
+        public override ulong GetSmallestIndex(ulong length) => 0;
 
-            public override uint GetLength() => (uint) _collection.Count;
+        public override uint GetLength() => (uint) _collection.Count;
 
-            public override ulong GetLongLength() => GetLength();
+        public override ulong GetLongLength() => GetLength();
 
-            public override void SetLength(ulong length)
+        public override void SetLength(ulong length)
+        {
+            if (_list == null)
             {
-                if (_list == null)
-                {
-                    throw new NotSupportedException();
-                }
-                
-                while (_list.Count > (int) length)
-                {
-                    // shrink list to fit
-                    _list.RemoveAt(_list.Count - 1);
-                }
-                
-                while (_list.Count < (int) length)
-                {
-                    // expand list to fit
-                    _list.Add(null);
-                }
+                throw new NotSupportedException();
             }
 
-            public override void EnsureCapacity(ulong capacity)
+            while (_list.Count > (int) length)
             {
+                // shrink list to fit
+                _list.RemoveAt(_list.Count - 1);
             }
 
-            public override JsValue Get(ulong index) => index < (ulong) _collection.Count ? ReadValue((int) index) : JsValue.Undefined;
-
-            public override bool TryGetValue(ulong index, out JsValue value)
+            while (_list.Count < (int) length)
             {
-                if (index < (ulong) _collection.Count)
-                {
-                    value = ReadValue((int) index);
-                    return true;
-                }
-
-                value = JsValue.Undefined;
-                return false;
+                // expand list to fit
+                _list.Add(null);
             }
+        }
 
-            private JsValue ReadValue(int index)
-            {
-                if (_list is not null)
-                {
-                    return (uint) index < _list.Count ? JsValue.FromObject(_target.Engine, _list[index]) : JsValue.Undefined;
-                }
+        public override void EnsureCapacity(ulong capacity)
+        {
+        }
 
-                // via reflection is slow, but better than nothing
-                return JsValue.FromObject(_target.Engine, _target._typeDescriptor.IntegerIndexerProperty!.GetValue(Target, [index]));
-            }
+        public override JsValue Get(ulong index) => index < (ulong) _collection.Count ? ReadValue((int) index) : JsValue.Undefined;
 
-            public override bool HasProperty(ulong index) => index < (ulong) _collection.Count;
+        public override bool TryGetValue(ulong index, out JsValue value)
+        {
+            if (index < (ulong) _collection.Count)
+            {
+                value = ReadValue((int) index);
+                return true;
+            }
 
-            public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
-                => _target.CreateDataPropertyOrThrow(index, value);
+            value = JsValue.Undefined;
+            return false;
+        }
 
-            public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
+        private JsValue ReadValue(int index)
+        {
+            if (_list is not null)
             {
-                if (updateLength && _list != null && index >= (ulong) _list.Count)
-                {
-                    SetLength(index + 1);
-                }
-                
-                _target[(int) index] = value;
+                return (uint) index < _list.Count ? JsValue.FromObject(_target.Engine, _list[index]) : JsValue.Undefined;
             }
 
-            public override void DeletePropertyOrThrow(ulong index)
-                => _target.DeletePropertyOrThrow(index);
+            // via reflection is slow, but better than nothing
+            return JsValue.FromObject(_target.Engine, _target._typeDescriptor.IntegerIndexerProperty!.GetValue(Target, [index]));
         }
 
-        private sealed class ArrayLikeOperations : ArrayOperations
-        {
-            private readonly ArrayLikeWrapper _target;
+        public override bool HasProperty(ulong index) => index < (ulong) _collection.Count;
 
-            public ArrayLikeOperations(ArrayLikeWrapper wrapper)
+        public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
+            => _target.CreateDataPropertyOrThrow(index, value);
+
+        public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
+        {
+            if (updateLength && _list != null && index >= (ulong) _list.Count)
             {
-                _target = wrapper;
+                SetLength(index + 1);
             }
 
-            public override ObjectInstance Target => _target;
+            _target[(int) index] = value;
+        }
 
-            public override ulong GetSmallestIndex(ulong length) => 0;
+        public override void DeletePropertyOrThrow(ulong index)
+            => _target.DeletePropertyOrThrow(index);
+    }
 
-            public override uint GetLength() => (uint) _target.Length;
+    private sealed class ArrayLikeOperations : ArrayOperations
+    {
+        private readonly ArrayLikeWrapper _target;
 
-            public override ulong GetLongLength() => GetLength();
+        public ArrayLikeOperations(ArrayLikeWrapper wrapper)
+        {
+            _target = wrapper;
+        }
 
-            public override void SetLength(ulong length)
-            {
-                while (_target.Length > (int) length)
-                {
-                    // shrink list to fit
-                    _target.RemoveAt(_target.Length - 1);
-                }
-                
-                while (_target.Length < (int) length)
-                {
-                    // expand list to fit
-                    _target.AddDefault();
-                }
-            }
+        public override ObjectInstance Target => _target;
 
-            public override void EnsureCapacity(ulong capacity)
-            {
-                _target.EnsureCapacity((int)capacity);
-            }
+        public override ulong GetSmallestIndex(ulong length) => 0;
 
-            public override JsValue Get(ulong index) => index < (ulong) _target.Length ? ReadValue((int) index) : JsValue.Undefined;
+        public override uint GetLength() => (uint) _target.Length;
 
-            public override bool TryGetValue(ulong index, out JsValue value)
-            {
-                if (index < (ulong) _target.Length)
-                {
-                    value = ReadValue((int) index);
-                    return true;
-                }
+        public override ulong GetLongLength() => GetLength();
 
-                value = JsValue.Undefined;
-                return false;
+        public override void SetLength(ulong length)
+        {
+            while (_target.Length > (int) length)
+            {
+                // shrink list to fit
+                _target.RemoveAt(_target.Length - 1);
             }
 
-            private JsValue ReadValue(int index)
+            while (_target.Length < (int) length)
             {
-                return (uint) index < _target.Length ? JsValue.FromObject(_target.Engine, _target.GetAt(index)) : JsValue.Undefined;
+                // expand list to fit
+                _target.AddDefault();
             }
+        }
 
-            public override bool HasProperty(ulong index) => index < (ulong) _target.Length;
+        public override void EnsureCapacity(ulong capacity)
+        {
+            _target.EnsureCapacity((int)capacity);
+        }
 
-            public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
-                => _target.CreateDataPropertyOrThrow(index, value);
+        public override JsValue Get(ulong index) => index < (ulong) _target.Length ? ReadValue((int) index) : JsValue.Undefined;
 
-            public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
+        public override bool TryGetValue(ulong index, out JsValue value)
+        {
+            if (index < (ulong) _target.Length)
             {
-                _target.SetAt((int)index, value);
+                value = ReadValue((int) index);
+                return true;
             }
 
-            public override void DeletePropertyOrThrow(ulong index)
-                => _target.DeletePropertyOrThrow(index);
+            value = JsValue.Undefined;
+            return false;
         }
-    }
 
-    /// <summary>
-    ///     Adapter to use optimized array operations when possible.
-    ///     Gaps the difference between ArgumentsInstance and ArrayInstance.
-    /// </summary>
-    internal abstract class ArrayOperations<T> : ArrayOperations where T : ObjectInstance
-    {
-        protected readonly T _target;
+        private JsValue ReadValue(int index)
+        {
+            return (uint) index < _target.Length ? JsValue.FromObject(_target.Engine, _target.GetAt(index)) : JsValue.Undefined;
+        }
+
+        public override bool HasProperty(ulong index) => index < (ulong) _target.Length;
 
-        protected ArrayOperations(T target)
+        public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
+            => _target.CreateDataPropertyOrThrow(index, value);
+
+        public override void Set(ulong index, JsValue value, bool updateLength = false, bool throwOnError = true)
         {
-            _target = target;
+            _target.SetAt((int)index, value);
         }
 
-        public override ObjectInstance Target => _target;
+        public override void DeletePropertyOrThrow(ulong index)
+            => _target.DeletePropertyOrThrow(index);
+    }
+}
+
+/// <summary>
+///     Adapter to use optimized array operations when possible.
+///     Gaps the difference between ArgumentsInstance and ArrayInstance.
+/// </summary>
+internal abstract class ArrayOperations<T> : ArrayOperations where T : ObjectInstance
+{
+    protected readonly T _target;
+
+    protected ArrayOperations(T target)
+    {
+        _target = target;
     }
+
+    public override ObjectInstance Target => _target;
 }

文件差异内容过多而无法显示
+ 853 - 853
Jint/Native/Array/ArrayPrototype.cs


+ 47 - 48
Jint/Native/Boolean/BooleanConstructor.cs

@@ -3,66 +3,65 @@ using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 
-namespace Jint.Native.Boolean
+namespace Jint.Native.Boolean;
+
+internal sealed class BooleanConstructor : Constructor
 {
-    internal sealed class BooleanConstructor : Constructor
-    {
-        private static readonly JsString _functionName = new JsString("Boolean");
+    private static readonly JsString _functionName = new JsString("Boolean");
 
-        internal BooleanConstructor(
-            Engine engine,
-            Realm realm,
-            FunctionPrototype functionPrototype,
-            ObjectPrototype objectPrototype)
-            : base(engine, realm, _functionName)
-        {
-            _prototype = functionPrototype;
-            PrototypeObject = new BooleanPrototype(engine, realm, this, objectPrototype);
-            _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
-            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
-        }
+    internal BooleanConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype)
+        : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new BooleanPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
 
-        public BooleanPrototype PrototypeObject { get; }
+    public BooleanPrototype PrototypeObject { get; }
 
-        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+    protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+    {
+        if (arguments.Length == 0)
         {
-            if (arguments.Length == 0)
-            {
-                return false;
-            }
-
-            return TypeConverter.ToBoolean(arguments[0]);
+            return false;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
-        /// </summary>
-        public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
-        {
-            var b = TypeConverter.ToBoolean(arguments.At(0))
-                ? JsBoolean.True
-                : JsBoolean.False;
+        return TypeConverter.ToBoolean(arguments[0]);
+    }
 
-            if (newTarget.IsUndefined())
-            {
-                return Construct(b);
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
+    /// </summary>
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var b = TypeConverter.ToBoolean(arguments.At(0))
+            ? JsBoolean.True
+            : JsBoolean.False;
 
-            var o = OrdinaryCreateFromConstructor(
-                newTarget,
-                static intrinsics => intrinsics.Boolean.PrototypeObject,
-                static (engine, realm, state) => new BooleanInstance(engine, state!), b);
-            return o;
+        if (newTarget.IsUndefined())
+        {
+            return Construct(b);
         }
 
-        public BooleanInstance Construct(JsBoolean value)
+        var o = OrdinaryCreateFromConstructor(
+            newTarget,
+            static intrinsics => intrinsics.Boolean.PrototypeObject,
+            static (engine, realm, state) => new BooleanInstance(engine, state!), b);
+        return o;
+    }
+
+    public BooleanInstance Construct(JsBoolean value)
+    {
+        var instance = new BooleanInstance(Engine, value)
         {
-            var instance = new BooleanInstance(Engine, value)
-            {
-                _prototype = PrototypeObject
-            };
+            _prototype = PrototypeObject
+        };
 
-            return instance;
-        }
+        return instance;
     }
 }

+ 42 - 43
Jint/Native/Boolean/BooleanPrototype.cs

@@ -4,58 +4,57 @@ using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
-namespace Jint.Native.Boolean
+namespace Jint.Native.Boolean;
+
+/// <summary>
+///     http://www.ecma-international.org/ecma-262/5.1/#sec-15.6.4
+/// </summary>
+internal sealed class BooleanPrototype : BooleanInstance
 {
-    /// <summary>
-    ///     http://www.ecma-international.org/ecma-262/5.1/#sec-15.6.4
-    /// </summary>
-    internal sealed class BooleanPrototype : BooleanInstance
+    private readonly Realm _realm;
+    private readonly BooleanConstructor _constructor;
+
+    internal BooleanPrototype(
+        Engine engine,
+        Realm realm,
+        BooleanConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, JsBoolean.False)
     {
-        private readonly Realm _realm;
-        private readonly BooleanConstructor _constructor;
-
-        internal BooleanPrototype(
-            Engine engine,
-            Realm realm,
-            BooleanConstructor constructor,
-            ObjectPrototype objectPrototype) : base(engine, JsBoolean.False)
-        {
-            _prototype = objectPrototype;
-            _realm = realm;
-            _constructor = constructor;
-        }
+        _prototype = objectPrototype;
+        _realm = realm;
+        _constructor = constructor;
+    }
 
-        protected override void Initialize()
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(3, checkExistingKeys: false)
         {
-            var properties = new PropertyDictionary(3, checkExistingKeys: false)
-            {
-                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
-                ["toString"] = new PropertyDescriptor(new ClrFunction(Engine, "toString", ToBooleanString, 0, PropertyFlag.Configurable), true, false, true),
-                ["valueOf"] = new PropertyDescriptor(new ClrFunction(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true)
-            };
-            SetProperties(properties);
-        }
+            ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
+            ["toString"] = new PropertyDescriptor(new ClrFunction(Engine, "toString", ToBooleanString, 0, PropertyFlag.Configurable), true, false, true),
+            ["valueOf"] = new PropertyDescriptor(new ClrFunction(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true)
+        };
+        SetProperties(properties);
+    }
 
-        private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
+    private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
+    {
+        if (thisObject._type == InternalTypes.Boolean)
         {
-            if (thisObject._type == InternalTypes.Boolean)
-            {
-                return thisObject;
-            }
-
-            if (thisObject is BooleanInstance bi)
-            {
-                return bi.BooleanData;
-            }
-
-            ExceptionHelper.ThrowTypeError(_realm);
-            return Undefined;
+            return thisObject;
         }
 
-        private JsString ToBooleanString(JsValue thisObject, JsValue[] arguments)
+        if (thisObject is BooleanInstance bi)
         {
-            var b = ValueOf(thisObject, Arguments.Empty);
-            return ((JsBoolean) b)._value ? JsString.TrueString : JsString.FalseString;
+            return bi.BooleanData;
         }
+
+        ExceptionHelper.ThrowTypeError(_realm);
+        return Undefined;
+    }
+
+    private JsString ToBooleanString(JsValue thisObject, JsValue[] arguments)
+    {
+        var b = ValueOf(thisObject, Arguments.Empty);
+        return ((JsBoolean) b)._value ? JsString.TrueString : JsString.FalseString;
     }
 }

+ 79 - 80
Jint/Native/DataView/DataViewConstructor.cs

@@ -3,110 +3,109 @@ using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 
-namespace Jint.Native.DataView
+namespace Jint.Native.DataView;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-dataview-constructor
+/// </summary>
+internal sealed class DataViewConstructor : Constructor
 {
-    /// <summary>
-    /// https://tc39.es/ecma262/#sec-dataview-constructor
-    /// </summary>
-    internal sealed class DataViewConstructor : Constructor
+    private static readonly JsString _functionName = new("DataView");
+
+    internal DataViewConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype)
+        : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new DataViewPrototype(engine, this, objectPrototype);
+        _length = new PropertyDescriptor(1, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    private DataViewPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
     {
-        private static readonly JsString _functionName = new("DataView");
-
-        internal DataViewConstructor(
-            Engine engine,
-            Realm realm,
-            FunctionPrototype functionPrototype,
-            ObjectPrototype objectPrototype)
-            : base(engine, realm, _functionName)
+        if (newTarget.IsUndefined())
         {
-            _prototype = functionPrototype;
-            PrototypeObject = new DataViewPrototype(engine, this, objectPrototype);
-            _length = new PropertyDescriptor(1, PropertyFlag.Configurable);
-            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+            ExceptionHelper.ThrowTypeError(_realm);
         }
 
-        private DataViewPrototype PrototypeObject { get; }
+        var buffer = arguments.At(0) as JsArrayBuffer;
+        var byteOffset = arguments.At(1);
+        var byteLength = arguments.At(2);
 
-        public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        if (buffer is null)
         {
-            if (newTarget.IsUndefined())
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-
-            var buffer = arguments.At(0) as JsArrayBuffer;
-            var byteOffset = arguments.At(1);
-            var byteLength = arguments.At(2);
+            ExceptionHelper.ThrowTypeError(_realm, "First argument to DataView constructor must be an ArrayBuffer");
+        }
 
-            if (buffer is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "First argument to DataView constructor must be an ArrayBuffer");
-            }
+        var offset = TypeConverter.ToIndex(_realm, byteOffset);
 
-            var offset = TypeConverter.ToIndex(_realm, byteOffset);
+        if (buffer.IsDetachedBuffer)
+        {
+            ExceptionHelper.ThrowTypeError(_realm);
+        }
 
-            if (buffer.IsDetachedBuffer)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
+        var bufferByteLength = (uint) buffer.ArrayBufferByteLength;
+        if (offset > bufferByteLength)
+        {
+            ExceptionHelper.ThrowRangeError(_realm, "Start offset " + offset + " is outside the bounds of the buffer");
+        }
 
-            var bufferByteLength = (uint) buffer.ArrayBufferByteLength;
-            if (offset > bufferByteLength)
+        var bufferIsFixedLength = buffer.IsFixedLengthArrayBuffer;
+        uint viewByteLength;
+        if (byteLength.IsUndefined())
+        {
+            if (bufferIsFixedLength)
             {
-                ExceptionHelper.ThrowRangeError(_realm, "Start offset " + offset + " is outside the bounds of the buffer");
+                viewByteLength = bufferByteLength - offset;
             }
-
-            var bufferIsFixedLength = buffer.IsFixedLengthArrayBuffer;
-            uint viewByteLength;
-            if (byteLength.IsUndefined())
+            else
             {
-                if (bufferIsFixedLength)
-                {
-                    viewByteLength = bufferByteLength - offset;
-                }
-                else
-                {
-                    viewByteLength = JsTypedArray.LengthAuto;
-                }
+                viewByteLength = JsTypedArray.LengthAuto;
             }
-            else
+        }
+        else
+        {
+            viewByteLength = TypeConverter.ToIndex(_realm, byteLength);
+            if (offset + viewByteLength > bufferByteLength)
             {
-                viewByteLength = TypeConverter.ToIndex(_realm, byteLength);
-                if (offset + viewByteLength > bufferByteLength)
-                {
-                    ExceptionHelper.ThrowRangeError(_realm, "Invalid DataView length");
-                }
+                ExceptionHelper.ThrowRangeError(_realm, "Invalid DataView length");
             }
+        }
 
-            var o = OrdinaryCreateFromConstructor(
-                newTarget,
-                static intrinsics => intrinsics.DataView.PrototypeObject,
-                static (Engine engine, Realm _, object? _) => new JsDataView(engine));
+        var o = OrdinaryCreateFromConstructor(
+            newTarget,
+            static intrinsics => intrinsics.DataView.PrototypeObject,
+            static (Engine engine, Realm _, object? _) => new JsDataView(engine));
 
-            if (buffer.IsDetachedBuffer)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
+        if (buffer.IsDetachedBuffer)
+        {
+            ExceptionHelper.ThrowTypeError(_realm);
+        }
 
-            bufferByteLength = (uint) buffer.ArrayBufferByteLength;
-            if (offset > bufferByteLength)
-            {
-                ExceptionHelper.ThrowRangeError(_realm, "Invalid DataView offset");
-            }
+        bufferByteLength = (uint) buffer.ArrayBufferByteLength;
+        if (offset > bufferByteLength)
+        {
+            ExceptionHelper.ThrowRangeError(_realm, "Invalid DataView offset");
+        }
 
-            if (!byteLength.IsUndefined())
+        if (!byteLength.IsUndefined())
+        {
+            if (offset + viewByteLength > bufferByteLength)
             {
-                if (offset + viewByteLength > bufferByteLength)
-                {
-                    ExceptionHelper.ThrowRangeError(_realm, "Invalid DataView length");
-                }
+                ExceptionHelper.ThrowRangeError(_realm, "Invalid DataView length");
             }
+        }
 
-            o._viewedArrayBuffer = buffer;
-            o._byteLength = viewByteLength;
-            o._byteOffset = offset;
+        o._viewedArrayBuffer = buffer;
+        o._byteLength = viewByteLength;
+        o._byteOffset = offset;
 
-            return o;
-        }
+        return o;
     }
 }

+ 311 - 312
Jint/Native/DataView/DataViewPrototype.cs

@@ -9,396 +9,395 @@ using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
-namespace Jint.Native.DataView
+namespace Jint.Native.DataView;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-properties-of-the-dataview-prototype-object
+/// </summary>
+internal sealed class DataViewPrototype : Prototype
 {
+    private readonly DataViewConstructor _constructor;
+
+    internal DataViewPrototype(
+        Engine engine,
+        DataViewConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, engine.Realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        const PropertyFlag lengthFlags = PropertyFlag.Configurable;
+        const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
+        var properties = new PropertyDictionary(26, checkExistingKeys: false)
+        {
+            ["buffer"] = new GetSetPropertyDescriptor(new ClrFunction(_engine, "get buffer", Buffer, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
+            ["byteLength"] = new GetSetPropertyDescriptor(new ClrFunction(_engine, "get byteLength", ByteLength, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
+            ["byteOffset"] = new GetSetPropertyDescriptor(new ClrFunction(Engine, "get byteOffset", ByteOffset, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
+            ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
+            ["getBigInt64"] = new PropertyDescriptor(new ClrFunction(Engine, "getBigInt64", GetBigInt64, length: 1, lengthFlags), propertyFlags),
+            ["getBigUint64"] = new PropertyDescriptor(new ClrFunction(Engine, "getBigUint64", GetBigUint64, length: 1, lengthFlags), propertyFlags),
+            ["getFloat16"] = new PropertyDescriptor(new ClrFunction(Engine, "getFloat16", GetFloat16, length: 1, lengthFlags), propertyFlags),
+            ["getFloat32"] = new PropertyDescriptor(new ClrFunction(Engine, "getFloat32", GetFloat32, length: 1, lengthFlags), propertyFlags),
+            ["getFloat64"] = new PropertyDescriptor(new ClrFunction(Engine, "getFloat64", GetFloat64, length: 1, lengthFlags), propertyFlags),
+            ["getInt8"] = new PropertyDescriptor(new ClrFunction(Engine, "getInt8", GetInt8, length: 1, lengthFlags), propertyFlags),
+            ["getInt16"] = new PropertyDescriptor(new ClrFunction(Engine, "getInt16", GetInt16, length: 1, lengthFlags), propertyFlags),
+            ["getInt32"] = new PropertyDescriptor(new ClrFunction(Engine, "getInt32", GetInt32, length: 1, lengthFlags), propertyFlags),
+            ["getUint8"] = new PropertyDescriptor(new ClrFunction(Engine, "getUint8", GetUint8, length: 1, lengthFlags), propertyFlags),
+            ["getUint16"] = new PropertyDescriptor(new ClrFunction(Engine, "getUint16", GetUint16, length: 1, lengthFlags), propertyFlags),
+            ["getUint32"] = new PropertyDescriptor(new ClrFunction(Engine, "getUint32", GetUint32, length: 1, lengthFlags), propertyFlags),
+            ["setBigInt64"] = new PropertyDescriptor(new ClrFunction(Engine, "setBigInt64", SetBigInt64, length: 2, lengthFlags), propertyFlags),
+            ["setBigUint64"] = new PropertyDescriptor(new ClrFunction(Engine, "setBigUint64", SetBigUint64, length: 2, lengthFlags), propertyFlags),
+            ["setFloat16"] = new PropertyDescriptor(new ClrFunction(Engine, "setFloat16", SetFloat16, length: 2, lengthFlags), propertyFlags),
+            ["setFloat32"] = new PropertyDescriptor(new ClrFunction(Engine, "setFloat32", SetFloat32, length: 2, lengthFlags), propertyFlags),
+            ["setFloat64"] = new PropertyDescriptor(new ClrFunction(Engine, "setFloat64", SetFloat64, length: 2, lengthFlags), propertyFlags),
+            ["setInt8"] = new PropertyDescriptor(new ClrFunction(Engine, "setInt8", SetInt8, length: 2, lengthFlags), propertyFlags),
+            ["setInt16"] = new PropertyDescriptor(new ClrFunction(Engine, "setInt16", SetInt16, length: 2, lengthFlags), propertyFlags),
+            ["setInt32"] = new PropertyDescriptor(new ClrFunction(Engine, "setInt32", SetInt32, length: 2, lengthFlags), propertyFlags),
+            ["setUint8"] = new PropertyDescriptor(new ClrFunction(Engine, "setUint8", SetUint8, length: 2, lengthFlags), propertyFlags),
+            ["setUint16"] = new PropertyDescriptor(new ClrFunction(Engine, "setUint16", SetUint16, length: 2, lengthFlags), propertyFlags),
+            ["setUint32"] = new PropertyDescriptor(new ClrFunction(Engine, "setUint32", SetUint32, length: 2, lengthFlags), propertyFlags)
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1) { [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("DataView", PropertyFlag.Configurable) };
+        SetSymbols(symbols);
+    }
+
     /// <summary>
-    /// https://tc39.es/ecma262/#sec-properties-of-the-dataview-prototype-object
+    /// https://tc39.es/ecma262/#sec-get-dataview.prototype.buffer
     /// </summary>
-    internal sealed class DataViewPrototype : Prototype
+    private JsValue Buffer(JsValue thisObject, JsValue[] arguments)
     {
-        private readonly DataViewConstructor _constructor;
-
-        internal DataViewPrototype(
-            Engine engine,
-            DataViewConstructor constructor,
-            ObjectPrototype objectPrototype) : base(engine, engine.Realm)
+        var o = thisObject as JsDataView;
+        if (o is null)
         {
-            _prototype = objectPrototype;
-            _constructor = constructor;
+            ExceptionHelper.ThrowTypeError(_realm, "Method get DataView.prototype.buffer called on incompatible receiver " + thisObject);
         }
 
-        protected override void Initialize()
+        return o._viewedArrayBuffer!;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-get-dataview.prototype.bytelength
+    /// </summary>
+    private JsValue ByteLength(JsValue thisObject, JsValue[] arguments)
+    {
+        var o = thisObject as JsDataView;
+        if (o is null)
         {
-            const PropertyFlag lengthFlags = PropertyFlag.Configurable;
-            const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
-            var properties = new PropertyDictionary(26, checkExistingKeys: false)
-            {
-                ["buffer"] = new GetSetPropertyDescriptor(new ClrFunction(_engine, "get buffer", Buffer, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
-                ["byteLength"] = new GetSetPropertyDescriptor(new ClrFunction(_engine, "get byteLength", ByteLength, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
-                ["byteOffset"] = new GetSetPropertyDescriptor(new ClrFunction(Engine, "get byteOffset", ByteOffset, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
-                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
-                ["getBigInt64"] = new PropertyDescriptor(new ClrFunction(Engine, "getBigInt64", GetBigInt64, length: 1, lengthFlags), propertyFlags),
-                ["getBigUint64"] = new PropertyDescriptor(new ClrFunction(Engine, "getBigUint64", GetBigUint64, length: 1, lengthFlags), propertyFlags),
-                ["getFloat16"] = new PropertyDescriptor(new ClrFunction(Engine, "getFloat16", GetFloat16, length: 1, lengthFlags), propertyFlags),
-                ["getFloat32"] = new PropertyDescriptor(new ClrFunction(Engine, "getFloat32", GetFloat32, length: 1, lengthFlags), propertyFlags),
-                ["getFloat64"] = new PropertyDescriptor(new ClrFunction(Engine, "getFloat64", GetFloat64, length: 1, lengthFlags), propertyFlags),
-                ["getInt8"] = new PropertyDescriptor(new ClrFunction(Engine, "getInt8", GetInt8, length: 1, lengthFlags), propertyFlags),
-                ["getInt16"] = new PropertyDescriptor(new ClrFunction(Engine, "getInt16", GetInt16, length: 1, lengthFlags), propertyFlags),
-                ["getInt32"] = new PropertyDescriptor(new ClrFunction(Engine, "getInt32", GetInt32, length: 1, lengthFlags), propertyFlags),
-                ["getUint8"] = new PropertyDescriptor(new ClrFunction(Engine, "getUint8", GetUint8, length: 1, lengthFlags), propertyFlags),
-                ["getUint16"] = new PropertyDescriptor(new ClrFunction(Engine, "getUint16", GetUint16, length: 1, lengthFlags), propertyFlags),
-                ["getUint32"] = new PropertyDescriptor(new ClrFunction(Engine, "getUint32", GetUint32, length: 1, lengthFlags), propertyFlags),
-                ["setBigInt64"] = new PropertyDescriptor(new ClrFunction(Engine, "setBigInt64", SetBigInt64, length: 2, lengthFlags), propertyFlags),
-                ["setBigUint64"] = new PropertyDescriptor(new ClrFunction(Engine, "setBigUint64", SetBigUint64, length: 2, lengthFlags), propertyFlags),
-                ["setFloat16"] = new PropertyDescriptor(new ClrFunction(Engine, "setFloat16", SetFloat16, length: 2, lengthFlags), propertyFlags),
-                ["setFloat32"] = new PropertyDescriptor(new ClrFunction(Engine, "setFloat32", SetFloat32, length: 2, lengthFlags), propertyFlags),
-                ["setFloat64"] = new PropertyDescriptor(new ClrFunction(Engine, "setFloat64", SetFloat64, length: 2, lengthFlags), propertyFlags),
-                ["setInt8"] = new PropertyDescriptor(new ClrFunction(Engine, "setInt8", SetInt8, length: 2, lengthFlags), propertyFlags),
-                ["setInt16"] = new PropertyDescriptor(new ClrFunction(Engine, "setInt16", SetInt16, length: 2, lengthFlags), propertyFlags),
-                ["setInt32"] = new PropertyDescriptor(new ClrFunction(Engine, "setInt32", SetInt32, length: 2, lengthFlags), propertyFlags),
-                ["setUint8"] = new PropertyDescriptor(new ClrFunction(Engine, "setUint8", SetUint8, length: 2, lengthFlags), propertyFlags),
-                ["setUint16"] = new PropertyDescriptor(new ClrFunction(Engine, "setUint16", SetUint16, length: 2, lengthFlags), propertyFlags),
-                ["setUint32"] = new PropertyDescriptor(new ClrFunction(Engine, "setUint32", SetUint32, length: 2, lengthFlags), propertyFlags)
-            };
-            SetProperties(properties);
-
-            var symbols = new SymbolDictionary(1) { [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("DataView", PropertyFlag.Configurable) };
-            SetSymbols(symbols);
+            ExceptionHelper.ThrowTypeError(_realm, "Method get DataView.prototype.byteLength called on incompatible receiver " + thisObject);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-get-dataview.prototype.buffer
-        /// </summary>
-        private JsValue Buffer(JsValue thisObject, JsValue[] arguments)
+        var viewRecord = MakeDataViewWithBufferWitnessRecord(o, ArrayBufferOrder.SeqCst);
+        if (viewRecord.IsViewOutOfBounds)
         {
-            var o = thisObject as JsDataView;
-            if (o is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Method get DataView.prototype.buffer called on incompatible receiver " + thisObject);
-            }
+            ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
+        }
+
+        var buffer = o._viewedArrayBuffer!;
+        buffer.AssertNotDetached();
 
-            return o._viewedArrayBuffer!;
+        return JsNumber.Create(viewRecord.ViewByteLength);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-get-dataview.prototype.byteoffset
+    /// </summary>
+    private JsValue ByteOffset(JsValue thisObject, JsValue[] arguments)
+    {
+        var o = thisObject as JsDataView;
+        if (o is null)
+        {
+            ExceptionHelper.ThrowTypeError(_realm, "Method get DataView.prototype.byteOffset called on incompatible receiver " + thisObject);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-get-dataview.prototype.bytelength
-        /// </summary>
-        private JsValue ByteLength(JsValue thisObject, JsValue[] arguments)
+        var viewRecord = MakeDataViewWithBufferWitnessRecord(o, ArrayBufferOrder.SeqCst);
+        if (viewRecord.IsViewOutOfBounds)
         {
-            var o = thisObject as JsDataView;
-            if (o is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Method get DataView.prototype.byteLength called on incompatible receiver " + thisObject);
-            }
+            ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
+        }
 
-            var viewRecord = MakeDataViewWithBufferWitnessRecord(o, ArrayBufferOrder.SeqCst);
-            if (viewRecord.IsViewOutOfBounds)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
-            }
+        var buffer = o._viewedArrayBuffer!;
+        buffer.AssertNotDetached();
 
-            var buffer = o._viewedArrayBuffer!;
-            buffer.AssertNotDetached();
+        return JsNumber.Create(o._byteOffset);
+    }
 
-            return JsNumber.Create(viewRecord.ViewByteLength);
-        }
+    private JsValue GetBigInt64(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1), TypedArrayElementType.BigInt64);
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-get-dataview.prototype.byteoffset
-        /// </summary>
-        private JsValue ByteOffset(JsValue thisObject, JsValue[] arguments)
-        {
-            var o = thisObject as JsDataView;
-            if (o is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Method get DataView.prototype.byteOffset called on incompatible receiver " + thisObject);
-            }
+    private JsValue GetBigUint64(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1), TypedArrayElementType.BigUint64);
+    }
 
-            var viewRecord = MakeDataViewWithBufferWitnessRecord(o, ArrayBufferOrder.SeqCst);
-            if (viewRecord.IsViewOutOfBounds)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
-            }
+    private JsValue GetFloat16(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Float16);
+    }
 
-            var buffer = o._viewedArrayBuffer!;
-            buffer.AssertNotDetached();
+    private JsValue GetFloat32(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Float32);
+    }
 
-            return JsNumber.Create(o._byteOffset);
-        }
+    private JsValue GetFloat64(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Float64);
+    }
 
-        private JsValue GetBigInt64(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1), TypedArrayElementType.BigInt64);
-        }
+    private JsValue GetInt8(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Int8);
+    }
 
-        private JsValue GetBigUint64(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1), TypedArrayElementType.BigUint64);
-        }
+    private JsValue GetInt16(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Int16);
+    }
 
-        private JsValue GetFloat16(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Float16);
-        }
+    private JsValue GetInt32(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Int32);
+    }
 
-        private JsValue GetFloat32(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Float32);
-        }
+    private JsValue GetUint8(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Uint8);
+    }
 
-        private JsValue GetFloat64(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Float64);
-        }
+    private JsValue GetUint16(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Uint16);
+    }
 
-        private JsValue GetInt8(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Int8);
-        }
+    private JsValue GetUint32(JsValue thisObject, JsValue[] arguments)
+    {
+        return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Uint32);
+    }
 
-        private JsValue GetInt16(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Int16);
-        }
+    private JsValue SetBigInt64(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2), TypedArrayElementType.BigInt64, arguments.At(1));
+    }
 
-        private JsValue GetInt32(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Int32);
-        }
+    private JsValue SetBigUint64(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2), TypedArrayElementType.BigUint64, arguments.At(1));
+    }
 
-        private JsValue GetUint8(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Uint8);
-        }
+    private JsValue SetFloat16(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Float16, arguments.At(1));
+    }
 
-        private JsValue GetUint16(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Uint16);
-        }
+    private JsValue SetFloat32(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Float32, arguments.At(1));
+    }
 
-        private JsValue GetUint32(JsValue thisObject, JsValue[] arguments)
-        {
-            return GetViewValue(thisObject, arguments.At(0), arguments.At(1, JsBoolean.False), TypedArrayElementType.Uint32);
-        }
+    private JsValue SetFloat64(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Float64, arguments.At(1));
+    }
 
-        private JsValue SetBigInt64(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2), TypedArrayElementType.BigInt64, arguments.At(1));
-        }
+    private JsValue SetInt8(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Int8, arguments.At(1));
+    }
 
-        private JsValue SetBigUint64(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2), TypedArrayElementType.BigUint64, arguments.At(1));
-        }
+    private JsValue SetInt16(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Int16, arguments.At(1));
+    }
 
-        private JsValue SetFloat16(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Float16, arguments.At(1));
-        }
+    private JsValue SetInt32(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Int32, arguments.At(1));
+    }
 
-        private JsValue SetFloat32(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Float32, arguments.At(1));
-        }
+    private JsValue SetUint8(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Uint8, arguments.At(1));
+    }
 
-        private JsValue SetFloat64(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Float64, arguments.At(1));
-        }
+    private JsValue SetUint16(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Uint16, arguments.At(1));
+    }
 
-        private JsValue SetInt8(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Int8, arguments.At(1));
-        }
+    private JsValue SetUint32(JsValue thisObject, JsValue[] arguments)
+    {
+        return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Uint32, arguments.At(1));
+    }
 
-        private JsValue SetInt16(JsValue thisObject, JsValue[] arguments)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-getviewvalue
+    /// </summary>
+    private JsValue GetViewValue(
+        JsValue view,
+        JsValue requestIndex,
+        JsValue isLittleEndian,
+        TypedArrayElementType type)
+    {
+        if (view is not JsDataView dataView)
         {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Int16, arguments.At(1));
+            ExceptionHelper.ThrowTypeError(_realm, "Method called on incompatible receiver " + view);
+            return Undefined;
         }
 
-        private JsValue SetInt32(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Int32, arguments.At(1));
-        }
+        var getIndex = (int) TypeConverter.ToIndex(_realm, requestIndex);
+        var isLittleEndianBoolean = TypeConverter.ToBoolean(isLittleEndian);
+        var buffer = dataView._viewedArrayBuffer!;
 
-        private JsValue SetUint8(JsValue thisObject, JsValue[] arguments)
-        {
-            return SetViewValue(thisObject, arguments.At(0), JsBoolean.True, TypedArrayElementType.Uint8, arguments.At(1));
-        }
+        buffer.AssertNotDetached();
 
-        private JsValue SetUint16(JsValue thisObject, JsValue[] arguments)
+        var viewOffset = dataView._byteOffset;
+        var viewRecord = MakeDataViewWithBufferWitnessRecord(dataView, ArrayBufferOrder.Unordered);
+        if (viewRecord.IsViewOutOfBounds)
         {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Uint16, arguments.At(1));
+            ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
         }
 
-        private JsValue SetUint32(JsValue thisObject, JsValue[] arguments)
+        var viewSize = viewRecord.ViewByteLength;
+        var elementSize = type.GetElementSize();
+        if (getIndex + elementSize > viewSize)
         {
-            return SetViewValue(thisObject, arguments.At(0), arguments.At(2, JsBoolean.False), TypedArrayElementType.Uint32, arguments.At(1));
+            ExceptionHelper.ThrowRangeError(_realm, "Offset is outside the bounds of the DataView");
         }
 
+        var bufferIndex = (int) (getIndex + viewOffset);
+        return buffer.GetValueFromBuffer(bufferIndex, type, isTypedArray: false, ArrayBufferOrder.Unordered, isLittleEndianBoolean).ToJsValue();
+    }
+
+    internal readonly record struct DataViewWithBufferWitnessRecord(JsDataView Object, int CachedBufferByteLength)
+    {
         /// <summary>
-        /// https://tc39.es/ecma262/#sec-getviewvalue
+        /// https://tc39.es/ecma262/#sec-isviewoutofbounds
         /// </summary>
-        private JsValue GetViewValue(
-            JsValue view,
-            JsValue requestIndex,
-            JsValue isLittleEndian,
-            TypedArrayElementType type)
+        public bool IsViewOutOfBounds
         {
-            if (view is not JsDataView dataView)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Method called on incompatible receiver " + view);
-                return Undefined;
-            }
-
-            var getIndex = (int) TypeConverter.ToIndex(_realm, requestIndex);
-            var isLittleEndianBoolean = TypeConverter.ToBoolean(isLittleEndian);
-            var buffer = dataView._viewedArrayBuffer!;
-
-            buffer.AssertNotDetached();
-
-            var viewOffset = dataView._byteOffset;
-            var viewRecord = MakeDataViewWithBufferWitnessRecord(dataView, ArrayBufferOrder.Unordered);
-            if (viewRecord.IsViewOutOfBounds)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
-            }
-
-            var viewSize = viewRecord.ViewByteLength;
-            var elementSize = type.GetElementSize();
-            if (getIndex + elementSize > viewSize)
+            get
             {
-                ExceptionHelper.ThrowRangeError(_realm, "Offset is outside the bounds of the DataView");
-            }
-
-            var bufferIndex = (int) (getIndex + viewOffset);
-            return buffer.GetValueFromBuffer(bufferIndex, type, isTypedArray: false, ArrayBufferOrder.Unordered, isLittleEndianBoolean).ToJsValue();
-        }
+                var view = Object;
+                var bufferByteLength = CachedBufferByteLength;
+                if (bufferByteLength == -1)
+                {
+                    return true;
+                }
 
-        internal readonly record struct DataViewWithBufferWitnessRecord(JsDataView Object, int CachedBufferByteLength)
-        {
-            /// <summary>
-            /// https://tc39.es/ecma262/#sec-isviewoutofbounds
-            /// </summary>
-            public bool IsViewOutOfBounds
-            {
-                get
+                var byteOffsetStart = view._byteOffset;
+                long byteOffsetEnd;
+                if (view._byteLength == JsTypedArray.LengthAuto)
                 {
-                    var view = Object;
-                    var bufferByteLength = CachedBufferByteLength;
-                    if (bufferByteLength == -1)
-                    {
-                        return true;
-                    }
-
-                    var byteOffsetStart = view._byteOffset;
-                    long byteOffsetEnd;
-                    if (view._byteLength == JsTypedArray.LengthAuto)
-                    {
-                        byteOffsetEnd = bufferByteLength;
-                    }
-                    else
-                    {
-                        byteOffsetEnd = byteOffsetStart + view._byteLength;
-                    }
-
-                    if (byteOffsetStart > bufferByteLength || byteOffsetEnd > bufferByteLength)
-                    {
-                        return true;
-                    }
-
-                    return false;
+                    byteOffsetEnd = bufferByteLength;
+                }
+                else
+                {
+                    byteOffsetEnd = byteOffsetStart + view._byteLength;
                 }
-            }
 
-            /// <summary>
-            /// https://tc39.es/ecma262/#sec-getviewbytelength
-            /// </summary>
-            public long ViewByteLength
-            {
-                get
+                if (byteOffsetStart > bufferByteLength || byteOffsetEnd > bufferByteLength)
                 {
-                    var view = Object;
-                    if (view._byteLength != JsTypedArray.LengthAuto)
-                    {
-                        return view._byteLength;
-                    }
-
-                    var byteOffset = view._byteOffset;
-                    var byteLength = CachedBufferByteLength;
-                    return byteLength - byteOffset;
+                    return true;
                 }
+
+                return false;
             }
         }
 
         /// <summary>
-        /// https://tc39.es/ecma262/#sec-makedataviewwithbufferwitnessrecord
+        /// https://tc39.es/ecma262/#sec-getviewbytelength
         /// </summary>
-        private static DataViewWithBufferWitnessRecord MakeDataViewWithBufferWitnessRecord(JsDataView obj, ArrayBufferOrder order)
+        public long ViewByteLength
         {
-            var buffer = obj._viewedArrayBuffer;
-            int byteLength;
-            if (buffer?.IsDetachedBuffer == true)
-            {
-                byteLength = -1;
-            }
-            else
+            get
             {
-                byteLength = IntrinsicTypedArrayPrototype.ArrayBufferByteLength(buffer!, order);
-            }
+                var view = Object;
+                if (view._byteLength != JsTypedArray.LengthAuto)
+                {
+                    return view._byteLength;
+                }
 
-            return new DataViewWithBufferWitnessRecord(obj, byteLength);
+                var byteOffset = view._byteOffset;
+                var byteLength = CachedBufferByteLength;
+                return byteLength - byteOffset;
+            }
         }
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-setviewvalue
-        /// </summary>
-        private JsValue SetViewValue(
-            JsValue view,
-            JsValue requestIndex,
-            JsValue isLittleEndian,
-            TypedArrayElementType type,
-            JsValue value)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-makedataviewwithbufferwitnessrecord
+    /// </summary>
+    private static DataViewWithBufferWitnessRecord MakeDataViewWithBufferWitnessRecord(JsDataView obj, ArrayBufferOrder order)
+    {
+        var buffer = obj._viewedArrayBuffer;
+        int byteLength;
+        if (buffer?.IsDetachedBuffer == true)
         {
-            var dataView = view as JsDataView;
-            if (dataView is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Method called on incompatible receiver " + view);
-            }
+            byteLength = -1;
+        }
+        else
+        {
+            byteLength = IntrinsicTypedArrayPrototype.ArrayBufferByteLength(buffer!, order);
+        }
 
-            var getIndex = TypeConverter.ToIndex(_realm, requestIndex);
+        return new DataViewWithBufferWitnessRecord(obj, byteLength);
+    }
 
-            TypedArrayValue numberValue;
-            if (type.IsBigIntElementType())
-            {
-                numberValue = TypeConverter.ToBigInt(value);
-            }
-            else
-            {
-                numberValue = TypeConverter.ToNumber(value);
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-setviewvalue
+    /// </summary>
+    private JsValue SetViewValue(
+        JsValue view,
+        JsValue requestIndex,
+        JsValue isLittleEndian,
+        TypedArrayElementType type,
+        JsValue value)
+    {
+        var dataView = view as JsDataView;
+        if (dataView is null)
+        {
+            ExceptionHelper.ThrowTypeError(_realm, "Method called on incompatible receiver " + view);
+        }
 
-            var isLittleEndianBoolean = TypeConverter.ToBoolean(isLittleEndian);
-            var buffer = dataView._viewedArrayBuffer!;
-            buffer.AssertNotDetached();
+        var getIndex = TypeConverter.ToIndex(_realm, requestIndex);
 
-            var viewOffset = dataView._byteOffset;
-            var viewRecord = MakeDataViewWithBufferWitnessRecord(dataView, ArrayBufferOrder.Unordered);
-            if (viewRecord.IsViewOutOfBounds)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
-            }
+        TypedArrayValue numberValue;
+        if (type.IsBigIntElementType())
+        {
+            numberValue = TypeConverter.ToBigInt(value);
+        }
+        else
+        {
+            numberValue = TypeConverter.ToNumber(value);
+        }
 
-            var viewSize = viewRecord.ViewByteLength;
-            var elementSize = type.GetElementSize();
-            if (getIndex + elementSize > viewSize)
-            {
-                ExceptionHelper.ThrowRangeError(_realm, "Offset is outside the bounds of the DataView");
-            }
+        var isLittleEndianBoolean = TypeConverter.ToBoolean(isLittleEndian);
+        var buffer = dataView._viewedArrayBuffer!;
+        buffer.AssertNotDetached();
 
-            var bufferIndex = (int) (getIndex + viewOffset);
-            buffer.SetValueInBuffer(bufferIndex, type, numberValue, false, ArrayBufferOrder.Unordered, isLittleEndianBoolean);
-            return Undefined;
+        var viewOffset = dataView._byteOffset;
+        var viewRecord = MakeDataViewWithBufferWitnessRecord(dataView, ArrayBufferOrder.Unordered);
+        if (viewRecord.IsViewOutOfBounds)
+        {
+            ExceptionHelper.ThrowTypeError(_realm, "Offset is outside the bounds of the DataView");
+        }
+
+        var viewSize = viewRecord.ViewByteLength;
+        var elementSize = type.GetElementSize();
+        if (getIndex + elementSize > viewSize)
+        {
+            ExceptionHelper.ThrowRangeError(_realm, "Offset is outside the bounds of the DataView");
         }
+
+        var bufferIndex = (int) (getIndex + viewOffset);
+        buffer.SetValueInBuffer(bufferIndex, type, numberValue, false, ArrayBufferOrder.Unordered, isLittleEndianBoolean);
+        return Undefined;
     }
 }

+ 1092 - 1093
Jint/Native/Date/DatePrototype.cs

@@ -10,1408 +10,1407 @@ using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
-namespace Jint.Native.Date
+namespace Jint.Native.Date;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-properties-of-the-date-prototype-object
+/// </summary>
+internal sealed class DatePrototype : Prototype
 {
-    /// <summary>
-    /// https://tc39.es/ecma262/#sec-properties-of-the-date-prototype-object
-    /// </summary>
-    internal sealed class DatePrototype : Prototype
+    // ES6 section 20.3.1.1 Time Values and Time Range
+    private const double MinYear = -1000000.0;
+    private const double MaxYear = -MinYear;
+    private const double MinMonth = -10000000.0;
+    private const double MaxMonth = -MinMonth;
+
+    private readonly DateConstructor _constructor;
+    private readonly ITimeSystem _timeSystem;
+
+    internal DatePrototype(
+        Engine engine,
+        DateConstructor constructor,
+        ObjectPrototype objectPrototype)
+        : base(engine, engine.Realm)
     {
-        // ES6 section 20.3.1.1 Time Values and Time Range
-        private const double MinYear = -1000000.0;
-        private const double MaxYear = -MinYear;
-        private const double MinMonth = -10000000.0;
-        private const double MaxMonth = -MinMonth;
+        _prototype = objectPrototype;
+        _constructor = constructor;
+        _timeSystem = engine.Options.TimeSystem;
+    }
 
-        private readonly DateConstructor _constructor;
-        private readonly ITimeSystem _timeSystem;
+    protected override  void Initialize()
+    {
+        const PropertyFlag lengthFlags = PropertyFlag.Configurable;
+        const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
+
+        var properties = new PropertyDictionary(50, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
+            ["toString"] = new PropertyDescriptor(new ClrFunction(Engine, "toString", ToString, 0, lengthFlags), propertyFlags),
+            ["toDateString"] = new PropertyDescriptor(new ClrFunction(Engine, "toDateString", ToDateString, 0, lengthFlags), propertyFlags),
+            ["toTimeString"] = new PropertyDescriptor(new ClrFunction(Engine, "toTimeString", ToTimeString, 0, lengthFlags), propertyFlags),
+            ["toLocaleString"] = new PropertyDescriptor(new ClrFunction(Engine, "toLocaleString", ToLocaleString, 0, lengthFlags), propertyFlags),
+            ["toLocaleDateString"] = new PropertyDescriptor(new ClrFunction(Engine, "toLocaleDateString", ToLocaleDateString, 0, lengthFlags), propertyFlags),
+            ["toLocaleTimeString"] = new PropertyDescriptor(new ClrFunction(Engine, "toLocaleTimeString", ToLocaleTimeString, 0, lengthFlags), propertyFlags),
+            ["valueOf"] = new PropertyDescriptor(new ClrFunction(Engine, "valueOf", ValueOf, 0, lengthFlags), propertyFlags),
+            ["getTime"] = new PropertyDescriptor(new ClrFunction(Engine, "getTime", GetTime, 0, lengthFlags), propertyFlags),
+            ["getFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "getFullYear", GetFullYear, 0, lengthFlags), propertyFlags),
+            ["getYear"] = new PropertyDescriptor(new ClrFunction(Engine, "getYear", GetYear, 0, lengthFlags), propertyFlags),
+            ["getUTCFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCFullYear", GetUTCFullYear, 0, lengthFlags), propertyFlags),
+            ["getMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "getMonth", GetMonth, 0, lengthFlags), propertyFlags),
+            ["getUTCMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCMonth", GetUTCMonth, 0, lengthFlags), propertyFlags),
+            ["getDate"] = new PropertyDescriptor(new ClrFunction(Engine, "getDate", GetDate, 0, lengthFlags), propertyFlags),
+            ["getUTCDate"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCDate", GetUTCDate, 0, lengthFlags), propertyFlags),
+            ["getDay"] = new PropertyDescriptor(new ClrFunction(Engine, "getDay", GetDay, 0, lengthFlags), propertyFlags),
+            ["getUTCDay"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCDay", GetUTCDay, 0, lengthFlags), propertyFlags),
+            ["getHours"] = new PropertyDescriptor(new ClrFunction(Engine, "getHours", GetHours, 0, lengthFlags), propertyFlags),
+            ["getUTCHours"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCHours", GetUTCHours, 0, lengthFlags), propertyFlags),
+            ["getMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "getMinutes", GetMinutes, 0, lengthFlags), propertyFlags),
+            ["getUTCMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCMinutes", GetUTCMinutes, 0, lengthFlags), propertyFlags),
+            ["getSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getSeconds", GetSeconds, 0, lengthFlags), propertyFlags),
+            ["getUTCSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCSeconds", GetUTCSeconds, 0, lengthFlags), propertyFlags),
+            ["getMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getMilliseconds", GetMilliseconds, 0, lengthFlags), propertyFlags),
+            ["getUTCMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCMilliseconds", GetUTCMilliseconds, 0, lengthFlags), propertyFlags),
+            ["getTimezoneOffset"] = new PropertyDescriptor(new ClrFunction(Engine, "getTimezoneOffset", GetTimezoneOffset, 0, lengthFlags), propertyFlags),
+            ["setTime"] = new PropertyDescriptor(new ClrFunction(Engine, "setTime", SetTime, 1, lengthFlags), propertyFlags),
+            ["setMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setMilliseconds", SetMilliseconds, 1, lengthFlags), propertyFlags),
+            ["setUTCMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCMilliseconds", SetUTCMilliseconds, 1, lengthFlags), propertyFlags),
+            ["setSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setSeconds", SetSeconds, 2, lengthFlags), propertyFlags),
+            ["setUTCSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCSeconds", SetUTCSeconds, 2, lengthFlags), propertyFlags),
+            ["setMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "setMinutes", SetMinutes, 3, lengthFlags), propertyFlags),
+            ["setUTCMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCMinutes", SetUTCMinutes, 3, lengthFlags), propertyFlags),
+            ["setHours"] = new PropertyDescriptor(new ClrFunction(Engine, "setHours", SetHours, 4, lengthFlags), propertyFlags),
+            ["setUTCHours"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCHours", SetUTCHours, 4, lengthFlags), propertyFlags),
+            ["setDate"] = new PropertyDescriptor(new ClrFunction(Engine, "setDate", SetDate, 1, lengthFlags), propertyFlags),
+            ["setUTCDate"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCDate", SetUTCDate, 1, lengthFlags), propertyFlags),
+            ["setMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "setMonth", SetMonth, 2, lengthFlags), propertyFlags),
+            ["setUTCMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCMonth", SetUTCMonth, 2, lengthFlags), propertyFlags),
+            ["setFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "setFullYear", SetFullYear, 3, lengthFlags), propertyFlags),
+            ["setYear"] = new PropertyDescriptor(new ClrFunction(Engine, "setYear", SetYear, 1, lengthFlags), propertyFlags),
+            ["setUTCFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCFullYear", SetUTCFullYear, 3, lengthFlags), propertyFlags),
+            ["toUTCString"] = new PropertyDescriptor(new ClrFunction(Engine, "toUTCString", ToUtcString, 0, lengthFlags), propertyFlags),
+            ["toISOString"] = new PropertyDescriptor(new ClrFunction(Engine, "toISOString", ToISOString, 0, lengthFlags), propertyFlags),
+            ["toJSON"] = new PropertyDescriptor(new ClrFunction(Engine, "toJSON", ToJson, 1, lengthFlags), propertyFlags)
+        };
+        SetProperties(properties);
 
-        internal DatePrototype(
-            Engine engine,
-            DateConstructor constructor,
-            ObjectPrototype objectPrototype)
-            : base(engine, engine.Realm)
+        var symbols = new SymbolDictionary(1)
         {
-            _prototype = objectPrototype;
-            _constructor = constructor;
-            _timeSystem = engine.Options.TimeSystem;
-        }
+            [GlobalSymbolRegistry.ToPrimitive] = new PropertyDescriptor(new ClrFunction(Engine, "[Symbol.toPrimitive]", ToPrimitive, 1, PropertyFlag.Configurable), PropertyFlag.Configurable),
+        };
+        SetSymbols(symbols);
+    }
 
-        protected override  void Initialize()
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive
+    /// </summary>
+    private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
+    {
+        var oi = thisObject as ObjectInstance;
+        if (oi is null)
         {
-            const PropertyFlag lengthFlags = PropertyFlag.Configurable;
-            const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
-
-            var properties = new PropertyDictionary(50, checkExistingKeys: false)
-            {
-                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
-                ["toString"] = new PropertyDescriptor(new ClrFunction(Engine, "toString", ToString, 0, lengthFlags), propertyFlags),
-                ["toDateString"] = new PropertyDescriptor(new ClrFunction(Engine, "toDateString", ToDateString, 0, lengthFlags), propertyFlags),
-                ["toTimeString"] = new PropertyDescriptor(new ClrFunction(Engine, "toTimeString", ToTimeString, 0, lengthFlags), propertyFlags),
-                ["toLocaleString"] = new PropertyDescriptor(new ClrFunction(Engine, "toLocaleString", ToLocaleString, 0, lengthFlags), propertyFlags),
-                ["toLocaleDateString"] = new PropertyDescriptor(new ClrFunction(Engine, "toLocaleDateString", ToLocaleDateString, 0, lengthFlags), propertyFlags),
-                ["toLocaleTimeString"] = new PropertyDescriptor(new ClrFunction(Engine, "toLocaleTimeString", ToLocaleTimeString, 0, lengthFlags), propertyFlags),
-                ["valueOf"] = new PropertyDescriptor(new ClrFunction(Engine, "valueOf", ValueOf, 0, lengthFlags), propertyFlags),
-                ["getTime"] = new PropertyDescriptor(new ClrFunction(Engine, "getTime", GetTime, 0, lengthFlags), propertyFlags),
-                ["getFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "getFullYear", GetFullYear, 0, lengthFlags), propertyFlags),
-                ["getYear"] = new PropertyDescriptor(new ClrFunction(Engine, "getYear", GetYear, 0, lengthFlags), propertyFlags),
-                ["getUTCFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCFullYear", GetUTCFullYear, 0, lengthFlags), propertyFlags),
-                ["getMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "getMonth", GetMonth, 0, lengthFlags), propertyFlags),
-                ["getUTCMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCMonth", GetUTCMonth, 0, lengthFlags), propertyFlags),
-                ["getDate"] = new PropertyDescriptor(new ClrFunction(Engine, "getDate", GetDate, 0, lengthFlags), propertyFlags),
-                ["getUTCDate"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCDate", GetUTCDate, 0, lengthFlags), propertyFlags),
-                ["getDay"] = new PropertyDescriptor(new ClrFunction(Engine, "getDay", GetDay, 0, lengthFlags), propertyFlags),
-                ["getUTCDay"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCDay", GetUTCDay, 0, lengthFlags), propertyFlags),
-                ["getHours"] = new PropertyDescriptor(new ClrFunction(Engine, "getHours", GetHours, 0, lengthFlags), propertyFlags),
-                ["getUTCHours"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCHours", GetUTCHours, 0, lengthFlags), propertyFlags),
-                ["getMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "getMinutes", GetMinutes, 0, lengthFlags), propertyFlags),
-                ["getUTCMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCMinutes", GetUTCMinutes, 0, lengthFlags), propertyFlags),
-                ["getSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getSeconds", GetSeconds, 0, lengthFlags), propertyFlags),
-                ["getUTCSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCSeconds", GetUTCSeconds, 0, lengthFlags), propertyFlags),
-                ["getMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getMilliseconds", GetMilliseconds, 0, lengthFlags), propertyFlags),
-                ["getUTCMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "getUTCMilliseconds", GetUTCMilliseconds, 0, lengthFlags), propertyFlags),
-                ["getTimezoneOffset"] = new PropertyDescriptor(new ClrFunction(Engine, "getTimezoneOffset", GetTimezoneOffset, 0, lengthFlags), propertyFlags),
-                ["setTime"] = new PropertyDescriptor(new ClrFunction(Engine, "setTime", SetTime, 1, lengthFlags), propertyFlags),
-                ["setMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setMilliseconds", SetMilliseconds, 1, lengthFlags), propertyFlags),
-                ["setUTCMilliseconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCMilliseconds", SetUTCMilliseconds, 1, lengthFlags), propertyFlags),
-                ["setSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setSeconds", SetSeconds, 2, lengthFlags), propertyFlags),
-                ["setUTCSeconds"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCSeconds", SetUTCSeconds, 2, lengthFlags), propertyFlags),
-                ["setMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "setMinutes", SetMinutes, 3, lengthFlags), propertyFlags),
-                ["setUTCMinutes"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCMinutes", SetUTCMinutes, 3, lengthFlags), propertyFlags),
-                ["setHours"] = new PropertyDescriptor(new ClrFunction(Engine, "setHours", SetHours, 4, lengthFlags), propertyFlags),
-                ["setUTCHours"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCHours", SetUTCHours, 4, lengthFlags), propertyFlags),
-                ["setDate"] = new PropertyDescriptor(new ClrFunction(Engine, "setDate", SetDate, 1, lengthFlags), propertyFlags),
-                ["setUTCDate"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCDate", SetUTCDate, 1, lengthFlags), propertyFlags),
-                ["setMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "setMonth", SetMonth, 2, lengthFlags), propertyFlags),
-                ["setUTCMonth"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCMonth", SetUTCMonth, 2, lengthFlags), propertyFlags),
-                ["setFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "setFullYear", SetFullYear, 3, lengthFlags), propertyFlags),
-                ["setYear"] = new PropertyDescriptor(new ClrFunction(Engine, "setYear", SetYear, 1, lengthFlags), propertyFlags),
-                ["setUTCFullYear"] = new PropertyDescriptor(new ClrFunction(Engine, "setUTCFullYear", SetUTCFullYear, 3, lengthFlags), propertyFlags),
-                ["toUTCString"] = new PropertyDescriptor(new ClrFunction(Engine, "toUTCString", ToUtcString, 0, lengthFlags), propertyFlags),
-                ["toISOString"] = new PropertyDescriptor(new ClrFunction(Engine, "toISOString", ToISOString, 0, lengthFlags), propertyFlags),
-                ["toJSON"] = new PropertyDescriptor(new ClrFunction(Engine, "toJSON", ToJson, 1, lengthFlags), propertyFlags)
-            };
-            SetProperties(properties);
-
-            var symbols = new SymbolDictionary(1)
-            {
-                [GlobalSymbolRegistry.ToPrimitive] = new PropertyDescriptor(new ClrFunction(Engine, "[Symbol.toPrimitive]", ToPrimitive, 1, PropertyFlag.Configurable), PropertyFlag.Configurable),
-            };
-            SetSymbols(symbols);
+            ExceptionHelper.ThrowTypeError(_realm);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive
-        /// </summary>
-        private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
+        var hint = arguments.At(0);
+        if (!hint.IsString())
         {
-            var oi = thisObject as ObjectInstance;
-            if (oi is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-
-            var hint = arguments.At(0);
-            if (!hint.IsString())
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-
-            var hintString = hint.ToString();
-            var tryFirst = Types.Empty;
-            if (string.Equals(hintString, "default", StringComparison.Ordinal) || string.Equals(hintString, "string", StringComparison.Ordinal))
-            {
-                tryFirst = Types.String;
-            }
-            else  if (string.Equals(hintString, "number", StringComparison.Ordinal))
-            {
-                tryFirst = Types.Number;
-            }
-            else
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-
-            return TypeConverter.OrdinaryToPrimitive(oi, tryFirst);
+            ExceptionHelper.ThrowTypeError(_realm);
         }
 
-        private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
+        var hintString = hint.ToString();
+        var tryFirst = Types.Empty;
+        if (string.Equals(hintString, "default", StringComparison.Ordinal) || string.Equals(hintString, "string", StringComparison.Ordinal))
         {
-            return ThisTimeValue(thisObject).ToJsValue();
+            tryFirst = Types.String;
         }
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#thistimevalue
-        /// </summary>
-        private DatePresentation ThisTimeValue(JsValue thisObject)
+        else  if (string.Equals(hintString, "number", StringComparison.Ordinal))
         {
-            if (thisObject is JsDate dateInstance)
-            {
-                return dateInstance._dateValue;
-            }
-
-            ExceptionHelper.ThrowTypeError(_realm, "this is not a Date object");
-            return default;
+            tryFirst = Types.Number;
         }
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.tostring
-        /// </summary>
-        internal JsValue ToString(JsValue thisObject, JsValue[] arg2)
+        else
         {
-            var tv = ThisTimeValue(thisObject);
-            return ToDateString(tv);
+            ExceptionHelper.ThrowTypeError(_realm);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.todatestring
-        /// </summary>
-        private JsValue ToDateString(JsValue thisObject, JsValue[] arguments)
-        {
-            var tv = ThisTimeValue(thisObject);
+        return TypeConverter.OrdinaryToPrimitive(oi, tryFirst);
+    }
 
-            if (tv.IsNaN)
-            {
-                return "Invalid Date";
-            }
+    private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
+    {
+        return ThisTimeValue(thisObject).ToJsValue();
+    }
 
-            var t = LocalTime(tv);
-            return DateString(t);
+    /// <summary>
+    /// https://tc39.es/ecma262/#thistimevalue
+    /// </summary>
+    private DatePresentation ThisTimeValue(JsValue thisObject)
+    {
+        if (thisObject is JsDate dateInstance)
+        {
+            return dateInstance._dateValue;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-todatestring
-        /// </summary>
-        private JsValue ToDateString(DatePresentation tv)
-        {
-            if (tv.IsNaN)
-            {
-                return "Invalid Date";
-            }
+        ExceptionHelper.ThrowTypeError(_realm, "this is not a Date object");
+        return default;
+    }
 
-            var t = LocalTime(tv);
-            return DateString(t) + " " + TimeString(t) + TimeZoneString(tv);
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.tostring
+    /// </summary>
+    internal JsValue ToString(JsValue thisObject, JsValue[] arg2)
+    {
+        var tv = ThisTimeValue(thisObject);
+        return ToDateString(tv);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.todatestring
+    /// </summary>
+    private JsValue ToDateString(JsValue thisObject, JsValue[] arguments)
+    {
+        var tv = ThisTimeValue(thisObject);
+
+        if (tv.IsNaN)
+        {
+            return "Invalid Date";
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.totimestring
-        /// </summary>
-        private JsValue ToTimeString(JsValue thisObject, JsValue[] arguments)
+        var t = LocalTime(tv);
+        return DateString(t);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-todatestring
+    /// </summary>
+    private JsValue ToDateString(DatePresentation tv)
+    {
+        if (tv.IsNaN)
         {
-            var tv = ThisTimeValue(thisObject);
+            return "Invalid Date";
+        }
 
-            if (tv.IsNaN)
-            {
-                return "Invalid Date";
-            }
+        var t = LocalTime(tv);
+        return DateString(t) + " " + TimeString(t) + TimeZoneString(tv);
+    }
 
-            var t = LocalTime(tv);
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.totimestring
+    /// </summary>
+    private JsValue ToTimeString(JsValue thisObject, JsValue[] arguments)
+    {
+        var tv = ThisTimeValue(thisObject);
 
-            return TimeString(t) + TimeZoneString(tv);
+        if (tv.IsNaN)
+        {
+            return "Invalid Date";
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.tolocalestring
-        /// </summary>
-        private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
-        {
-            var dateInstance = ThisTimeValue(thisObject);
+        var t = LocalTime(tv);
 
-            if (dateInstance.IsNaN)
-            {
-                return "Invalid Date";
-            }
+        return TimeString(t) + TimeZoneString(tv);
+    }
 
-            return ToLocalTime(dateInstance).ToString("F", Engine.Options.Culture);
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.tolocalestring
+    /// </summary>
+    private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
+    {
+        var dateInstance = ThisTimeValue(thisObject);
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.tolocaledatestring
-        /// </summary>
-        private JsValue ToLocaleDateString(JsValue thisObject, JsValue[] arguments)
+        if (dateInstance.IsNaN)
         {
-            var dateInstance = ThisTimeValue(thisObject);
+            return "Invalid Date";
+        }
 
-            if (dateInstance.IsNaN)
-            {
-                return "Invalid Date";
-            }
+        return ToLocalTime(dateInstance).ToString("F", Engine.Options.Culture);
+    }
 
-            return ToLocalTime(dateInstance).ToString("D", Engine.Options.Culture);
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.tolocaledatestring
+    /// </summary>
+    private JsValue ToLocaleDateString(JsValue thisObject, JsValue[] arguments)
+    {
+        var dateInstance = ThisTimeValue(thisObject);
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.tolocaletimestring
-        /// </summary>
-        private JsValue ToLocaleTimeString(JsValue thisObject, JsValue[] arguments)
+        if (dateInstance.IsNaN)
         {
-            var dateInstance = ThisTimeValue(thisObject);
+            return "Invalid Date";
+        }
 
-            if (dateInstance.IsNaN)
-            {
-                return "Invalid Date";
-            }
+        return ToLocalTime(dateInstance).ToString("D", Engine.Options.Culture);
+    }
 
-            return ToLocalTime(dateInstance).ToString("T", Engine.Options.Culture);
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.tolocaletimestring
+    /// </summary>
+    private JsValue ToLocaleTimeString(JsValue thisObject, JsValue[] arguments)
+    {
+        var dateInstance = ThisTimeValue(thisObject);
 
-        private JsValue GetTime(JsValue thisObject, JsValue[] arguments)
+        if (dateInstance.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return t.ToJsValue();
+            return "Invalid Date";
         }
 
-        private JsValue GetFullYear(JsValue thisObject, JsValue[] arguments)
+        return ToLocalTime(dateInstance).ToString("T", Engine.Options.Culture);
+    }
+
+    private JsValue GetTime(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return YearFromTime(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return t.ToJsValue();
+    }
 
-        private JsValue GetYear(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetFullYear(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return YearFromTime(LocalTime(t)) - 1900;
+            return JsNumber.DoubleNaN;
         }
+        return YearFromTime(LocalTime(t));
+    }
 
-        private JsValue GetUTCFullYear(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetYear(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return YearFromTime(t);
+            return JsNumber.DoubleNaN;
         }
+        return YearFromTime(LocalTime(t)) - 1900;
+    }
 
-        private JsValue GetMonth(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetUTCFullYear(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return MonthFromTime(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return YearFromTime(t);
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.getutcmonth
-        /// </summary>
-        private JsValue GetUTCMonth(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetMonth(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return MonthFromTime(t);
+            return JsNumber.DoubleNaN;
         }
+        return MonthFromTime(LocalTime(t));
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.getdate
-        /// </summary>
-        private JsValue GetDate(JsValue thisObject, JsValue[] arguments)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.getutcmonth
+    /// </summary>
+    private JsValue GetUTCMonth(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return DateFromTime(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return MonthFromTime(t);
+    }
 
-        private JsValue GetUTCDate(JsValue thisObject, JsValue[] arguments)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.getdate
+    /// </summary>
+    private JsValue GetDate(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return DateFromTime(t);
+            return JsNumber.DoubleNaN;
         }
+        return DateFromTime(LocalTime(t));
+    }
 
-        private JsValue GetDay(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetUTCDate(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return WeekDay(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return DateFromTime(t);
+    }
 
-        private JsValue GetUTCDay(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetDay(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return WeekDay(t);
+            return JsNumber.DoubleNaN;
         }
+        return WeekDay(LocalTime(t));
+    }
 
-        private JsValue GetHours(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetUTCDay(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return HourFromTime(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return WeekDay(t);
+    }
 
-        private JsValue GetUTCHours(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetHours(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return HourFromTime(t);
+            return JsNumber.DoubleNaN;
         }
+        return HourFromTime(LocalTime(t));
+    }
 
-        private JsValue GetMinutes(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetUTCHours(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return MinFromTime(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return HourFromTime(t);
+    }
 
-        private JsValue GetUTCMinutes(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetMinutes(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return MinFromTime(t);
+            return JsNumber.DoubleNaN;
         }
+        return MinFromTime(LocalTime(t));
+    }
 
-        private JsValue GetSeconds(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetUTCMinutes(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return SecFromTime(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return MinFromTime(t);
+    }
 
-        private JsValue GetUTCSeconds(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetSeconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return SecFromTime(t);
+            return JsNumber.DoubleNaN;
         }
+        return SecFromTime(LocalTime(t));
+    }
 
-        private JsValue GetMilliseconds(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetUTCSeconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return MsFromTime(LocalTime(t));
+            return JsNumber.DoubleNaN;
         }
+        return SecFromTime(t);
+    }
 
-        private JsValue GetUTCMilliseconds(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetMilliseconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return MsFromTime(t);
+            return JsNumber.DoubleNaN;
         }
+        return MsFromTime(LocalTime(t));
+    }
 
-        private JsValue GetTimezoneOffset(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetUTCMilliseconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-            return (int) ((double) t.Value - LocalTime(t).Value)/MsPerMinute;
+            return JsNumber.DoubleNaN;
         }
+        return MsFromTime(t);
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.settime
-        /// </summary>
-        private JsValue SetTime(JsValue thisObject, JsValue[] arguments)
+    private JsValue GetTimezoneOffset(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        if (t.IsNaN)
         {
-            ThisTimeValue(thisObject);
-            var t = TypeConverter.ToNumber(arguments.At(0));
-            var v = t.TimeClip();
-
-            ((JsDate) thisObject)._dateValue = t;
-            return v.ToJsValue();
+            return JsNumber.DoubleNaN;
         }
+        return (int) ((double) t.Value - LocalTime(t).Value)/MsPerMinute;
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setmilliseconds
-        /// </summary>
-        private JsValue SetMilliseconds(JsValue thisObject, JsValue[] arguments)
-        {
-            var t = LocalTime(ThisTimeValue(thisObject));
-            var ms = TypeConverter.ToNumber(arguments.At(0));
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.settime
+    /// </summary>
+    private JsValue SetTime(JsValue thisObject, JsValue[] arguments)
+    {
+        ThisTimeValue(thisObject);
+        var t = TypeConverter.ToNumber(arguments.At(0));
+        var v = t.TimeClip();
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        ((JsDate) thisObject)._dateValue = t;
+        return v.ToJsValue();
+    }
 
-            var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
-            var u = Utc(MakeDate(Day(t), time)).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setmilliseconds
+    /// </summary>
+    private JsValue SetMilliseconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = LocalTime(ThisTimeValue(thisObject));
+        var ms = TypeConverter.ToNumber(arguments.At(0));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setutcmilliseconds
-        /// </summary>
-        private JsValue SetUTCMilliseconds(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            var milli = TypeConverter.ToNumber(arguments.At(0));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return double.NaN;
-            }
+        var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
+        var u = Utc(MakeDate(Day(t), time)).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
-            var u = MakeDate(Day(t), time).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setutcmilliseconds
+    /// </summary>
+    private JsValue SetUTCMilliseconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        var milli = TypeConverter.ToNumber(arguments.At(0));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setseconds
-        /// </summary>
-        private JsValue SetSeconds(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = LocalTime(ThisTimeValue(thisObject));
-            var s = TypeConverter.ToNumber(arguments.At(0));
-            var milli = arguments.Length <= 1 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+            return double.NaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
+        var u = MakeDate(Day(t), time).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
-            var u = Utc(date).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setseconds
+    /// </summary>
+    private JsValue SetSeconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = LocalTime(ThisTimeValue(thisObject));
+        var s = TypeConverter.ToNumber(arguments.At(0));
+        var milli = arguments.Length <= 1 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setutcseconds
-        /// </summary>
-        private JsValue SetUTCSeconds(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            var s = TypeConverter.ToNumber(arguments.At(0));
-            var milli = arguments.Length <= 1 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
+        var u = Utc(date).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
-            var u = date.TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setutcseconds
+    /// </summary>
+    private JsValue SetUTCSeconds(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        var s = TypeConverter.ToNumber(arguments.At(0));
+        var milli = arguments.Length <= 1 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setminutes
-        /// </summary>
-        private JsValue SetMinutes(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = LocalTime(ThisTimeValue(thisObject));
-            var m = TypeConverter.ToNumber(arguments.At(0));
-            var s = arguments.Length <= 1 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
-            var milli = arguments.Length <= 2 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
+        var u = date.TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
-            var u = Utc(date).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setminutes
+    /// </summary>
+    private JsValue SetMinutes(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = LocalTime(ThisTimeValue(thisObject));
+        var m = TypeConverter.ToNumber(arguments.At(0));
+        var s = arguments.Length <= 1 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+        var milli = arguments.Length <= 2 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setutcminutes
-        /// </summary>
-        private JsValue SetUTCMinutes(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            var m = TypeConverter.ToNumber(arguments.At(0));
-            var s = arguments.Length <= 1 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
-            var milli = arguments.Length <= 2 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
+        var u = Utc(date).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
-            var u = date.TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setutcminutes
+    /// </summary>
+    private JsValue SetUTCMinutes(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        var m = TypeConverter.ToNumber(arguments.At(0));
+        var s = arguments.Length <= 1 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+        var milli = arguments.Length <= 2 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.sethours
-        /// </summary>
-        private JsValue SetHours(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = LocalTime(ThisTimeValue(thisObject));
-            var h = TypeConverter.ToNumber(arguments.At(0));
-            var m = arguments.Length <= 1 ? MinFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
-            var s = arguments.Length <= 2 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
-            var milli = arguments.Length <= 3 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(3));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
+        var u = date.TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var date = MakeDate(Day(t), MakeTime(h, m, s, milli));
-            var u = Utc(date).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.sethours
+    /// </summary>
+    private JsValue SetHours(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = LocalTime(ThisTimeValue(thisObject));
+        var h = TypeConverter.ToNumber(arguments.At(0));
+        var m = arguments.Length <= 1 ? MinFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+        var s = arguments.Length <= 2 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
+        var milli = arguments.Length <= 3 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(3));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setutchours
-        /// </summary>
-        private JsValue SetUTCHours(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            var h = TypeConverter.ToNumber(arguments.At(0));
-            var m = arguments.Length <= 1 ? MinFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
-            var s = arguments.Length <= 2 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
-            var milli = arguments.Length <= 3 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(3));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var date = MakeDate(Day(t), MakeTime(h, m, s, milli));
+        var u = Utc(date).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var newDate = MakeDate(Day(t), MakeTime(h, m, s, milli));
-            var v = newDate.TimeClip();
-            ((JsDate) thisObject)._dateValue = v;
-            return v.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setutchours
+    /// </summary>
+    private JsValue SetUTCHours(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        var h = TypeConverter.ToNumber(arguments.At(0));
+        var m = arguments.Length <= 1 ? MinFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+        var s = arguments.Length <= 2 ? SecFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
+        var milli = arguments.Length <= 3 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(3));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setdate
-        /// </summary>
-        private JsValue SetDate(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = LocalTime(ThisTimeValue(thisObject));
-            var dt = TypeConverter.ToNumber(arguments.At(0));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var newDate = MakeDate(Day(t), MakeTime(h, m, s, milli));
+        var v = newDate.TimeClip();
+        ((JsDate) thisObject)._dateValue = v;
+        return v.ToJsValue();
+    }
 
-            var (year, month, __) = YearMonthDayFromTime(t);
-            var newDate = MakeDate(MakeDay(year, month, dt), TimeWithinDay(t));
-            var u = Utc(newDate).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setdate
+    /// </summary>
+    private JsValue SetDate(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = LocalTime(ThisTimeValue(thisObject));
+        var dt = TypeConverter.ToNumber(arguments.At(0));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setutcdate
-        /// </summary>
-        private JsValue SetUTCDate(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = ThisTimeValue(thisObject);
-            var dt = TypeConverter.ToNumber(arguments.At(0));
+            return JsNumber.DoubleNaN;
+        }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+        var (year, month, __) = YearMonthDayFromTime(t);
+        var newDate = MakeDate(MakeDay(year, month, dt), TimeWithinDay(t));
+        var u = Utc(newDate).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t));
-            var u = newDate.TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setutcdate
+    /// </summary>
+    private JsValue SetUTCDate(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        var dt = TypeConverter.ToNumber(arguments.At(0));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setmonth
-        /// </summary>
-        private JsValue SetMonth(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var t = LocalTime(ThisTimeValue(thisObject));
-            var m = TypeConverter.ToNumber(arguments.At(0));
-            var dt = arguments.Length <= 1 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
-
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
-
-            var newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t));
-            var u = Utc(newDate).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
+            return JsNumber.DoubleNaN;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setutcmonth
-        /// </summary>
-        private JsValue SetUTCMonth(JsValue thisObject, JsValue[] arguments)
-        {
-            var t = ThisTimeValue(thisObject);
-            var m = TypeConverter.ToNumber(arguments.At(0));
-            var dt = arguments.Length <= 1 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+        var newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t));
+        var u = newDate.TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            if (t.IsNaN)
-            {
-                return JsNumber.DoubleNaN;
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setmonth
+    /// </summary>
+    private JsValue SetMonth(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = LocalTime(ThisTimeValue(thisObject));
+        var m = TypeConverter.ToNumber(arguments.At(0));
+        var dt = arguments.Length <= 1 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
 
-            var newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t));
-            var u = newDate.TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
+        if (t.IsNaN)
+        {
+            return JsNumber.DoubleNaN;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setfullyear
-        /// </summary>
-        private JsValue SetFullYear(JsValue thisObject, JsValue[] arguments)
-        {
-            var thisTime = ThisTimeValue(thisObject);
-            var t = thisTime.IsNaN ? 0 : LocalTime(thisTime);
-            var y = TypeConverter.ToNumber(arguments.At(0));
-            var m = arguments.Length <= 1 ? MonthFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
-            var dt = arguments.Length <= 2 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
+        var newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t));
+        var u = Utc(newDate).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t));
-            var u = Utc(newDate).TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setutcmonth
+    /// </summary>
+    private JsValue SetUTCMonth(JsValue thisObject, JsValue[] arguments)
+    {
+        var t = ThisTimeValue(thisObject);
+        var m = TypeConverter.ToNumber(arguments.At(0));
+        var dt = arguments.Length <= 1 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setyear
-        /// </summary>
-        private JsValue SetYear(JsValue thisObject, JsValue[] arguments)
+        if (t.IsNaN)
         {
-            var thisTime = ThisTimeValue(thisObject);
-            var t = thisTime.IsNaN ? 0 : LocalTime(thisTime);
-            var y = TypeConverter.ToNumber(arguments.At(0));
-            if (double.IsNaN(y))
-            {
-                ((JsDate) thisObject)._dateValue = double.NaN;
-                return JsNumber.DoubleNaN;
-            }
+            return JsNumber.DoubleNaN;
+        }
 
-            var fy = TypeConverter.ToInteger(y);
-            if (y >= 0 && y <= 99)
-            {
-                fy += 1900;
-            }
+        var newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t));
+        var u = newDate.TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var newDate = MakeDay(fy, MonthFromTime(t), DateFromTime(t));
-            var u = Utc(MakeDate(newDate, TimeWithinDay(t)));
-            ((JsDate) thisObject)._dateValue = u.TimeClip();
-            return u.ToJsValue();
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setfullyear
+    /// </summary>
+    private JsValue SetFullYear(JsValue thisObject, JsValue[] arguments)
+    {
+        var thisTime = ThisTimeValue(thisObject);
+        var t = thisTime.IsNaN ? 0 : LocalTime(thisTime);
+        var y = TypeConverter.ToNumber(arguments.At(0));
+        var m = arguments.Length <= 1 ? MonthFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+        var dt = arguments.Length <= 2 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
+
+        var newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t));
+        var u = Utc(newDate).TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.setutcfullyear
-        /// </summary>
-        private JsValue SetUTCFullYear(JsValue thisObject, JsValue[] arguments)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setyear
+    /// </summary>
+    private JsValue SetYear(JsValue thisObject, JsValue[] arguments)
+    {
+        var thisTime = ThisTimeValue(thisObject);
+        var t = thisTime.IsNaN ? 0 : LocalTime(thisTime);
+        var y = TypeConverter.ToNumber(arguments.At(0));
+        if (double.IsNaN(y))
         {
-            var thisTime = ThisTimeValue(thisObject);
-            var t = thisTime.IsNaN ? 0 : thisTime;
-            var y = TypeConverter.ToNumber(arguments.At(0));
-            var m = arguments.Length <= 1 ? MonthFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
-            var dt = arguments.Length <= 2 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
-            var newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t));
-            var u = newDate.TimeClip();
-            ((JsDate) thisObject)._dateValue = u;
-            return u.ToJsValue();
+            ((JsDate) thisObject)._dateValue = double.NaN;
+            return JsNumber.DoubleNaN;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.toutcstring
-        /// </summary>
-        private JsValue ToUtcString(JsValue thisObject, JsValue[] arguments)
+        var fy = TypeConverter.ToInteger(y);
+        if (y >= 0 && y <= 99)
         {
-            var tv = ThisTimeValue(thisObject);
-            if (!IsFinite(tv))
-            {
-                return "Invalid Date";
-            }
-
-            var weekday = _dayNames[WeekDay(tv)];
-            var month = _monthNames[MonthFromTime(tv)];
-            var day = DateFromTime(tv).ToString("00", CultureInfo.InvariantCulture);
-            var yv = YearFromTime(tv);
-            var paddedYear = yv.ToString("0000", CultureInfo.InvariantCulture);
-
-            return $"{weekday}, {day} {month} {paddedYear} {TimeString(tv)}";
+            fy += 1900;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-date.prototype.toisostring
-        /// </summary>
-        private JsValue ToISOString(JsValue thisObject, JsValue[] arguments)
-        {
-            var thisTime = ThisTimeValue(thisObject);
-            var t = thisTime;
-            if (t.IsNaN)
-            {
-                ExceptionHelper.ThrowRangeError(_realm);
-            }
+        var newDate = MakeDay(fy, MonthFromTime(t), DateFromTime(t));
+        var u = Utc(MakeDate(newDate, TimeWithinDay(t)));
+        ((JsDate) thisObject)._dateValue = u.TimeClip();
+        return u.ToJsValue();
+    }
 
-            if (((JsDate) thisObject).DateTimeRangeValid)
-            {
-                // shortcut
-                var dt = thisTime.ToDateTime();
-                return $"{dt.Year:0000}-{dt.Month:00}-{dt.Day:00}T{dt.Hour:00}:{dt.Minute:00}:{dt.Second:00}.{dt.Millisecond:000}Z";
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.setutcfullyear
+    /// </summary>
+    private JsValue SetUTCFullYear(JsValue thisObject, JsValue[] arguments)
+    {
+        var thisTime = ThisTimeValue(thisObject);
+        var t = thisTime.IsNaN ? 0 : thisTime;
+        var y = TypeConverter.ToNumber(arguments.At(0));
+        var m = arguments.Length <= 1 ? MonthFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
+        var dt = arguments.Length <= 2 ? DateFromTime(t) : TypeConverter.ToNumber(arguments.At(2));
+        var newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t));
+        var u = newDate.TimeClip();
+        ((JsDate) thisObject)._dateValue = u;
+        return u.ToJsValue();
+    }
 
-            var h = HourFromTime(t);
-            var m = MinFromTime(t);
-            var s = SecFromTime(t);
-            var ms = MsFromTime(t);
-            if (h < 0) { h += HoursPerDay; }
-            if (m < 0) { m += MinutesPerHour; }
-            if (s < 0) { s += SecondsPerMinute; }
-            if (ms < 0) { ms += MsPerSecond; }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.toutcstring
+    /// </summary>
+    private JsValue ToUtcString(JsValue thisObject, JsValue[] arguments)
+    {
+        var tv = ThisTimeValue(thisObject);
+        if (!IsFinite(tv))
+        {
+            return "Invalid Date";
+        }
 
-            var (year, month, day) = YearMonthDayFromTime(t);
-            month++;
+        var weekday = _dayNames[WeekDay(tv)];
+        var month = _monthNames[MonthFromTime(tv)];
+        var day = DateFromTime(tv).ToString("00", CultureInfo.InvariantCulture);
+        var yv = YearFromTime(tv);
+        var paddedYear = yv.ToString("0000", CultureInfo.InvariantCulture);
 
-            var formatted = $"{year:0000}-{month:00}-{day:00}T{h:00}:{m:00}:{s:00}.{ms:000}Z";
-            if (year > 9999)
-            {
-                formatted = "+" + formatted;
-            }
+        return $"{weekday}, {day} {month} {paddedYear} {TimeString(tv)}";
+    }
 
-            return formatted;
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date.prototype.toisostring
+    /// </summary>
+    private JsValue ToISOString(JsValue thisObject, JsValue[] arguments)
+    {
+        var thisTime = ThisTimeValue(thisObject);
+        var t = thisTime;
+        if (t.IsNaN)
+        {
+            ExceptionHelper.ThrowRangeError(_realm);
         }
 
-        private JsValue ToJson(JsValue thisObject, JsValue[] arguments)
+        if (((JsDate) thisObject).DateTimeRangeValid)
         {
-            var o = TypeConverter.ToObject(_realm, thisObject);
-            var tv = TypeConverter.ToPrimitive(o, Types.Number);
-            if (tv.IsNumber() && !IsFinite(((JsNumber) tv)._value))
-            {
-                return Null;
-            }
-
-            return Invoke(o, "toISOString", Arguments.Empty);
+            // shortcut
+            var dt = thisTime.ToDateTime();
+            return $"{dt.Year:0000}-{dt.Month:00}-{dt.Day:00}T{dt.Hour:00}:{dt.Minute:00}:{dt.Second:00}.{dt.Millisecond:000}Z";
         }
 
-        private const int HoursPerDay = 24;
-        private const int MinutesPerHour = 60;
-        private const int SecondsPerMinute = 60;
-        private const int MsPerSecond = 1000;
-        private const int MsPerMinute = 60000;
-        private const int MsPerHour = 3600000;
-        private const long MsPerDay = 86400000;
+        var h = HourFromTime(t);
+        var m = MinFromTime(t);
+        var s = SecFromTime(t);
+        var ms = MsFromTime(t);
+        if (h < 0) { h += HoursPerDay; }
+        if (m < 0) { m += MinutesPerHour; }
+        if (s < 0) { s += SecondsPerMinute; }
+        if (ms < 0) { ms += MsPerSecond; }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#eqn-Day
-        /// </summary>
-        private static int Day(DatePresentation t)
+        var (year, month, day) = YearMonthDayFromTime(t);
+        month++;
+
+        var formatted = $"{year:0000}-{month:00}-{day:00}T{h:00}:{m:00}:{s:00}.{ms:000}Z";
+        if (year > 9999)
         {
-            return (int) System.Math.Floor((double) t.Value / MsPerDay);
+            formatted = "+" + formatted;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#eqn-Day
-        /// </summary>
-        private static long TimeWithinDay(DatePresentation t)
+        return formatted;
+    }
+
+    private JsValue ToJson(JsValue thisObject, JsValue[] arguments)
+    {
+        var o = TypeConverter.ToObject(_realm, thisObject);
+        var tv = TypeConverter.ToPrimitive(o, Types.Number);
+        if (tv.IsNumber() && !IsFinite(((JsNumber) tv)._value))
         {
-            var result = t.Value % MsPerDay;
+            return Null;
+        }
 
-            if (result < 0)
-            {
-                result += MsPerDay;
-            }
+        return Invoke(o, "toISOString", Arguments.Empty);
+    }
 
-            return result;
-        }
+    private const int HoursPerDay = 24;
+    private const int MinutesPerHour = 60;
+    private const int SecondsPerMinute = 60;
+    private const int MsPerSecond = 1000;
+    private const int MsPerMinute = 60000;
+    private const int MsPerHour = 3600000;
+    private const long MsPerDay = 86400000;
 
-        /// <summary>
-        /// The number of days in a year
-        /// </summary>
-        private static int DaysInYear(double y)
-        {
-            if (y%4 != 0)
-            {
-                return 365;
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#eqn-Day
+    /// </summary>
+    private static int Day(DatePresentation t)
+    {
+        return (int) System.Math.Floor((double) t.Value / MsPerDay);
+    }
 
-            if (y%4 == 0 && y%100 != 0)
-            {
-                return 366;
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#eqn-Day
+    /// </summary>
+    private static long TimeWithinDay(DatePresentation t)
+    {
+        var result = t.Value % MsPerDay;
 
-            if (y%100 == 0 && y%400 != 0)
-            {
-                return 365;
-            }
+        if (result < 0)
+        {
+            result += MsPerDay;
+        }
 
-            if (y%400 == 0)
-            {
-                return 366;
-            }
+        return result;
+    }
 
+    /// <summary>
+    /// The number of days in a year
+    /// </summary>
+    private static int DaysInYear(double y)
+    {
+        if (y%4 != 0)
+        {
             return 365;
         }
 
-        /// <summary>
-        /// The day number of the first day of the year.
-        /// </summary>
-        private static int DayFromYear(DatePresentation y)
+        if (y%4 == 0 && y%100 != 0)
         {
-            return (int) (365*(y.Value - 1970)
-                          + System.Math.Floor((y.Value - 1969)/4d)
-                          - System.Math.Floor((y.Value - 1901)/100d)
-                          + System.Math.Floor((y.Value - 1601)/400d));
+            return 366;
         }
 
-        /// <summary>
-        /// The time value of the start of the year
-        /// </summary>
-        private static long TimeFromYear(DatePresentation y)
+        if (y%100 == 0 && y%400 != 0)
         {
-            return MsPerDay*DayFromYear(y);
+            return 365;
         }
 
-        /// <summary>
-        /// The year of a time value.
-        /// </summary>
-        private static int YearFromTime(DatePresentation t)
+        if (y%400 == 0)
         {
-            var (year, _, _) = YearMonthDayFromTime(t);
-            return year;
+            return 366;
         }
 
-        /// <summary>
-        /// <value>true</value> if the time is within a leap year, <value>false</value> otherwise
-        /// </summary>
-        private static int InLeapYear(DatePresentation t)
-        {
-            var daysInYear = DaysInYear(YearFromTime(t));
+        return 365;
+    }
 
-            if (daysInYear == 365)
-            {
-                return 0;
-            }
+    /// <summary>
+    /// The day number of the first day of the year.
+    /// </summary>
+    private static int DayFromYear(DatePresentation y)
+    {
+        return (int) (365*(y.Value - 1970)
+                      + System.Math.Floor((y.Value - 1969)/4d)
+                      - System.Math.Floor((y.Value - 1901)/100d)
+                      + System.Math.Floor((y.Value - 1601)/400d));
+    }
 
-            if (daysInYear == 366)
-            {
-                return 1;
-            }
+    /// <summary>
+    /// The time value of the start of the year
+    /// </summary>
+    private static long TimeFromYear(DatePresentation y)
+    {
+        return MsPerDay*DayFromYear(y);
+    }
+
+    /// <summary>
+    /// The year of a time value.
+    /// </summary>
+    private static int YearFromTime(DatePresentation t)
+    {
+        var (year, _, _) = YearMonthDayFromTime(t);
+        return year;
+    }
+
+    /// <summary>
+    /// <value>true</value> if the time is within a leap year, <value>false</value> otherwise
+    /// </summary>
+    private static int InLeapYear(DatePresentation t)
+    {
+        var daysInYear = DaysInYear(YearFromTime(t));
 
-            ExceptionHelper.ThrowArgumentException();
+        if (daysInYear == 365)
+        {
             return 0;
         }
 
-        /// <summary>
-        /// The month number of a time value.
-        /// </summary>
-        private static int MonthFromTime(DatePresentation t)
+        if (daysInYear == 366)
         {
-            var dayWithinYear = DayWithinYear(t);
-            var inLeapYear = InLeapYear(t);
-
-            if (dayWithinYear < 31)
-            {
-                return 0;
-            }
-
-            if (dayWithinYear < 59 + inLeapYear)
-            {
-                return 1;
-            }
-
-            if (dayWithinYear < 90 + inLeapYear)
-            {
-                return 2;
-            }
-
-            if (dayWithinYear < 120 + inLeapYear)
-            {
-                return 3;
-            }
-
-            if (dayWithinYear < 151 + inLeapYear)
-            {
-                return 4;
-            }
+            return 1;
+        }
 
-            if (dayWithinYear < 181 + inLeapYear)
-            {
-                return 5;
-            }
+        ExceptionHelper.ThrowArgumentException();
+        return 0;
+    }
 
-            if (dayWithinYear < 212 + inLeapYear)
-            {
-                return 6;
-            }
+    /// <summary>
+    /// The month number of a time value.
+    /// </summary>
+    private static int MonthFromTime(DatePresentation t)
+    {
+        var dayWithinYear = DayWithinYear(t);
+        var inLeapYear = InLeapYear(t);
 
-            if (dayWithinYear < 243 + inLeapYear)
-            {
-                return 7;
-            }
+        if (dayWithinYear < 31)
+        {
+            return 0;
+        }
 
-            if (dayWithinYear < 273 + inLeapYear)
-            {
-                return 8;
-            }
+        if (dayWithinYear < 59 + inLeapYear)
+        {
+            return 1;
+        }
 
-            if (dayWithinYear < 304 + inLeapYear)
-            {
-                return 9;
-            }
+        if (dayWithinYear < 90 + inLeapYear)
+        {
+            return 2;
+        }
 
-            if (dayWithinYear < 334 + inLeapYear)
-            {
-                return 10;
-            }
+        if (dayWithinYear < 120 + inLeapYear)
+        {
+            return 3;
+        }
 
-            if (dayWithinYear < 365 + inLeapYear)
-            {
-                return 11;
-            }
+        if (dayWithinYear < 151 + inLeapYear)
+        {
+            return 4;
+        }
 
-            ExceptionHelper.ThrowInvalidOperationException();
-            return 0;
+        if (dayWithinYear < 181 + inLeapYear)
+        {
+            return 5;
         }
 
-        private static int DayWithinYear(DatePresentation t)
+        if (dayWithinYear < 212 + inLeapYear)
         {
-            return Day(t) - DayFromYear(YearFromTime(t));
+            return 6;
         }
 
-        private static int DateFromTime(DatePresentation t)
+        if (dayWithinYear < 243 + inLeapYear)
         {
-            var monthFromTime = MonthFromTime(t);
-            var dayWithinYear = DayWithinYear(t);
+            return 7;
+        }
 
-            if (monthFromTime == 0)
-            {
-                return dayWithinYear + 1;
-            }
+        if (dayWithinYear < 273 + inLeapYear)
+        {
+            return 8;
+        }
 
-            if (monthFromTime== 1)
-            {
-                return dayWithinYear - 30;
-            }
+        if (dayWithinYear < 304 + inLeapYear)
+        {
+            return 9;
+        }
 
-            if (monthFromTime == 2)
-            {
-                return dayWithinYear - 58 - InLeapYear(t);
-            }
+        if (dayWithinYear < 334 + inLeapYear)
+        {
+            return 10;
+        }
 
-            if (monthFromTime == 3)
-            {
-                return dayWithinYear - 89 - InLeapYear(t);
-            }
+        if (dayWithinYear < 365 + inLeapYear)
+        {
+            return 11;
+        }
 
-            if (monthFromTime == 4)
-            {
-                return dayWithinYear - 119 - InLeapYear(t);
-            }
+        ExceptionHelper.ThrowInvalidOperationException();
+        return 0;
+    }
 
-            if (monthFromTime == 5)
-            {
-                return dayWithinYear - 150 - InLeapYear(t);
-            }
+    private static int DayWithinYear(DatePresentation t)
+    {
+        return Day(t) - DayFromYear(YearFromTime(t));
+    }
 
-            if (monthFromTime == 6)
-            {
-                return dayWithinYear - 180 - InLeapYear(t);
-            }
+    private static int DateFromTime(DatePresentation t)
+    {
+        var monthFromTime = MonthFromTime(t);
+        var dayWithinYear = DayWithinYear(t);
 
-            if (monthFromTime == 7)
-            {
-                return dayWithinYear - 211 - InLeapYear(t);
-            }
+        if (monthFromTime == 0)
+        {
+            return dayWithinYear + 1;
+        }
 
-            if (monthFromTime == 8)
-            {
-                return dayWithinYear - 242 - InLeapYear(t);
-            }
+        if (monthFromTime== 1)
+        {
+            return dayWithinYear - 30;
+        }
 
-            if (monthFromTime == 9)
-            {
-                return dayWithinYear - 272 - InLeapYear(t);
-            }
+        if (monthFromTime == 2)
+        {
+            return dayWithinYear - 58 - InLeapYear(t);
+        }
 
-            if (monthFromTime == 10)
-            {
-                return dayWithinYear - 303 - InLeapYear(t);
-            }
+        if (monthFromTime == 3)
+        {
+            return dayWithinYear - 89 - InLeapYear(t);
+        }
 
-            if (monthFromTime == 11)
-            {
-                return dayWithinYear - 333 - InLeapYear(t);
-            }
+        if (monthFromTime == 4)
+        {
+            return dayWithinYear - 119 - InLeapYear(t);
+        }
 
-            ExceptionHelper.ThrowInvalidOperationException();
-            return 0;
+        if (monthFromTime == 5)
+        {
+            return dayWithinYear - 150 - InLeapYear(t);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-week-day
-        /// </summary>
-        private static int WeekDay(DatePresentation t)
+        if (monthFromTime == 6)
         {
-            var result = (Day(t) + 4) % 7;
-            return result >= 0 ? result : result + 7;
+            return dayWithinYear - 180 - InLeapYear(t);
         }
 
-        private DateTime ToLocalTime(DatePresentation t)
+        if (monthFromTime == 7)
         {
-            var utcOffset = _timeSystem.GetUtcOffset(t.Value).TotalMilliseconds;
-            return (t + utcOffset).ToDateTime();
+            return dayWithinYear - 211 - InLeapYear(t);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-localtime
-        /// </summary>
-        private DatePresentation LocalTime(DatePresentation t)
+        if (monthFromTime == 8)
         {
-            if (t.IsNaN)
-            {
-                return DatePresentation.NaN;
-            }
+            return dayWithinYear - 242 - InLeapYear(t);
+        }
 
-            var offset = _timeSystem.GetUtcOffset(t.Value).TotalMilliseconds;
-            return t + offset;
+        if (monthFromTime == 9)
+        {
+            return dayWithinYear - 272 - InLeapYear(t);
         }
 
-        internal DatePresentation Utc(DatePresentation t)
+        if (monthFromTime == 10)
         {
-            var offset = _timeSystem.GetUtcOffset(t.Value).TotalMilliseconds;
-            return t - offset;
+            return dayWithinYear - 303 - InLeapYear(t);
         }
 
-        private static int HourFromTime(DatePresentation t)
+        if (monthFromTime == 11)
         {
-            var hours = System.Math.Floor((double) t.Value / MsPerHour) % HoursPerDay;
+            return dayWithinYear - 333 - InLeapYear(t);
+        }
 
-            if (hours < 0)
-            {
-                hours += HoursPerDay;
-            }
+        ExceptionHelper.ThrowInvalidOperationException();
+        return 0;
+    }
 
-            return (int) hours;
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-week-day
+    /// </summary>
+    private static int WeekDay(DatePresentation t)
+    {
+        var result = (Day(t) + 4) % 7;
+        return result >= 0 ? result : result + 7;
+    }
+
+    private DateTime ToLocalTime(DatePresentation t)
+    {
+        var utcOffset = _timeSystem.GetUtcOffset(t.Value).TotalMilliseconds;
+        return (t + utcOffset).ToDateTime();
+    }
 
-        private static int MinFromTime(DatePresentation t)
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-localtime
+    /// </summary>
+    private DatePresentation LocalTime(DatePresentation t)
+    {
+        if (t.IsNaN)
         {
-            var minutes = System.Math.Floor((double) t.Value / MsPerMinute) % MinutesPerHour;
+            return DatePresentation.NaN;
+        }
 
-            if (minutes < 0)
-            {
-                minutes += MinutesPerHour;
-            }
+        var offset = _timeSystem.GetUtcOffset(t.Value).TotalMilliseconds;
+        return t + offset;
+    }
 
-            return (int) minutes;
-        }
+    internal DatePresentation Utc(DatePresentation t)
+    {
+        var offset = _timeSystem.GetUtcOffset(t.Value).TotalMilliseconds;
+        return t - offset;
+    }
 
-        private static int SecFromTime(DatePresentation t)
+    private static int HourFromTime(DatePresentation t)
+    {
+        var hours = System.Math.Floor((double) t.Value / MsPerHour) % HoursPerDay;
+
+        if (hours < 0)
         {
-            var seconds = System.Math.Floor((double) t.Value / MsPerSecond) % SecondsPerMinute;
+            hours += HoursPerDay;
+        }
 
-            if (seconds < 0)
-            {
-                seconds += SecondsPerMinute;
-            }
+        return (int) hours;
+    }
 
-            return (int) seconds;
-        }
+    private static int MinFromTime(DatePresentation t)
+    {
+        var minutes = System.Math.Floor((double) t.Value / MsPerMinute) % MinutesPerHour;
 
-        private static int MsFromTime(DatePresentation t)
+        if (minutes < 0)
         {
-            var milli = t.Value % MsPerSecond;
+            minutes += MinutesPerHour;
+        }
 
-            if (milli < 0)
-            {
-                milli += MsPerSecond;
-            }
+        return (int) minutes;
+    }
 
-            return (int) milli;
-        }
+    private static int SecFromTime(DatePresentation t)
+    {
+        var seconds = System.Math.Floor((double) t.Value / MsPerSecond) % SecondsPerMinute;
 
-        internal static double MakeTime(double hour, double min, double sec, double ms)
+        if (seconds < 0)
         {
-            if (!AreFinite(hour, min, sec, ms))
-            {
-                return double.NaN;
-            }
+            seconds += SecondsPerMinute;
+        }
+
+        return (int) seconds;
+    }
 
-            var h = TypeConverter.ToInteger(hour);
-            var m = TypeConverter.ToInteger(min);
-            var s = TypeConverter.ToInteger(sec);
-            var milli = TypeConverter.ToInteger(ms);
-            var t = h*MsPerHour + m*MsPerMinute + s*MsPerSecond + milli;
+    private static int MsFromTime(DatePresentation t)
+    {
+        var milli = t.Value % MsPerSecond;
 
-            return t;
+        if (milli < 0)
+        {
+            milli += MsPerSecond;
         }
 
-        private static readonly int[] _dayFromMonth = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-        private static readonly int[] _dayFromMonthLeapYear = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
+        return (int) milli;
+    }
 
-        internal static double MakeDay(double year, double month, double date)
+    internal static double MakeTime(double hour, double min, double sec, double ms)
+    {
+        if (!AreFinite(hour, min, sec, ms))
         {
-            if (year < MinYear || year > MaxYear || month < MinMonth || month > MaxMonth || !AreFinite(year, month, date))
-            {
-                return double.NaN;
-            }
+            return double.NaN;
+        }
 
-            var y = (long) TypeConverter.ToInteger(year);
-            var m = (long) TypeConverter.ToInteger(month);
-            var dt = (long) TypeConverter.ToInteger(date);
+        var h = TypeConverter.ToInteger(hour);
+        var m = TypeConverter.ToInteger(min);
+        var s = TypeConverter.ToInteger(sec);
+        var milli = TypeConverter.ToInteger(ms);
+        var t = h*MsPerHour + m*MsPerMinute + s*MsPerSecond + milli;
 
-            y += m / 12;
-            m %= 12;
-            if (m < 0)
-            {
-                m += 12;
-                y -= 1;
-            }
+        return t;
+    }
 
-            // kYearDelta is an arbitrary number such that:
-            // a) kYearDelta = -1 (mod 400)
-            // b) year + kYearDelta > 0 for years in the range defined by
-            //    ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
-            //    Jan 1 1970. This is required so that we don't run into integer
-            //    division of negative numbers.
-            // c) there shouldn't be an overflow for 32-bit integers in the following
-            //    operations.
-            const int kYearDelta = 399999;
-            const long kBaseDay =
-                365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
-                (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
-
-            var dayFromYear = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
-                (y + kYearDelta) / 100 + (y + kYearDelta) / 400 - kBaseDay;
-
-            if (y % 4 != 0 || (y % 100 == 0 && y % 400 != 0))
-            {
-                dayFromYear += _dayFromMonth[m];
-            }
-            else
-            {
-                dayFromYear += _dayFromMonthLeapYear[m];
-            }
+    private static readonly int[] _dayFromMonth = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+    private static readonly int[] _dayFromMonthLeapYear = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
 
-            return dayFromYear + dt - 1;
+    internal static double MakeDay(double year, double month, double date)
+    {
+        if (year < MinYear || year > MaxYear || month < MinMonth || month > MaxMonth || !AreFinite(year, month, date))
+        {
+            return double.NaN;
         }
 
-        internal static DatePresentation MakeDate(double day, double time)
-        {
-            if (!AreFinite(day, time))
-            {
-                return DatePresentation.NaN;
-            }
+        var y = (long) TypeConverter.ToInteger(year);
+        var m = (long) TypeConverter.ToInteger(month);
+        var dt = (long) TypeConverter.ToInteger(date);
 
-            return new DatePresentation((long) (day * MsPerDay + time), DateFlags.None);
+        y += m / 12;
+        m %= 12;
+        if (m < 0)
+        {
+            m += 12;
+            y -= 1;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static bool IsFinite(double value) => !double.IsNaN(value) && !double.IsInfinity(value);
-
-        private static bool AreFinite(double value1, double value2) => IsFinite(value1) && IsFinite(value2);
+        // kYearDelta is an arbitrary number such that:
+        // a) kYearDelta = -1 (mod 400)
+        // b) year + kYearDelta > 0 for years in the range defined by
+        //    ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
+        //    Jan 1 1970. This is required so that we don't run into integer
+        //    division of negative numbers.
+        // c) there shouldn't be an overflow for 32-bit integers in the following
+        //    operations.
+        const int kYearDelta = 399999;
+        const long kBaseDay =
+            365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
+            (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static bool IsFinite(DatePresentation value) => value.IsFinite;
+        var dayFromYear = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
+            (y + kYearDelta) / 100 + (y + kYearDelta) / 400 - kBaseDay;
 
-        private static bool AreFinite(double value1, double value2, double value3)
-            => IsFinite(value1) && IsFinite(value2) && IsFinite(value3);
+        if (y % 4 != 0 || (y % 100 == 0 && y % 400 != 0))
+        {
+            dayFromYear += _dayFromMonth[m];
+        }
+        else
+        {
+            dayFromYear += _dayFromMonthLeapYear[m];
+        }
 
-        private static bool AreFinite(double value1, double value2, double value3, double value4)
-            => IsFinite(value1) && IsFinite(value2) &&  IsFinite(value3) && IsFinite(value4);
+        return dayFromYear + dt - 1;
+    }
 
-        [StructLayout(LayoutKind.Auto)]
-        private readonly record struct Date(int Year, int Month, int Day);
+    internal static DatePresentation MakeDate(double day, double time)
+    {
+        if (!AreFinite(day, time))
+        {
+            return DatePresentation.NaN;
+        }
 
-        private static readonly int[] kDaysInMonths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+        return new DatePresentation((long) (day * MsPerDay + time), DateFlags.None);
+    }
 
-        private static Date YearMonthDayFromTime(DatePresentation t) => YearMonthDayFromDays((long) System.Math.Floor(t.Value / 1000 / 60 / 60 / 24d));
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static bool IsFinite(double value) => !double.IsNaN(value) && !double.IsInfinity(value);
 
-        private static Date YearMonthDayFromDays(long days)
-        {
-            const int kDaysIn4Years = 4 * 365 + 1;
-            const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
-            const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
-            const int kDays1970to2000 = 30 * 365 + 7;
-            const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years - kDays1970to2000;
-            const int kYearsOffset = 400000;
+    private static bool AreFinite(double value1, double value2) => IsFinite(value1) && IsFinite(value2);
 
-            days += kDaysOffset;
-            var year = 400 * (days / kDaysIn400Years) - kYearsOffset;
-            days %= kDaysIn400Years;
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static bool IsFinite(DatePresentation value) => value.IsFinite;
 
-            days--;
-            var yd1 = days / kDaysIn100Years;
-            days %= kDaysIn100Years;
-            year += 100 * yd1;
+    private static bool AreFinite(double value1, double value2, double value3)
+        => IsFinite(value1) && IsFinite(value2) && IsFinite(value3);
 
-            days++;
-            var yd2 = days / kDaysIn4Years;
-            days %= kDaysIn4Years;
-            year += 4 * yd2;
+    private static bool AreFinite(double value1, double value2, double value3, double value4)
+        => IsFinite(value1) && IsFinite(value2) &&  IsFinite(value3) && IsFinite(value4);
 
-            days--;
-            var yd3 = days / 365;
-            days %= 365;
-            year += yd3;
+    [StructLayout(LayoutKind.Auto)]
+    private readonly record struct Date(int Year, int Month, int Day);
 
-            var is_leap = (yd1 == 0 || yd2 != 0) && yd3 == 0;
+    private static readonly int[] kDaysInMonths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
-            days += is_leap ? 1 : 0;
-            var month = 0;
-            var day = 0;
+    private static Date YearMonthDayFromTime(DatePresentation t) => YearMonthDayFromDays((long) System.Math.Floor(t.Value / 1000 / 60 / 60 / 24d));
 
-            // Check if the date is after February.
-            if (days >= 31 + 28 + (is_leap ? 1 : 0))
-            {
-                days -= 31 + 28 + (is_leap ? 1 : 0);
-                // Find the date starting from March.
-                for (int i = 2; i < 12; i++)
+    private static Date YearMonthDayFromDays(long days)
+    {
+        const int kDaysIn4Years = 4 * 365 + 1;
+        const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
+        const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
+        const int kDays1970to2000 = 30 * 365 + 7;
+        const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years - kDays1970to2000;
+        const int kYearsOffset = 400000;
+
+        days += kDaysOffset;
+        var year = 400 * (days / kDaysIn400Years) - kYearsOffset;
+        days %= kDaysIn400Years;
+
+        days--;
+        var yd1 = days / kDaysIn100Years;
+        days %= kDaysIn100Years;
+        year += 100 * yd1;
+
+        days++;
+        var yd2 = days / kDaysIn4Years;
+        days %= kDaysIn4Years;
+        year += 4 * yd2;
+
+        days--;
+        var yd3 = days / 365;
+        days %= 365;
+        year += yd3;
+
+        var is_leap = (yd1 == 0 || yd2 != 0) && yd3 == 0;
+
+        days += is_leap ? 1 : 0;
+        var month = 0;
+        var day = 0;
+
+        // Check if the date is after February.
+        if (days >= 31 + 28 + (is_leap ? 1 : 0))
+        {
+            days -= 31 + 28 + (is_leap ? 1 : 0);
+            // Find the date starting from March.
+            for (int i = 2; i < 12; i++)
+            {
+                if (days < kDaysInMonths[i])
                 {
-                    if (days < kDaysInMonths[i])
-                    {
-                        month = i;
-                        day = (int) (days + 1);
-                        break;
-                    }
-
-                    days -= kDaysInMonths[i];
+                    month = i;
+                    day = (int) (days + 1);
+                    break;
                 }
+
+                days -= kDaysInMonths[i];
+            }
+        }
+        else
+        {
+            // Check January and February.
+            if (days < 31)
+            {
+                month = 0;
+                day = (int) (days + 1);
             }
             else
             {
-                // Check January and February.
-                if (days < 31)
-                {
-                    month = 0;
-                    day = (int) (days + 1);
-                }
-                else
-                {
-                    month = 1;
-                    day = (int) (days - 31 + 1);
-                }
+                month = 1;
+                day = (int) (days - 31 + 1);
             }
-
-            return new Date((int) year, month, day);
         }
 
-        private static readonly string[] _dayNames =
-        {
-            "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-        };
-
-        private static readonly string[] _monthNames =
-        {
-            "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-        };
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-datestring
-        /// </summary>
-        private static string DateString(DatePresentation tv)
-        {
-            var weekday = _dayNames[WeekDay(tv)];
-            var month = _monthNames[MonthFromTime(tv)];
+        return new Date((int) year, month, day);
+    }
 
-            var dateFromTime = DateFromTime(tv);
-            var day = System.Math.Max(1, dateFromTime).ToString("00", CultureInfo.InvariantCulture);
-            var yv = YearFromTime(tv);
-            var yearSign = yv < 0 ? "-" : "";
-            var year = System.Math.Abs(yv);
-            var paddedYear = year.ToString("0000", CultureInfo.InvariantCulture);
+    private static readonly string[] _dayNames =
+    {
+        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+    };
 
-            return weekday + " " + month + " " + day + " " + yearSign + paddedYear;
-        }
+    private static readonly string[] _monthNames =
+    {
+        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+    };
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-timestring
-        /// </summary>
-        private static string TimeString(DatePresentation t)
-        {
-            var hour = HourFromTime(t).ToString("00", CultureInfo.InvariantCulture);
-            var minute = MinFromTime(t).ToString("00", CultureInfo.InvariantCulture);
-            var second = SecFromTime(t).ToString("00", CultureInfo.InvariantCulture);
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-datestring
+    /// </summary>
+    private static string DateString(DatePresentation tv)
+    {
+        var weekday = _dayNames[WeekDay(tv)];
+        var month = _monthNames[MonthFromTime(tv)];
 
-            return hour + ":" + minute + ":" + second + " GMT";
-        }
+        var dateFromTime = DateFromTime(tv);
+        var day = System.Math.Max(1, dateFromTime).ToString("00", CultureInfo.InvariantCulture);
+        var yv = YearFromTime(tv);
+        var yearSign = yv < 0 ? "-" : "";
+        var year = System.Math.Abs(yv);
+        var paddedYear = year.ToString("0000", CultureInfo.InvariantCulture);
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-timezoneestring
-        /// </summary>
-        private string TimeZoneString(DatePresentation tv)
-        {
-            var offset = _timeSystem.GetUtcOffset(tv.Value).TotalMilliseconds;
+        return weekday + " " + month + " " + day + " " + yearSign + paddedYear;
+    }
 
-            string offsetSign;
-            double absOffset;
-            if (offset >= 0)
-            {
-                offsetSign = "+";
-                absOffset = offset;
-            }
-            else
-            {
-                offsetSign = "-";
-                absOffset = -1 * offset;
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-timestring
+    /// </summary>
+    private static string TimeString(DatePresentation t)
+    {
+        var hour = HourFromTime(t).ToString("00", CultureInfo.InvariantCulture);
+        var minute = MinFromTime(t).ToString("00", CultureInfo.InvariantCulture);
+        var second = SecFromTime(t).ToString("00", CultureInfo.InvariantCulture);
 
-            var offsetMin = MinFromTime(absOffset).ToString("00", CultureInfo.InvariantCulture);
-            var offsetHour = HourFromTime(absOffset).ToString("00", CultureInfo.InvariantCulture);
+        return hour + ":" + minute + ":" + second + " GMT";
+    }
 
-            var tzName = " (" + _timeSystem.DefaultTimeZone.StandardName + ")";
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-timezoneestring
+    /// </summary>
+    private string TimeZoneString(DatePresentation tv)
+    {
+        var offset = _timeSystem.GetUtcOffset(tv.Value).TotalMilliseconds;
 
-            return offsetSign + offsetHour + offsetMin + tzName;
+        string offsetSign;
+        double absOffset;
+        if (offset >= 0)
+        {
+            offsetSign = "+";
+            absOffset = offset;
         }
-
-        public override string ToString()
+        else
         {
-            return "Date.prototype";
+            offsetSign = "-";
+            absOffset = -1 * offset;
         }
+
+        var offsetMin = MinFromTime(absOffset).ToString("00", CultureInfo.InvariantCulture);
+        var offsetHour = HourFromTime(absOffset).ToString("00", CultureInfo.InvariantCulture);
+
+        var tzName = " (" + _timeSystem.DefaultTimeZone.StandardName + ")";
+
+        return offsetSign + offsetHour + offsetMin + tzName;
+    }
+
+    public override string ToString()
+    {
+        return "Date.prototype";
     }
 }

+ 61 - 62
Jint/Native/Error/ErrorConstructor.cs

@@ -2,86 +2,85 @@ using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 
-namespace Jint.Native.Error
+namespace Jint.Native.Error;
+
+public sealed class ErrorConstructor : Constructor
 {
-    public sealed class ErrorConstructor : Constructor
+    private readonly Func<Intrinsics, ObjectInstance> _intrinsicDefaultProto;
+
+    internal ErrorConstructor(
+        Engine engine,
+        Realm realm,
+        ObjectInstance functionPrototype,
+        ObjectInstance objectPrototype,
+        JsString name, Func<Intrinsics, ObjectInstance> intrinsicDefaultProto)
+        : base(engine, realm, name)
     {
-        private readonly Func<Intrinsics, ObjectInstance> _intrinsicDefaultProto;
+        _intrinsicDefaultProto = intrinsicDefaultProto;
+        _prototype = functionPrototype;
+        PrototypeObject = new ErrorPrototype(engine, realm, this, objectPrototype, name);
+        _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
 
-        internal ErrorConstructor(
-            Engine engine,
-            Realm realm,
-            ObjectInstance functionPrototype,
-            ObjectInstance objectPrototype,
-            JsString name, Func<Intrinsics, ObjectInstance> intrinsicDefaultProto)
-            : base(engine, realm, name)
-        {
-            _intrinsicDefaultProto = intrinsicDefaultProto;
-            _prototype = functionPrototype;
-            PrototypeObject = new ErrorPrototype(engine, realm, this, objectPrototype, name);
-            _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
-            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
-        }
+    internal ErrorPrototype PrototypeObject { get; }
+
+    protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+    {
+        return Construct(arguments, this);
+    }
+
+    public ObjectInstance Construct(string? message = null)
+    {
+        return Construct(message != null ? new JsValue[]{ message } : System.Array.Empty<JsValue>(), this);
+    }
 
-        internal ErrorPrototype PrototypeObject { get; }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-nativeerror
+    /// </summary>
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var o = OrdinaryCreateFromConstructor(
+            newTarget,
+            _intrinsicDefaultProto,
+            static (Engine engine, Realm _, object? _) => new JsError(engine));
 
-        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+        var jsValue = arguments.At(0);
+        if (!jsValue.IsUndefined())
         {
-            return Construct(arguments, this);
+            var msg = TypeConverter.ToJsString(jsValue);
+            o.CreateNonEnumerableDataPropertyOrThrow(CommonProperties.Message, msg);
         }
 
-        public ObjectInstance Construct(string? message = null)
+        var stackString = BuildStackString();
+        if (stackString is not null)
         {
-            return Construct(message != null ? new JsValue[]{ message } : System.Array.Empty<JsValue>(), this);
+            var stackDesc = new PropertyDescriptor(stackString, PropertyFlag.NonEnumerable);
+            o.DefinePropertyOrThrow(CommonProperties.Stack, stackDesc);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-nativeerror
-        /// </summary>
-        public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        var options = arguments.At(1);
+        if (!options.IsUndefined())
         {
-            var o = OrdinaryCreateFromConstructor(
-                newTarget,
-                _intrinsicDefaultProto,
-                static (Engine engine, Realm _, object? _) => new JsError(engine));
-
-            var jsValue = arguments.At(0);
-            if (!jsValue.IsUndefined())
-            {
-                var msg = TypeConverter.ToJsString(jsValue);
-                o.CreateNonEnumerableDataPropertyOrThrow(CommonProperties.Message, msg);
-            }
+            o.InstallErrorCause(options);
+        }
 
-            var stackString = BuildStackString();
-            if (stackString is not null)
-            {
-                var stackDesc = new PropertyDescriptor(stackString, PropertyFlag.NonEnumerable);
-                o.DefinePropertyOrThrow(CommonProperties.Stack, stackDesc);
-            }
+        return o;
 
-            var options = arguments.At(1);
-            if (!options.IsUndefined())
+        JsValue? BuildStackString()
+        {
+            var lastSyntaxNode = _engine.GetLastSyntaxElement();
+            if (lastSyntaxNode == null)
             {
-                o.InstallErrorCause(options);
+                return null;
             }
 
-            return o;
-
-            JsValue? BuildStackString()
-            {
-                var lastSyntaxNode = _engine.GetLastSyntaxElement();
-                if (lastSyntaxNode == null)
-                {
-                    return null;
-                }
+            var callStack = _engine.CallStack;
+            var currentFunction = callStack.TryPeek(out var element) ? element.Function : null;
 
-                var callStack = _engine.CallStack;
-                var currentFunction = callStack.TryPeek(out var element) ? element.Function : null;
-
-                // If the current function is the ErrorConstructor itself (i.e. "throw new Error(...)" was called
-                // from script), exclude it from the stack trace, because the trace should begin at the throw point.
-                return callStack.BuildCallStackString(lastSyntaxNode.Location, currentFunction == this ? 1 : 0);
-            }
+            // If the current function is the ErrorConstructor itself (i.e. "throw new Error(...)" was called
+            // from script), exclude it from the stack trace, because the trace should begin at the throw point.
+            return callStack.BuildCallStackString(lastSyntaxNode.Location, currentFunction == this ? 1 : 0);
         }
     }
 }

+ 49 - 50
Jint/Native/Error/ErrorPrototype.cs

@@ -4,66 +4,65 @@ using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
-namespace Jint.Native.Error
+namespace Jint.Native.Error;
+
+/// <summary>
+/// http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.4
+/// </summary>
+internal sealed class ErrorPrototype : ErrorInstance
 {
-    /// <summary>
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.4
-    /// </summary>
-    internal sealed class ErrorPrototype : ErrorInstance
+    private readonly JsString _name;
+    private readonly Realm _realm;
+    private readonly ErrorConstructor _constructor;
+
+    internal ErrorPrototype(
+        Engine engine,
+        Realm realm,
+        ErrorConstructor constructor,
+        ObjectInstance prototype,
+        JsString name)
+        : base(engine, ObjectClass.Object)
     {
-        private readonly JsString _name;
-        private readonly Realm _realm;
-        private readonly ErrorConstructor _constructor;
+        _realm = realm;
+        _name = name;
+        _constructor = constructor;
+        _prototype = prototype;
+    }
 
-        internal ErrorPrototype(
-            Engine engine,
-            Realm realm,
-            ErrorConstructor constructor,
-            ObjectInstance prototype,
-            JsString name)
-            : base(engine, ObjectClass.Object)
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(3, checkExistingKeys: false)
         {
-            _realm = realm;
-            _name = name;
-            _constructor = constructor;
-            _prototype = prototype;
-        }
+            ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
+            ["message"] = new PropertyDescriptor("", PropertyFlag.Configurable | PropertyFlag.Writable),
+            ["name"] = new PropertyDescriptor(_name, PropertyFlag.Configurable | PropertyFlag.Writable),
+            ["toString"] = new PropertyDescriptor(new ClrFunction(Engine, "toString", ToString, 0, PropertyFlag.Configurable), PropertyFlag.Configurable | PropertyFlag.Writable)
+        };
+        SetProperties(properties);
+    }
 
-        protected override void Initialize()
+    public JsValue ToString(JsValue thisObject, JsValue[] arguments)
+    {
+        var o = thisObject.TryCast<ObjectInstance>();
+        if (o is null)
         {
-            var properties = new PropertyDictionary(3, checkExistingKeys: false)
-            {
-                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
-                ["message"] = new PropertyDescriptor("", PropertyFlag.Configurable | PropertyFlag.Writable),
-                ["name"] = new PropertyDescriptor(_name, PropertyFlag.Configurable | PropertyFlag.Writable),
-                ["toString"] = new PropertyDescriptor(new ClrFunction(Engine, "toString", ToString, 0, PropertyFlag.Configurable), PropertyFlag.Configurable | PropertyFlag.Writable)
-            };
-            SetProperties(properties);
+            ExceptionHelper.ThrowTypeError(_realm);
         }
 
-        public JsValue ToString(JsValue thisObject, JsValue[] arguments)
-        {
-            var o = thisObject.TryCast<ObjectInstance>();
-            if (o is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-
-            var nameProp = o.Get("name", this);
-            var name = nameProp.IsUndefined() ? "Error" : TypeConverter.ToString(nameProp);
+        var nameProp = o.Get("name", this);
+        var name = nameProp.IsUndefined() ? "Error" : TypeConverter.ToString(nameProp);
 
-            var msgProp = o.Get("message", this);
-            string msg = msgProp.IsUndefined() ? "" : TypeConverter.ToString(msgProp);
+        var msgProp = o.Get("message", this);
+        string msg = msgProp.IsUndefined() ? "" : TypeConverter.ToString(msgProp);
 
-            if (name == "")
-            {
-                return msg;
-            }
-            if (msg == "")
-            {
-                return name;
-            }
-            return name + ": " + msg;
+        if (name == "")
+        {
+            return msg;
+        }
+        if (msg == "")
+        {
+            return name;
         }
+        return name + ": " + msg;
     }
 }

+ 75 - 76
Jint/Native/Function/BindFunction.cs

@@ -1,102 +1,101 @@
 using Jint.Native.Object;
 using Jint.Runtime;
 
-namespace Jint.Native.Function
+namespace Jint.Native.Function;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-bound-function-exotic-objects
+/// </summary>
+public sealed class BindFunction : ObjectInstance, IConstructor, ICallable
 {
-    /// <summary>
-    /// https://tc39.es/ecma262/#sec-bound-function-exotic-objects
-    /// </summary>
-    public sealed class BindFunction : ObjectInstance, IConstructor, ICallable
+    private readonly Realm _realm;
+
+    public BindFunction(Engine engine,
+        Realm realm,
+        ObjectInstance? proto,
+        ObjectInstance targetFunction,
+        JsValue boundThis,
+        JsValue[] boundArgs)
+        : base(engine, ObjectClass.Function)
     {
-        private readonly Realm _realm;
-
-        public BindFunction(Engine engine,
-            Realm realm,
-            ObjectInstance? proto,
-            ObjectInstance targetFunction,
-            JsValue boundThis,
-            JsValue[] boundArgs)
-            : base(engine, ObjectClass.Function)
-        {
-            _realm = realm;
-            _prototype = proto;
-            BoundTargetFunction = targetFunction;
-            BoundThis = boundThis;
-            BoundArguments = boundArgs;
-        }
+        _realm = realm;
+        _prototype = proto;
+        BoundTargetFunction = targetFunction;
+        BoundThis = boundThis;
+        BoundArguments = boundArgs;
+    }
 
-        /// <summary>
-        /// The wrapped function object.
-        /// </summary>
-        public JsValue BoundTargetFunction { get; }
+    /// <summary>
+    /// The wrapped function object.
+    /// </summary>
+    public JsValue BoundTargetFunction { get; }
 
-        /// <summary>
-        /// The value that is always passed as the this value when calling the wrapped function.
-        /// </summary>
-        public JsValue BoundThis { get; }
+    /// <summary>
+    /// The value that is always passed as the this value when calling the wrapped function.
+    /// </summary>
+    public JsValue BoundThis { get; }
 
-        /// <summary>
-        /// A list of values whose elements are used as the first arguments to any call to the wrapped function.
-        /// </summary>
-        public JsValue[] BoundArguments { get; }
+    /// <summary>
+    /// A list of values whose elements are used as the first arguments to any call to the wrapped function.
+    /// </summary>
+    public JsValue[] BoundArguments { get; }
 
-        JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
+    JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
+    {
+        var f = BoundTargetFunction as Function;
+        if (f is null)
         {
-            var f = BoundTargetFunction as Function;
-            if (f is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-
-            var args = CreateArguments(arguments);
-            var value = f.Call(BoundThis, args);
-            _engine._jsValueArrayPool.ReturnArray(args);
-
-            return value;
+            ExceptionHelper.ThrowTypeError(_realm);
         }
 
-        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
-        {
-            var target = BoundTargetFunction as IConstructor;
-            if (target is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
+        var args = CreateArguments(arguments);
+        var value = f.Call(BoundThis, args);
+        _engine._jsValueArrayPool.ReturnArray(args);
 
-            var args = CreateArguments(arguments);
+        return value;
+    }
 
-            if (ReferenceEquals(this, newTarget))
-            {
-                newTarget = BoundTargetFunction;
-            }
+    ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var target = BoundTargetFunction as IConstructor;
+        if (target is null)
+        {
+            ExceptionHelper.ThrowTypeError(_realm);
+        }
 
-            var value = target.Construct(args, newTarget);
-            _engine._jsValueArrayPool.ReturnArray(args);
+        var args = CreateArguments(arguments);
 
-            return value;
+        if (ReferenceEquals(this, newTarget))
+        {
+            newTarget = BoundTargetFunction;
         }
 
-        internal override bool OrdinaryHasInstance(JsValue v)
-        {
-            var f = BoundTargetFunction as Function;
-            if (f is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
+        var value = target.Construct(args, newTarget);
+        _engine._jsValueArrayPool.ReturnArray(args);
 
-            return f.OrdinaryHasInstance(v);
-        }
+        return value;
+    }
 
-        private JsValue[] CreateArguments(JsValue[] arguments)
+    internal override bool OrdinaryHasInstance(JsValue v)
+    {
+        var f = BoundTargetFunction as Function;
+        if (f is null)
         {
-            var combined = _engine._jsValueArrayPool.RentArray(BoundArguments.Length + arguments.Length);
-            System.Array.Copy(BoundArguments, combined, BoundArguments.Length);
-            System.Array.Copy(arguments, 0, combined, BoundArguments.Length, arguments.Length);
-            return combined;
+            ExceptionHelper.ThrowTypeError(_realm);
         }
 
-        internal override bool IsConstructor => BoundTargetFunction.IsConstructor;
+        return f.OrdinaryHasInstance(v);
+    }
 
-        public override string ToString() => "function () { [native code] }";
+    private JsValue[] CreateArguments(JsValue[] arguments)
+    {
+        var combined = _engine._jsValueArrayPool.RentArray(BoundArguments.Length + arguments.Length);
+        System.Array.Copy(BoundArguments, combined, BoundArguments.Length);
+        System.Array.Copy(arguments, 0, combined, BoundArguments.Length, arguments.Length);
+        return combined;
     }
+
+    internal override bool IsConstructor => BoundTargetFunction.IsConstructor;
+
+    public override string ToString() => "function () { [native code] }";
 }

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

@@ -1,8 +1,7 @@
-namespace Jint.Native.Function
+namespace Jint.Native.Function;
+
+internal enum ConstructorKind
 {
-    internal enum ConstructorKind
-    {
-        Base,
-        Derived
-    }
+    Base,
+    Derived
 }

+ 334 - 335
Jint/Native/Function/Function.cs

@@ -7,433 +7,432 @@ using Jint.Runtime.Environments;
 using Jint.Runtime.Interpreter;
 using Environment = Jint.Runtime.Environments.Environment;
 
-namespace Jint.Native.Function
-{
-    [DebuggerDisplay("{ToString(),nq}")]
+namespace Jint.Native.Function;
+
+[DebuggerDisplay("{ToString(),nq}")]
 #pragma warning disable MA0049
-    public abstract partial class Function : ObjectInstance, ICallable
+public abstract partial class Function : ObjectInstance, ICallable
 #pragma warning restore MA0049
+{
+    protected PropertyDescriptor? _prototypeDescriptor;
+
+    protected internal PropertyDescriptor? _length;
+    internal PropertyDescriptor? _nameDescriptor;
+
+    internal Environment? _environment;
+    internal readonly JintFunctionDefinition _functionDefinition = null!;
+    internal readonly FunctionThisMode _thisMode;
+    internal JsValue _homeObject = Undefined;
+    internal ConstructorKind _constructorKind = ConstructorKind.Base;
+
+    internal Realm _realm;
+    internal PrivateEnvironment? _privateEnvironment;
+    private readonly IScriptOrModule? _scriptOrModule;
+
+    protected Function(
+        Engine engine,
+        Realm realm,
+        JsString? name)
+        : this(engine, realm, name, FunctionThisMode.Global)
     {
-        protected PropertyDescriptor? _prototypeDescriptor;
-
-        protected internal PropertyDescriptor? _length;
-        internal PropertyDescriptor? _nameDescriptor;
-
-        internal Environment? _environment;
-        internal readonly JintFunctionDefinition _functionDefinition = null!;
-        internal readonly FunctionThisMode _thisMode;
-        internal JsValue _homeObject = Undefined;
-        internal ConstructorKind _constructorKind = ConstructorKind.Base;
-
-        internal Realm _realm;
-        internal PrivateEnvironment? _privateEnvironment;
-        private readonly IScriptOrModule? _scriptOrModule;
-
-        protected Function(
-            Engine engine,
-            Realm realm,
-            JsString? name)
-            : this(engine, realm, name, FunctionThisMode.Global)
-        {
-        }
-
-        internal Function(
-            Engine engine,
-            Realm realm,
-            JintFunctionDefinition function,
-            Environment env,
-            FunctionThisMode thisMode)
-            : this(
-                engine,
-                realm,
-                !string.IsNullOrWhiteSpace(function.Name) ? new JsString(function.Name!) : null,
-                thisMode)
-        {
-            _functionDefinition = function;
-            _environment = env;
-        }
-
-        internal Function(
-            Engine engine,
-            Realm realm,
-            JsString? name,
-            FunctionThisMode thisMode = FunctionThisMode.Global,
-            ObjectClass objectClass = ObjectClass.Function)
-            : base(engine, objectClass)
-        {
-            if (name is not null)
-            {
-                _nameDescriptor = new PropertyDescriptor(name, PropertyFlag.Configurable);
-            }
-            _realm = realm;
-            _thisMode = thisMode;
-            _scriptOrModule = _engine.GetActiveScriptOrModule();
+    }
+
+    internal Function(
+        Engine engine,
+        Realm realm,
+        JintFunctionDefinition function,
+        Environment env,
+        FunctionThisMode thisMode)
+        : this(
+            engine,
+            realm,
+            !string.IsNullOrWhiteSpace(function.Name) ? new JsString(function.Name!) : null,
+            thisMode)
+    {
+        _functionDefinition = function;
+        _environment = env;
+    }
+
+    internal Function(
+        Engine engine,
+        Realm realm,
+        JsString? name,
+        FunctionThisMode thisMode = FunctionThisMode.Global,
+        ObjectClass objectClass = ObjectClass.Function)
+        : base(engine, objectClass)
+    {
+        if (name is not null)
+        {
+            _nameDescriptor = new PropertyDescriptor(name, PropertyFlag.Configurable);
         }
+        _realm = realm;
+        _thisMode = thisMode;
+        _scriptOrModule = _engine.GetActiveScriptOrModule();
+    }
 
-        // for example RavenDB wants to inspect this
-        public IFunction FunctionDeclaration => _functionDefinition.Function;
+    // for example RavenDB wants to inspect this
+    public IFunction FunctionDeclaration => _functionDefinition.Function;
 
-        internal override bool IsCallable => true;
+    internal override bool IsCallable => true;
 
-        JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments) => Call(thisObject, arguments);
+    JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments) => Call(thisObject, arguments);
 
-        /// <summary>
-        /// Executed when a function object is used as a function
-        /// </summary>
-        protected internal abstract JsValue Call(JsValue thisObject, JsValue[] arguments);
+    /// <summary>
+    /// Executed when a function object is used as a function
+    /// </summary>
+    protected internal abstract JsValue Call(JsValue thisObject, JsValue[] arguments);
 
-        public bool Strict => _thisMode == FunctionThisMode.Strict;
+    public bool Strict => _thisMode == FunctionThisMode.Strict;
 
-        internal override bool IsConstructor => this is IConstructor;
+    internal override bool IsConstructor => this is IConstructor;
 
-        public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
+    public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
+    {
+        if (_prototypeDescriptor != null)
         {
-            if (_prototypeDescriptor != null)
-            {
-                yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Prototype, _prototypeDescriptor);
-            }
-            if (_length != null)
-            {
-                yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Length, _length);
-            }
-            if (_nameDescriptor != null)
-            {
-                yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Name, GetOwnProperty(CommonProperties.Name));
-            }
+            yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Prototype, _prototypeDescriptor);
+        }
+        if (_length != null)
+        {
+            yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Length, _length);
+        }
+        if (_nameDescriptor != null)
+        {
+            yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Name, GetOwnProperty(CommonProperties.Name));
+        }
 
-            foreach (var entry in base.GetOwnProperties())
-            {
-                yield return entry;
-            }
+        foreach (var entry in base.GetOwnProperties())
+        {
+            yield return entry;
         }
+    }
 
-        internal sealed override IEnumerable<JsValue> GetInitialOwnStringPropertyKeys()
+    internal sealed override IEnumerable<JsValue> GetInitialOwnStringPropertyKeys()
+    {
+        if (_length != null)
         {
-            if (_length != null)
-            {
-                yield return CommonProperties.Length;
-            }
+            yield return CommonProperties.Length;
+        }
 
-            if (_nameDescriptor != null)
-            {
-                yield return CommonProperties.Name;
-            }
+        if (_nameDescriptor != null)
+        {
+            yield return CommonProperties.Name;
+        }
 
-            if (_prototypeDescriptor != null)
-            {
-                yield return CommonProperties.Prototype;
-            }
+        if (_prototypeDescriptor != null)
+        {
+            yield return CommonProperties.Prototype;
         }
+    }
 
-        public override PropertyDescriptor GetOwnProperty(JsValue property)
+    public override PropertyDescriptor GetOwnProperty(JsValue property)
+    {
+        if (CommonProperties.Prototype.Equals(property))
         {
-            if (CommonProperties.Prototype.Equals(property))
-            {
-                return _prototypeDescriptor ?? PropertyDescriptor.Undefined;
-            }
-            if (CommonProperties.Length.Equals(property))
-            {
-                return _length ?? PropertyDescriptor.Undefined;
-            }
-            if (CommonProperties.Name.Equals(property))
-            {
-                return _nameDescriptor ?? PropertyDescriptor.Undefined;
-            }
+            return _prototypeDescriptor ?? PropertyDescriptor.Undefined;
+        }
+        if (CommonProperties.Length.Equals(property))
+        {
+            return _length ?? PropertyDescriptor.Undefined;
+        }
+        if (CommonProperties.Name.Equals(property))
+        {
+            return _nameDescriptor ?? PropertyDescriptor.Undefined;
+        }
 
-            return base.GetOwnProperty(property);
+        return base.GetOwnProperty(property);
+    }
+
+    protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
+    {
+        if (CommonProperties.Prototype.Equals(property))
+        {
+            _prototypeDescriptor = desc;
+        }
+        else if (CommonProperties.Length.Equals(property))
+        {
+            _length = desc;
+        }
+        else if (CommonProperties.Name.Equals(property))
+        {
+            _nameDescriptor = desc;
+        }
+        else
+        {
+            base.SetOwnProperty(property, desc);
         }
+    }
 
-        protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
+    public override void RemoveOwnProperty(JsValue property)
+    {
+        if (CommonProperties.Prototype.Equals(property))
         {
-            if (CommonProperties.Prototype.Equals(property))
-            {
-                _prototypeDescriptor = desc;
-            }
-            else if (CommonProperties.Length.Equals(property))
-            {
-                _length = desc;
-            }
-            else if (CommonProperties.Name.Equals(property))
-            {
-                _nameDescriptor = desc;
-            }
-            else
-            {
-                base.SetOwnProperty(property, desc);
-            }
+            _prototypeDescriptor = null;
+        }
+        if (CommonProperties.Length.Equals(property))
+        {
+            _length = null;
+        }
+        if (CommonProperties.Name.Equals(property))
+        {
+            _nameDescriptor = null;
         }
 
-        public override void RemoveOwnProperty(JsValue property)
+        base.RemoveOwnProperty(property);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-setfunctionname
+    /// </summary>
+    internal void SetFunctionName(JsValue name, string? prefix = null, bool force = false)
+    {
+        if (!force && _nameDescriptor != null && UnwrapJsValue(_nameDescriptor) != JsString.Empty)
         {
-            if (CommonProperties.Prototype.Equals(property))
-            {
-                _prototypeDescriptor = null;
-            }
-            if (CommonProperties.Length.Equals(property))
-            {
-                _length = null;
-            }
-            if (CommonProperties.Name.Equals(property))
-            {
-                _nameDescriptor = null;
-            }
+            return;
+        }
 
-            base.RemoveOwnProperty(property);
+        if (name is JsSymbol symbol)
+        {
+            name = symbol._value.IsUndefined()
+                ? JsString.Empty
+                : new JsString("[" + symbol._value + "]");
+        }
+        else if (name is PrivateName privateName)
+        {
+            name = "#" + privateName.Description;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-setfunctionname
-        /// </summary>
-        internal void SetFunctionName(JsValue name, string? prefix = null, bool force = false)
+        if (!string.IsNullOrWhiteSpace(prefix))
         {
-            if (!force && _nameDescriptor != null && UnwrapJsValue(_nameDescriptor) != JsString.Empty)
-            {
-                return;
-            }
+            name = prefix + " " + name;
+        }
 
-            if (name is JsSymbol symbol)
-            {
-                name = symbol._value.IsUndefined()
-                    ? JsString.Empty
-                    : new JsString("[" + symbol._value + "]");
-            }
-            else if (name is PrivateName privateName)
-            {
-                name = "#" + privateName.Description;
-            }
+        _nameDescriptor = new PropertyDescriptor(name, PropertyFlag.Configurable);
+    }
 
-            if (!string.IsNullOrWhiteSpace(prefix))
-            {
-                name = prefix + " " + name;
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor
+    /// </summary>
+    /// <remarks>
+    /// Uses separate builder to get correct type with state support to prevent allocations.
+    /// In spec intrinsicDefaultProto is string pointing to intrinsic, but we do a selector.
+    /// </remarks>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal T OrdinaryCreateFromConstructor<T, TState>(
+        JsValue constructor,
+        Func<Intrinsics, ObjectInstance> intrinsicDefaultProto,
+        Func<Engine, Realm, TState?, T> objectCreator,
+        TState? state = default) where T : ObjectInstance
+    {
+        var proto = GetPrototypeFromConstructor(constructor, intrinsicDefaultProto);
 
-            _nameDescriptor = new PropertyDescriptor(name, PropertyFlag.Configurable);
-        }
+        var obj = objectCreator(_engine, _realm, state);
+        obj._prototype = proto;
+        return obj;
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor
-        /// </summary>
-        /// <remarks>
-        /// Uses separate builder to get correct type with state support to prevent allocations.
-        /// In spec intrinsicDefaultProto is string pointing to intrinsic, but we do a selector.
-        /// </remarks>
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal T OrdinaryCreateFromConstructor<T, TState>(
-            JsValue constructor,
-            Func<Intrinsics, ObjectInstance> intrinsicDefaultProto,
-            Func<Engine, Realm, TState?, T> objectCreator,
-            TState? state = default) where T : ObjectInstance
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-getprototypefromconstructor
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal ObjectInstance GetPrototypeFromConstructor(JsValue constructor, Func<Intrinsics, ObjectInstance> intrinsicDefaultProto)
+    {
+        if (constructor.Get(CommonProperties.Prototype) is not ObjectInstance proto)
         {
-            var proto = GetPrototypeFromConstructor(constructor, intrinsicDefaultProto);
+            var realm = GetFunctionRealm(constructor);
+            proto = intrinsicDefaultProto(realm.Intrinsics);
+        }
+        return proto;
+    }
 
-            var obj = objectCreator(_engine, _realm, state);
-            obj._prototype = proto;
-            return obj;
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-getfunctionrealm
+    /// </summary>
+    internal Realm GetFunctionRealm(JsValue obj)
+    {
+        if (obj is Function functionInstance && functionInstance._realm is not null)
+        {
+            return functionInstance._realm;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-getprototypefromconstructor
-        /// </summary>
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal ObjectInstance GetPrototypeFromConstructor(JsValue constructor, Func<Intrinsics, ObjectInstance> intrinsicDefaultProto)
+        if (obj is BindFunction bindFunctionInstance)
         {
-            if (constructor.Get(CommonProperties.Prototype) is not ObjectInstance proto)
-            {
-                var realm = GetFunctionRealm(constructor);
-                proto = intrinsicDefaultProto(realm.Intrinsics);
-            }
-            return proto;
+            return GetFunctionRealm(bindFunctionInstance.BoundTargetFunction);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-getfunctionrealm
-        /// </summary>
-        internal Realm GetFunctionRealm(JsValue obj)
+        if (obj is JsProxy proxyInstance)
         {
-            if (obj is Function functionInstance && functionInstance._realm is not null)
+            if (proxyInstance._handler is null)
             {
-                return functionInstance._realm;
+                ExceptionHelper.ThrowTypeErrorNoEngine();
             }
 
-            if (obj is BindFunction bindFunctionInstance)
-            {
-                return GetFunctionRealm(bindFunctionInstance.BoundTargetFunction);
-            }
+            return GetFunctionRealm(proxyInstance._target);
+        }
 
-            if (obj is JsProxy proxyInstance)
-            {
-                if (proxyInstance._handler is null)
-                {
-                    ExceptionHelper.ThrowTypeErrorNoEngine();
-                }
+        return _engine.ExecutionContext.Realm;
+    }
 
-                return GetFunctionRealm(proxyInstance._target);
-            }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-makemethod
+    /// </summary>
+    internal void MakeMethod(ObjectInstance homeObject)
+    {
+        _homeObject = homeObject;
+    }
 
-            return _engine.ExecutionContext.Realm;
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-ordinarycallbindthis
+    /// </summary>
+    internal void OrdinaryCallBindThis(in ExecutionContext calleeContext, JsValue thisArgument)
+    {
+        if (_thisMode == FunctionThisMode.Lexical)
+        {
+            return;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-makemethod
-        /// </summary>
-        internal void MakeMethod(ObjectInstance homeObject)
+        var calleeRealm = _realm;
+
+        var localEnv = (FunctionEnvironment) calleeContext.LexicalEnvironment;
+        JsValue thisValue;
+        if (_thisMode == FunctionThisMode.Strict)
         {
-            _homeObject = homeObject;
+            thisValue = thisArgument;
         }
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-ordinarycallbindthis
-        /// </summary>
-        internal void OrdinaryCallBindThis(in ExecutionContext calleeContext, JsValue thisArgument)
+        else
         {
-            if (_thisMode == FunctionThisMode.Lexical)
-            {
-                return;
-            }
-
-            var calleeRealm = _realm;
-
-            var localEnv = (FunctionEnvironment) calleeContext.LexicalEnvironment;
-            JsValue thisValue;
-            if (_thisMode == FunctionThisMode.Strict)
+            if (thisArgument is null || thisArgument.IsNullOrUndefined())
             {
-                thisValue = thisArgument;
+                var globalEnv = calleeRealm.GlobalEnv;
+                thisValue = globalEnv.GlobalThisValue;
             }
             else
             {
-                if (thisArgument is null || thisArgument.IsNullOrUndefined())
-                {
-                    var globalEnv = calleeRealm.GlobalEnv;
-                    thisValue = globalEnv.GlobalThisValue;
-                }
-                else
-                {
-                    thisValue = TypeConverter.ToObject(calleeRealm, thisArgument);
-                }
+                thisValue = TypeConverter.ToObject(calleeRealm, thisArgument);
             }
-
-            localEnv.BindThisValue(thisValue);
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-prepareforordinarycall
-        /// </summary>
-        internal ref readonly ExecutionContext PrepareForOrdinaryCall(JsValue newTarget)
+        localEnv.BindThisValue(thisValue);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-prepareforordinarycall
+    /// </summary>
+    internal ref readonly ExecutionContext PrepareForOrdinaryCall(JsValue newTarget)
+    {
+        var callerContext = _engine.ExecutionContext;
+
+        var localEnv = JintEnvironment.NewFunctionEnvironment(_engine, this, newTarget);
+        var calleeRealm = _realm;
+
+        var calleeContext = new ExecutionContext(
+            _scriptOrModule,
+            lexicalEnvironment: localEnv,
+            variableEnvironment: localEnv,
+            _privateEnvironment,
+            calleeRealm,
+            generator: null,
+            function: this);
+
+        // If callerContext is not already suspended, suspend callerContext.
+        // 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.
+        // Return calleeContext.
+
+        _engine.EnterExecutionContext(calleeContext);
+        return ref _engine.ExecutionContext;
+    }
+
+    internal void MakeConstructor(bool writableProperty = true, ObjectInstance? prototype = null)
+    {
+        _constructorKind = ConstructorKind.Base;
+        if (prototype is null)
         {
-            var callerContext = _engine.ExecutionContext;
+            prototype = new ObjectInstanceWithConstructor(_engine, this)
+            {
+                _prototype = _realm.Intrinsics.Object.PrototypeObject
+            };
+        }
 
-            var localEnv = JintEnvironment.NewFunctionEnvironment(_engine, this, newTarget);
-            var calleeRealm = _realm;
+        _prototypeDescriptor = new PropertyDescriptor(prototype, writableProperty, enumerable: false, configurable: false);
+    }
 
-            var calleeContext = new ExecutionContext(
-                _scriptOrModule,
-                lexicalEnvironment: localEnv,
-                variableEnvironment: localEnv,
-                _privateEnvironment,
-                calleeRealm,
-                generator: null,
-                function: this);
+    internal void SetFunctionLength(JsNumber length)
+    {
+        DefinePropertyOrThrow(CommonProperties.Length, new PropertyDescriptor(length, writable: false, enumerable: false, configurable: true));
+    }
 
-            // If callerContext is not already suspended, suspend callerContext.
-            // 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.
-            // Return calleeContext.
+    // native syntax doesn't expect to have private identifier indicator
+    private static readonly char[] _functionNameTrimStartChars = { '#' };
 
-            _engine.EnterExecutionContext(calleeContext);
-            return ref _engine.ExecutionContext;
+    public override string ToString()
+    {
+        // TODO no way to extract SourceText from Esprima at the moment, just returning native code
+        var nameValue = _nameDescriptor != null ? UnwrapJsValue(_nameDescriptor) : JsString.Empty;
+        var name = "";
+        if (!nameValue.IsUndefined())
+        {
+            name = TypeConverter.ToString(nameValue);
         }
 
-        internal void MakeConstructor(bool writableProperty = true, ObjectInstance? prototype = null)
-        {
-            _constructorKind = ConstructorKind.Base;
-            if (prototype is null)
-            {
-                prototype = new ObjectInstanceWithConstructor(_engine, this)
-                {
-                    _prototype = _realm.Intrinsics.Object.PrototypeObject
-                };
-            }
+        name = name.TrimStart(_functionNameTrimStartChars);
 
-            _prototypeDescriptor = new PropertyDescriptor(prototype, writableProperty, enumerable: false, configurable: false);
-        }
+        return "function " + name + "() { [native code] }";
+    }
 
-        internal void SetFunctionLength(JsNumber length)
+    private sealed class ObjectInstanceWithConstructor : ObjectInstance
+    {
+        private PropertyDescriptor? _constructor;
+
+        public ObjectInstanceWithConstructor(Engine engine, ObjectInstance thisObj) : base(engine)
         {
-            DefinePropertyOrThrow(CommonProperties.Length, new PropertyDescriptor(length, writable: false, enumerable: false, configurable: true));
+            _constructor = new PropertyDescriptor(thisObj, PropertyFlag.NonEnumerable);
         }
 
-        // native syntax doesn't expect to have private identifier indicator
-        private static readonly char[] _functionNameTrimStartChars = { '#' };
-
-        public override string ToString()
+        public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
         {
-            // TODO no way to extract SourceText from Esprima at the moment, just returning native code
-            var nameValue = _nameDescriptor != null ? UnwrapJsValue(_nameDescriptor) : JsString.Empty;
-            var name = "";
-            if (!nameValue.IsUndefined())
+            if (_constructor != null)
             {
-                name = TypeConverter.ToString(nameValue);
+                yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Constructor, _constructor);
             }
 
-            name = name.TrimStart(_functionNameTrimStartChars);
-
-            return "function " + name + "() { [native code] }";
+            foreach (var entry in base.GetOwnProperties())
+            {
+                yield return entry;
+            }
         }
 
-        private sealed class ObjectInstanceWithConstructor : ObjectInstance
+        public override PropertyDescriptor GetOwnProperty(JsValue property)
         {
-            private PropertyDescriptor? _constructor;
-
-            public ObjectInstanceWithConstructor(Engine engine, ObjectInstance thisObj) : base(engine)
+            if (CommonProperties.Constructor.Equals(property))
             {
-                _constructor = new PropertyDescriptor(thisObj, PropertyFlag.NonEnumerable);
+                return _constructor ?? PropertyDescriptor.Undefined;
             }
 
-            public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
+            return base.GetOwnProperty(property);
+        }
+
+        protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
+        {
+            if (CommonProperties.Constructor.Equals(property))
             {
-                if (_constructor != null)
-                {
-                    yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Constructor, _constructor);
-                }
-
-                foreach (var entry in base.GetOwnProperties())
-                {
-                    yield return entry;
-                }
+                _constructor = desc;
             }
-
-            public override PropertyDescriptor GetOwnProperty(JsValue property)
+            else
             {
-                if (CommonProperties.Constructor.Equals(property))
-                {
-                    return _constructor ?? PropertyDescriptor.Undefined;
-                }
-
-                return base.GetOwnProperty(property);
+                base.SetOwnProperty(property, desc);
             }
+        }
 
-            protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
+        public override void RemoveOwnProperty(JsValue property)
+        {
+            if (CommonProperties.Constructor.Equals(property))
             {
-                if (CommonProperties.Constructor.Equals(property))
-                {
-                    _constructor = desc;
-                }
-                else
-                {
-                    base.SetOwnProperty(property, desc);
-                }
+                _constructor = null;
             }
-
-            public override void RemoveOwnProperty(JsValue property)
+            else
             {
-                if (CommonProperties.Constructor.Equals(property))
-                {
-                    _constructor = null;
-                }
-                else
-                {
-                    base.RemoveOwnProperty(property);
-                }
+                base.RemoveOwnProperty(property);
             }
         }
     }

+ 108 - 109
Jint/Native/Function/FunctionConstructor.cs

@@ -5,133 +5,132 @@ using Jint.Runtime.Environments;
 using Jint.Runtime.Interpreter;
 using Environment = Jint.Runtime.Environments.Environment;
 
-namespace Jint.Native.Function
+namespace Jint.Native.Function;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-function-constructor
+/// </summary>
+public sealed class FunctionConstructor : Constructor
 {
-    /// <summary>
-    /// https://tc39.es/ecma262/#sec-function-constructor
-    /// </summary>
-    public sealed class FunctionConstructor : Constructor
+    private static readonly JsString _functionName = new JsString("Function");
+
+    internal FunctionConstructor(
+        Engine engine,
+        Realm realm,
+        ObjectPrototype objectPrototype)
+        : base(engine, realm, _functionName)
     {
-        private static readonly JsString _functionName = new JsString("Function");
+        PrototypeObject = new FunctionPrototype(engine, realm, objectPrototype);
+        _prototype = PrototypeObject;
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+        _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
+    }
 
-        internal FunctionConstructor(
-            Engine engine,
-            Realm realm,
-            ObjectPrototype objectPrototype)
-            : base(engine, realm, _functionName)
-        {
-            PrototypeObject = new FunctionPrototype(engine, realm, objectPrototype);
-            _prototype = PrototypeObject;
-            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
-            _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
-        }
+    internal FunctionPrototype PrototypeObject { get; }
 
-        internal FunctionPrototype PrototypeObject { get; }
+    protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+    {
+        return Construct(arguments, thisObject);
+    }
 
-        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
-        {
-            return Construct(arguments, thisObject);
-        }
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var function = CreateDynamicFunction(
+            this,
+            newTarget,
+            FunctionKind.Normal,
+            arguments);
 
-        public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
-        {
-            var function = CreateDynamicFunction(
-                this,
-                newTarget,
-                FunctionKind.Normal,
-                arguments);
+        return function;
+    }
 
-            return function;
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
+    /// </summary>
+    internal Function InstantiateFunctionObject(
+        JintFunctionDefinition functionDeclaration,
+        Environment scope,
+        PrivateEnvironment? privateEnv)
+    {
+        var function = functionDeclaration.Function;
+        if (!function.Generator)
+        {
+            return function.Async
+                ? InstantiateAsyncFunctionObject(functionDeclaration, scope, privateEnv)
+                : InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateEnv);
         }
-
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
-        /// </summary>
-        internal Function InstantiateFunctionObject(
-            JintFunctionDefinition functionDeclaration,
-            Environment scope,
-            PrivateEnvironment? privateEnv)
+        else
         {
-            var function = functionDeclaration.Function;
-            if (!function.Generator)
-            {
-                return function.Async
-                    ? InstantiateAsyncFunctionObject(functionDeclaration, scope, privateEnv)
-                    : InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateEnv);
-            }
-            else
-            {
-                return InstantiateGeneratorFunctionObject(functionDeclaration, scope, privateEnv);
-            }
+            return InstantiateGeneratorFunctionObject(functionDeclaration, scope, privateEnv);
         }
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionobject
-        /// </summary>
-        private ScriptFunction InstantiateAsyncFunctionObject(
-            JintFunctionDefinition functionDeclaration,
-            Environment env,
-            PrivateEnvironment? privateEnv)
-        {
-            var F = OrdinaryFunctionCreate(
-                _realm.Intrinsics.AsyncFunction.PrototypeObject,
-                functionDeclaration,
-                functionDeclaration.ThisMode,
-                env,
-                privateEnv);
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionobject
+    /// </summary>
+    private ScriptFunction InstantiateAsyncFunctionObject(
+        JintFunctionDefinition functionDeclaration,
+        Environment env,
+        PrivateEnvironment? privateEnv)
+    {
+        var F = OrdinaryFunctionCreate(
+            _realm.Intrinsics.AsyncFunction.PrototypeObject,
+            functionDeclaration,
+            functionDeclaration.ThisMode,
+            env,
+            privateEnv);
 
-            F.SetFunctionName(functionDeclaration.Name ?? "default");
+        F.SetFunctionName(functionDeclaration.Name ?? "default");
 
-            return F;
-        }
+        return F;
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionobject
-        /// </summary>
-        private ScriptFunction InstantiateOrdinaryFunctionObject(
-            JintFunctionDefinition functionDeclaration,
-            Environment env,
-            PrivateEnvironment? privateEnv)
-        {
-            var F = OrdinaryFunctionCreate(
-                _realm.Intrinsics.Function.PrototypeObject,
-                functionDeclaration,
-                functionDeclaration.ThisMode,
-                env,
-                privateEnv);
-
-            var name = functionDeclaration.Name ?? "default";
-            F.SetFunctionName(name);
-            F.MakeConstructor();
-            return F;
-        }
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionobject
+    /// </summary>
+    private ScriptFunction InstantiateOrdinaryFunctionObject(
+        JintFunctionDefinition functionDeclaration,
+        Environment env,
+        PrivateEnvironment? privateEnv)
+    {
+        var F = OrdinaryFunctionCreate(
+            _realm.Intrinsics.Function.PrototypeObject,
+            functionDeclaration,
+            functionDeclaration.ThisMode,
+            env,
+            privateEnv);
+
+        var name = functionDeclaration.Name ?? "default";
+        F.SetFunctionName(name);
+        F.MakeConstructor();
+        return F;
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionobject
-        /// </summary>
-        private ScriptFunction InstantiateGeneratorFunctionObject(
-            JintFunctionDefinition functionDeclaration,
-            Environment scope,
-            PrivateEnvironment? privateScope)
-        {
-            var thisMode = functionDeclaration.Strict || _engine._isStrict
-                ? FunctionThisMode.Strict
-                : FunctionThisMode.Global;
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionobject
+    /// </summary>
+    private ScriptFunction InstantiateGeneratorFunctionObject(
+        JintFunctionDefinition functionDeclaration,
+        Environment scope,
+        PrivateEnvironment? privateScope)
+    {
+        var thisMode = functionDeclaration.Strict || _engine._isStrict
+            ? FunctionThisMode.Strict
+            : FunctionThisMode.Global;
 
-            var name = functionDeclaration.Function.Id?.Name ?? "default";
-            var F = OrdinaryFunctionCreate(
-                _realm.Intrinsics.GeneratorFunction.PrototypeObject,
-                functionDeclaration,
-                thisMode,
-                scope,
-                privateScope);
+        var name = functionDeclaration.Function.Id?.Name ?? "default";
+        var F = OrdinaryFunctionCreate(
+            _realm.Intrinsics.GeneratorFunction.PrototypeObject,
+            functionDeclaration,
+            thisMode,
+            scope,
+            privateScope);
 
-            F.SetFunctionName(name);
+        F.SetFunctionName(name);
 
-            var prototype = OrdinaryObjectCreate(_engine, _realm.Intrinsics.GeneratorFunction.PrototypeObject.PrototypeObject);
-            F.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
+        var prototype = OrdinaryObjectCreate(_engine, _realm.Intrinsics.GeneratorFunction.PrototypeObject.PrototypeObject);
+        F.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
 
-            return F;
-        }
+        return F;
     }
 }

部分文件因为文件数量过多而无法显示