Просмотр исходного кода

Switch to using Acorn-based parsing via Acornima (#1820)

* Fix invalid template literal-related bug
* Update test262 suite exclusions
adams85 1 год назад
Родитель
Сommit
6d866a2d28
69 измененных файлов с 459 добавлено и 452 удалено
  1. 3 11
      Directory.Build.props
  2. 2 1
      Directory.Packages.props
  3. 2 3
      Jint.Benchmark/Jint.Benchmark.csproj
  4. 0 1
      Jint.Repl/Program.cs
  5. 1 0
      Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj
  6. 1 0
      Jint.Tests.PublicInterface/Jint.Tests.PublicInterface.csproj
  7. 3 4
      Jint.Tests.PublicInterface/RavenApiUsageTests.cs
  8. 1 0
      Jint.Tests.Test262/Jint.Tests.Test262.csproj
  9. 19 18
      Jint.Tests.Test262/Test262Harness.settings.json
  10. 2 2
      Jint.Tests.Test262/Test262Test.cs
  11. 1 0
      Jint.Tests/Jint.Tests.csproj
  12. 5 5
      Jint.Tests/Parser/JavascriptParserTests.cs
  13. 1 1
      Jint.Tests/Runtime/Debugger/BreakPointTests.cs
  14. 1 1
      Jint.Tests/Runtime/Debugger/EvaluateTests.cs
  15. 17 17
      Jint.Tests/Runtime/Debugger/StepFlowTests.cs
  16. 1 1
      Jint.Tests/Runtime/Debugger/TestHelpers.cs
  17. 7 8
      Jint.Tests/Runtime/EngineTests.ScriptPreparation.cs
  18. 9 9
      Jint.Tests/Runtime/EngineTests.cs
  19. 2 2
      Jint.Tests/Runtime/ErrorTests.cs
  20. 5 5
      Jint.Tests/Runtime/ModuleTests.cs
  21. 49 50
      Jint.Tests/Runtime/ParserOptionsPropagationTests.cs
  22. 45 29
      Jint/AstExtensions.cs
  23. 16 42
      Jint/Engine.Ast.cs
  24. 3 8
      Jint/Engine.Defaults.cs
  25. 1 1
      Jint/Engine.Modules.cs
  26. 21 25
      Jint/Engine.cs
  27. 49 0
      Jint/Extensions/Character.cs
  28. 1 1
      Jint/Jint.csproj
  29. 0 9
      Jint/Messages.cs
  30. 12 13
      Jint/Native/Function/ClassDefinition.cs
  31. 10 4
      Jint/Native/Function/EvalFunction.cs
  32. 2 2
      Jint/Native/Function/FunctionInstance.Dynamic.cs
  33. 2 2
      Jint/Native/Generator/GeneratorInstance.cs
  34. 1 0
      Jint/Native/Global/GlobalObject.cs
  35. 3 1
      Jint/Native/RegExp/RegExpConstructor.cs
  36. 3 3
      Jint/Native/ShadowRealm/ShadowRealm.cs
  37. 1 7
      Jint/ParsingOptions.cs
  38. 6 5
      Jint/Runtime/CallStack/CallStackElement.cs
  39. 2 2
      Jint/Runtime/CallStack/JintCallStack.cs
  40. 3 3
      Jint/Runtime/Completion.cs
  41. 1 1
      Jint/Runtime/Debugger/BreakLocation.cs
  42. 3 2
      Jint/Runtime/Debugger/CallFrame.cs
  43. 2 2
      Jint/Runtime/Debugger/DebugHandler.cs
  44. 1 1
      Jint/Runtime/Debugger/DebugInformation.cs
  45. 2 2
      Jint/Runtime/Environments/FunctionEnvironment.cs
  46. 2 2
      Jint/Runtime/Interpreter/EvaluationContext.cs
  47. 1 1
      Jint/Runtime/Interpreter/Expressions/DestructuringPatternAssignmentExpression.cs
  48. 29 30
      Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs
  49. 31 33
      Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs
  50. 7 7
      Jint/Runtime/Interpreter/Expressions/JintExpression.cs
  51. 10 12
      Jint/Runtime/Interpreter/Expressions/JintLiteralExpression.cs
  52. 2 2
      Jint/Runtime/Interpreter/Expressions/JintLogicalAndExpression.cs
  53. 1 1
      Jint/Runtime/Interpreter/Expressions/JintLogicalOrExpression.cs
  54. 1 1
      Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs
  55. 1 1
      Jint/Runtime/Interpreter/Expressions/JintObjectExpression.cs
  56. 1 1
      Jint/Runtime/Interpreter/Expressions/JintTaggedTemplateExpression.cs
  57. 7 8
      Jint/Runtime/Interpreter/Expressions/JintUnaryExpression.cs
  58. 2 2
      Jint/Runtime/Interpreter/Expressions/JintUpdateExpression.cs
  59. 1 1
      Jint/Runtime/Interpreter/Expressions/NullishCoalescingExpression.cs
  60. 7 6
      Jint/Runtime/Interpreter/JintFunctionDefinition.cs
  61. 4 4
      Jint/Runtime/Interpreter/JintStatementList.cs
  62. 2 2
      Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs
  63. 4 4
      Jint/Runtime/Interpreter/Statements/JintStatement.cs
  64. 1 1
      Jint/Runtime/Interpreter/Statements/ProbablyBlockStatement.cs
  65. 3 2
      Jint/Runtime/Modules/CyclicModule.cs
  66. 11 20
      Jint/Runtime/Modules/ModuleBuilder.cs
  67. 5 5
      Jint/Runtime/Modules/ModuleFactory.cs
  68. 1 1
      Jint/Runtime/Modules/ModuleLoader.cs
  69. 3 1
      Jint/Runtime/TypeConverter.cs

+ 3 - 11
Directory.Build.props

@@ -27,17 +27,9 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <Using Include="Esprima" />
-    <Using Include="Esprima.Ast" />
-    <Using Include="Esprima.Utils" />
-
-    <Using Include="Esprima.Ast.BindingPattern" Alias="DestructuringPattern" />
-    <Using Include="Esprima.Ast.Module" Alias="AstModule" />
-    <Using Include="Esprima.Ast.Nodes" Alias="NodeType" />
-    <Using Include="Esprima.JavaScriptParser" Alias="Parser" />
-    <Using Include="Esprima.Location" Alias="SourceLocation" />
-    <Using Include="Esprima.TokenType" Alias="TokenKind" />
-    <Using Include="Esprima.ParserException" Alias="ParseErrorException" />
+    <Using Include="Acornima" />
+    <Using Include="Acornima.Ast" />
+    <Using Include="Acornima.Ast.Module" Alias="AstModule" />
   </ItemGroup>
 
 </Project>

+ 2 - 1
Directory.Packages.props

@@ -4,9 +4,10 @@
     <CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
   </PropertyGroup>
   <ItemGroup>
+    <PackageVersion Include="Acornima" Version="1.0.0" />
+    <PackageVersion Include="Acornima.Extras" Version="1.0.0" />
     <PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
     <PackageVersion Include="BenchmarkDotNet.TestAdapter" Version="0.13.12" />
-    <PackageVersion Include="Esprima" Version="3.0.5" />
     <PackageVersion Include="FluentAssertions" Version="6.12.0" />
     <PackageVersion Include="Flurl.Http.Signed" Version="3.2.4" />
     <PackageVersion Include="Jurassic" Version="3.2.7" />

+ 2 - 3
Jint.Benchmark/Jint.Benchmark.csproj

@@ -32,8 +32,7 @@
     <PackageReference Include="YantraJS.Core" />
   </ItemGroup>
   <ItemGroup>
-    <Using Include="Esprima" />
-    <Using Include="Esprima.Ast" />
-    <Using Include="Esprima.JavaScriptParser" Alias="Parser" />
+    <Using Include="Acornima" />
+    <Using Include="Acornima.Ast" />
   </ItemGroup>
 </Project>

+ 0 - 1
Jint.Repl/Program.cs

@@ -43,7 +43,6 @@ var defaultColor = Console.ForegroundColor;
 var parsingOptions = new ScriptParsingOptions
 {
     Tolerant = true,
-    CompileRegex = false,
 };
 
 var serializer = new JsonSerializer(engine);

+ 1 - 0
Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj

@@ -17,6 +17,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="Acornima.Extras" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" />
     <PackageReference Include="NUnit" />
     <PackageReference Include="NUnit3TestAdapter" />

+ 1 - 0
Jint.Tests.PublicInterface/Jint.Tests.PublicInterface.csproj

@@ -22,6 +22,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="Acornima.Extras" />
     <PackageReference Include="Flurl.Http.Signed" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" />
     <PackageReference Include="MongoDB.Bson.signed" />

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

@@ -18,16 +18,15 @@ public class RavenApiUsageTests
 
         var properties = new List<Node>
         {
-            new Property(PropertyKind.Init, new Identifier("field"), false,
-                new StaticMemberExpression(new Identifier("self"), new Identifier("field"), optional: false), false, false)
+            new ObjectProperty(PropertyKind.Init, new Identifier("field"),
+                new MemberExpression(new Identifier("self"), new Identifier("field"), computed: false, optional: false), false, false, false)
         };
 
         var functionExp = new FunctionExpression(
             new Identifier("functionId"),
             NodeList.Create<Node>(new List<Expression> { new Identifier("self") }),
-            new BlockStatement(NodeList.Create(new List<Statement> { new ReturnStatement(new ObjectExpression(NodeList.Create(properties))) })),
+            new FunctionBody(NodeList.Create(new List<Statement> { new ReturnStatement(new ObjectExpression(NodeList.Create(properties))) }), strict: false),
             generator: false,
-            strict: false,
             async: false);
 
         var functionObject = new ScriptFunction(

+ 1 - 0
Jint.Tests.Test262/Jint.Tests.Test262.csproj

@@ -16,6 +16,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="Acornima.Extras" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" />
     <PackageReference Include="NUnit" />
     <PackageReference Include="NUnit3TestAdapter" />

+ 19 - 18
Jint.Tests.Test262/Test262Harness.settings.json

@@ -8,9 +8,9 @@
     "Array.fromAsync",
     "async-iteration",
     "Atomics",
+    "decorators",
     "import-assertions",
     "iterator-helpers",
-    "regexp-duplicate-named-groups",
     "regexp-lookbehind",
     "regexp-unicode-property-escapes",
     "regexp-v-flag",
@@ -43,6 +43,24 @@
     "language/literals/regexp/u-case-mapping.js",
     "built-ins/RegExp/lookahead-quantifier-match-groups.js",
     "built-ins/RegExp/unicode_full_case_folding.js",
+    "built-ins/RegExp/named-groups/duplicate-names-exec.js",
+    "built-ins/RegExp/named-groups/duplicate-names-exec.js",
+    "built-ins/RegExp/named-groups/duplicate-names-match.js",
+    "built-ins/RegExp/named-groups/duplicate-names-match.js",
+    "built-ins/RegExp/named-groups/duplicate-names-match-indices.js",
+    "built-ins/RegExp/named-groups/duplicate-names-match-indices.js",
+    "built-ins/RegExp/named-groups/duplicate-names-replace.js",
+    "built-ins/RegExp/named-groups/duplicate-names-replace.js",
+    "built-ins/RegExp/named-groups/duplicate-names-replaceall.js",
+    "built-ins/RegExp/named-groups/duplicate-names-replaceall.js",
+    "built-ins/RegExp/prototype/exec/duplicate-named-groups-properties.js",
+    "built-ins/RegExp/prototype/exec/duplicate-named-groups-properties.js",
+    "built-ins/RegExp/prototype/exec/duplicate-named-indices-groups-properties.js",
+    "built-ins/RegExp/prototype/exec/duplicate-named-indices-groups-properties.js",
+    "built-ins/String/prototype/match/duplicate-named-groups-properties.js",
+    "built-ins/String/prototype/match/duplicate-named-groups-properties.js",
+    "built-ins/String/prototype/match/duplicate-named-indices-groups-properties.js",
+    "built-ins/String/prototype/match/duplicate-named-indices-groups-properties.js",
 
     // requires investigation how to process complex function name evaluation for property
     "built-ins/Function/prototype/toString/method-computed-property-name.js",
@@ -68,10 +86,6 @@
     // C# can't distinguish 1.797693134862315808e+308 and 1.797693134862315708145274237317e+308
     "language/types/number/8.5.1.js",
 
-    // inner binding is immutable (from parameters) Expected SameValue(«null», «function() {{ ... }}») to be true
-    "language/expressions/function/scope-name-var-open-non-strict.js",
-    "language/expressions/function/scope-name-var-open-strict.js",
-
     // generators
     "built-ins/GeneratorFunction/instance-yield-expr-in-param.js",
     "built-ins/GeneratorFunction/instance-yield-expr-in-param.js",
@@ -1018,15 +1032,6 @@
     "language/statements/variable/dstr/ary-ptrn-elision.js",
     "language/statements/variable/dstr/ary-ptrn-elision.js",
 
-     // Esprima problem
-    "language/expressions/object/let-non-strict-access.js",
-    "language/expressions/object/let-non-strict-syntax.js",
-    "language/expressions/object/yield-non-strict-access.js",
-    "language/expressions/object/yield-non-strict-syntax.js",
-    "language/expressions/tagged-template/invalid-escape-sequences.js",
-    "language/statements/for-of/dstr-obj-id-identifier-yield-ident-valid.js",
-    "language/statements/for/head-lhs-let.js",
-
     // SharedArrayBuffer not implemented
     "built-ins/SharedArrayBuffer/prototype/prop-desc.js",
 
@@ -1034,7 +1039,6 @@
     "built-ins/**/special_casing*.js",
 
     // failing tests in new test suite (due to updating to latest and using whole set)
-    "language/arguments-object/mapped/nonconfigurable-descriptors-define-failure.js",
     "language/eval-code/direct/arrow-fn-a-following-parameter-is-named-arguments-arrow-func-declare-arguments-assign-incl-def-param-arrow-arguments.js",
     "language/eval-code/direct/arrow-fn-a-following-parameter-is-named-arguments-arrow-func-declare-arguments-assign.js",
     "language/eval-code/direct/arrow-fn-a-preceding-parameter-is-named-arguments-arrow-func-declare-arguments-assign-incl-def-param-arrow-arguments.js",
@@ -1203,7 +1207,6 @@
     "language/expressions/assignment/dstr/array-elem-put-obj-literal-prop-ref-init.js",
     "language/expressions/assignment/dstr/obj-prop-elem-target-obj-literal-prop-ref-init-active.js",
     "language/expressions/assignment/dstr/obj-prop-elem-target-obj-literal-prop-ref-init.js",
-    "language/expressions/assignment/fn-name-lhs-member.js",
     "language/expressions/assignment/target-member-computed-reference-null.js",
     "language/expressions/assignment/target-member-computed-reference-undefined.js",
     "language/expressions/assignment/target-member-identifier-reference-null.js",
@@ -1243,8 +1246,6 @@
     "language/statements/for-of/dstr/obj-id-init-let.js",
     "language/statements/for-of/dstr/obj-prop-elem-target-obj-literal-prop-ref-init-active.js",
     "language/statements/for-of/dstr/obj-prop-elem-target-obj-literal-prop-ref-init.js",
-    "language/statements/for-of/head-lhs-async-dot.js",
-    "language/statements/for-of/head-lhs-async-escaped.js",
     "language/statements/function/cptn-decl.js",
     "language/statements/function/dstr/ary-init-iter-get-err-array-prototype.js",
     "language/statements/function/dstr/dflt-ary-init-iter-get-err-array-prototype.js",

+ 2 - 2
Jint.Tests.Test262/Test262Test.cs

@@ -39,7 +39,7 @@ public abstract partial class Test262Test
 
                 var script = Engine.PrepareScript(args.At(0).AsString(), options: new ScriptPreparationOptions
                 {
-                    ParsingOptions = ScriptParsingOptions.Default with { CompileRegex = false, Tolerant = false },
+                    ParsingOptions = ScriptParsingOptions.Default with { Tolerant = false },
                 });
 
                 return engine.Evaluate(script);
@@ -96,7 +96,7 @@ public abstract partial class Test262Test
         {
             var script = Engine.PrepareScript(file.Program, source: file.FileName, options: new ScriptPreparationOptions
             {
-                ParsingOptions = ScriptParsingOptions.Default with { CompileRegex = false, Tolerant = false },
+                ParsingOptions = ScriptParsingOptions.Default with { Tolerant = false },
             });
 
             engine.Execute(script);

+ 1 - 0
Jint.Tests/Jint.Tests.csproj

@@ -24,6 +24,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="Acornima.Extras" />
     <PackageReference Include="FluentAssertions" />
     <PackageReference Include="Flurl.Http.Signed" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection" />

+ 5 - 5
Jint.Tests/Parser/JavascriptParserTests.cs

@@ -52,10 +52,10 @@ public class JavascriptParserTests
         Assert.Single(body);
         Assert.NotNull(binary = body.First().As<ExpressionStatement>().Expression.As<BinaryExpression>());
         Assert.Equal(3d, binary.Right.As<Literal>().Value);
-        Assert.Equal(BinaryOperator.Times, binary.Operator);
+        Assert.Equal(Operator.Multiplication, binary.Operator);
         Assert.Equal(1d, binary.Left.As<BinaryExpression>().Left.As<Literal>().Value);
         Assert.Equal(2d, binary.Left.As<BinaryExpression>().Right.As<Literal>().Value);
-        Assert.Equal(BinaryOperator.Plus, binary.Left.As<BinaryExpression>().Operator);
+        Assert.Equal(Operator.Addition, binary.Left.As<BinaryExpression>().Operator);
     }
 
     [Theory]
@@ -154,7 +154,7 @@ public class JavascriptParserTests
 \
 '
 ";
-        var program = new Parser(new ParserOptions()).ParseScript(Code);
+        var program = new Parser().ParseScript(Code);
         var expr = program.Body.First().As<ExpressionStatement>().Expression;
         Assert.Equal(1, expr.Location.Start.Line);
         Assert.Equal(0, expr.Location.Start.Column);
@@ -165,7 +165,7 @@ public class JavascriptParserTests
     [Fact]
     public void ShouldThrowErrorForInvalidLeftHandOperation()
     {
-        Assert.Throws<JavaScriptException>(() => new Engine().Execute("~ (WE0=1)--- l('1');"));
+        Assert.Throws<SyntaxErrorException>(() => new Engine().Execute("~ (WE0=1)--- l('1');"));
     }
 
 
@@ -176,6 +176,6 @@ public class JavascriptParserTests
     [InlineData("-.-")]
     public void ShouldThrowParseErrorExceptionForInvalidCode(string code)
     {
-        Assert.Throws<ParseErrorException>(() => new Parser().ParseScript(code));
+        Assert.Throws<SyntaxErrorException>(() => new Parser().ParseScript(code));
     }
 }

+ 1 - 1
Jint.Tests/Runtime/Debugger/BreakPointTests.cs

@@ -157,7 +157,7 @@ test(z);";
             bool didBreak = false;
             engine.Debugger.Break += (sender, info) =>
             {
-                Assert.Equal("script2", info.Location.Source);
+                Assert.Equal("script2", info.Location.SourceFile);
                 Assert.Equal(3, info.Location.Start.Line);
                 Assert.Equal(0, info.Location.Start.Column);
                 didBreak = true;

+ 1 - 1
Jint.Tests/Runtime/Debugger/EvaluateTests.cs

@@ -72,7 +72,7 @@ namespace Jint.Tests.Runtime.Debugger
             {
                 var exception = Assert.Throws<DebugEvaluationException>(() =>
                     engine.Debugger.Evaluate("this is a syntax error"));
-                Assert.IsType<ParseErrorException>(exception.InnerException);
+                Assert.IsType<SyntaxErrorException>(exception.InnerException);
             });
         }
 

+ 17 - 17
Jint.Tests/Runtime/Debugger/StepFlowTests.cs

@@ -38,11 +38,11 @@ namespace Jint.Tests.Runtime.Debugger
             Assert.Collection(nodes,
                 node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
                 node => Assert.IsType<WhileStatement>(node),      // while ...
-                node => Assert.IsType<BinaryExpression>(node),    // x < 2
-                node => Assert.IsType<ExpressionStatement>(node), // x++;
-                node => Assert.IsType<BinaryExpression>(node),    // x < 2
-                node => Assert.IsType<ExpressionStatement>(node), // x++;
-                node => Assert.IsType<BinaryExpression>(node)     // x < 2 (false)
+                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)
             );
         }
 
@@ -63,10 +63,10 @@ namespace Jint.Tests.Runtime.Debugger
             Assert.Collection(nodes,
                 node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
                 node => Assert.IsType<DoWhileStatement>(node),    // do ...
-                node => Assert.IsType<ExpressionStatement>(node), // x++;
-                node => Assert.IsType<BinaryExpression>(node),    // x < 2
-                node => Assert.IsType<ExpressionStatement>(node), // x++;
-                node => Assert.IsType<BinaryExpression>(node)     // x < 2 (false)
+                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)
             );
         }
 
@@ -85,13 +85,13 @@ namespace Jint.Tests.Runtime.Debugger
             Assert.Collection(nodes,
                 node => Assert.IsType<ForStatement>(node),        // for ...
                 node => Assert.IsType<VariableDeclaration>(node), // let x = 0
-                node => Assert.IsType<BinaryExpression>(node),    // x < 2
+                node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
                 node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
                 node => Assert.IsType<UpdateExpression>(node),    // x++;
-                node => Assert.IsType<BinaryExpression>(node),    // x < 2
+                node => Assert.IsType<NonLogicalBinaryExpression>(node),    // x < 2
                 node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
                 node => Assert.IsType<UpdateExpression>(node),    // x++;
-                node => Assert.IsType<BinaryExpression>(node)     // x < 2 (false)
+                node => Assert.IsType<NonLogicalBinaryExpression>(node)     // x < 2 (false)
             );
         }
 
@@ -135,9 +135,9 @@ namespace Jint.Tests.Runtime.Debugger
                 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<ExpressionStatement>(node), // 'dummy';
+                node => Assert.IsType<NonSpecialExpressionStatement>(node), // 'dummy';
                 node => Assert.IsType<VariableDeclaration>(node), // key
-                node => Assert.IsType<ExpressionStatement>(node)  // 'dummy';
+                node => Assert.IsType<NonSpecialExpressionStatement>(node)  // 'dummy';
             );
         }
 
@@ -160,7 +160,7 @@ namespace Jint.Tests.Runtime.Debugger
 
             Assert.Collection(nodes,
                 node => Assert.IsType<ClassDeclaration>(node),          // class Test
-                node => Assert.IsType<ExpressionStatement>(node),       // new 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"))
@@ -182,7 +182,7 @@ namespace Jint.Tests.Runtime.Debugger
 
             Assert.Collection(nodes,
                 node => Assert.IsType<FunctionDeclaration>(node), // function(test) ...;
-                node => Assert.IsType<ExpressionStatement>(node), // test();
+                node => Assert.IsType<NonSpecialExpressionStatement>(node), // test();
                 node => Assert.True(node.IsLiteral("dummy")),     // 'dummy';
                 node => Assert.Null(node)                         // return point
             );
@@ -202,7 +202,7 @@ namespace Jint.Tests.Runtime.Debugger
             var nodes = CollectStepNodes(script);
             Assert.Collection(nodes,
                 node => Assert.IsType<ClassDeclaration>(node),    // class Test
-                node => Assert.IsType<ExpressionStatement>(node), // new Test();
+                node => Assert.IsType<NonSpecialExpressionStatement>(node), // new Test();
                 node => Assert.True(node.IsLiteral("dummy"))      // 'dummy';
             );
         }

+ 1 - 1
Jint.Tests/Runtime/Debugger/TestHelpers.cs

@@ -9,7 +9,7 @@ namespace Jint.Tests.Runtime.Debugger
             return node switch
             {
                 Directive directive => requiredValue == null || directive.Value == requiredValue,
-                ExpressionStatement expr => requiredValue == null || (expr.Expression is Literal literal && literal.StringValue == requiredValue),
+                NonSpecialExpressionStatement expr => requiredValue == null || (expr.Expression is StringLiteral literal && literal.Value == requiredValue),
                 _ => false
             };
         }

+ 7 - 8
Jint.Tests/Runtime/EngineTests.ScriptPreparation.cs

@@ -21,9 +21,8 @@ public partial class EngineTests
         var script = Engine.PrepareScript("var x = /[cgt]/ig; var y = /[cgt]/ig; 'g'.match(x).length;");
         var declaration = Assert.IsType<VariableDeclaration>(script.Program.Body[0]);
         var init = Assert.IsType<RegExpLiteral>(declaration.Declarations[0].Init);
-        var regex = Assert.IsType<Regex>(init.Value);
-        Assert.Equal("[cgt]", regex.ToString());
-        Assert.Equal(RegexOptions.Compiled, regex.Options & RegexOptions.Compiled);
+        Assert.Equal("[cgt]", init.Value.ToString());
+        Assert.Equal(RegexOptions.Compiled, init.Value.Options & RegexOptions.Compiled);
 
         Assert.Equal(1, _engine.Evaluate(script));
     }
@@ -33,7 +32,7 @@ public partial class EngineTests
     {
         var preparedScript = Engine.PrepareScript("return 1 + 2;");
         var returnStatement = Assert.IsType<ReturnStatement>(preparedScript.Program.Body[0]);
-        var constant = Assert.IsType<JintConstantExpression>(returnStatement.Argument?.AssociatedData);
+        var constant = Assert.IsType<JintConstantExpression>(returnStatement.Argument?.UserData);
         Assert.Equal(3, constant.GetValue(null!));
 
         Assert.Equal(3, _engine.Evaluate(preparedScript));
@@ -43,9 +42,9 @@ public partial class EngineTests
     public void ScriptPreparationOptimizesNegatingUnaryExpression()
     {
         var preparedScript = Engine.PrepareScript("-1");
-        var expression = Assert.IsType<ExpressionStatement>(preparedScript.Program.Body[0]);
-        var unaryExpression = Assert.IsType<UnaryExpression>(expression.Expression);
-        var constant = Assert.IsType<JintConstantExpression>(unaryExpression.AssociatedData);
+        var expression = Assert.IsType<NonSpecialExpressionStatement>(preparedScript.Program.Body[0]);
+        var unaryExpression = Assert.IsType<NonUpdateUnaryExpression>(expression.Expression);
+        var constant = Assert.IsType<JintConstantExpression>(unaryExpression.UserData);
 
         Assert.Equal(-1, constant.GetValue(null!));
         Assert.Equal(-1, _engine.Evaluate(preparedScript));
@@ -56,7 +55,7 @@ public partial class EngineTests
     {
         var preparedScript = Engine.PrepareScript("return false;");
         var statement = Assert.IsType<ReturnStatement>(preparedScript.Program.Body[0]);
-        var returnStatement = Assert.IsType<ConstantStatement>(statement.AssociatedData);
+        var returnStatement = Assert.IsType<ConstantStatement>(statement.UserData);
 
         var builtStatement = JintStatement.Build(statement);
         Assert.Same(returnStatement, builtStatement);

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

@@ -1046,11 +1046,11 @@ namespace Jint.Tests.Runtime
             {
                 engine.Evaluate("1.2+ new", "jQuery.js");
             }
-            catch (ParseErrorException e)
+            catch (SyntaxErrorException e)
             {
                 Assert.Equal(1, e.LineNumber);
-                Assert.Equal(9, e.Column);
-                Assert.Equal("jQuery.js", e.SourceLocation);
+                Assert.Equal(8, e.Column);
+                Assert.Equal("jQuery.js", e.SourceFile);
             }
         }
         #region DateParsingAndStrings
@@ -1314,7 +1314,7 @@ var prep = function (fn) { fn(); };
         {
             var code = "if({ __proto__: [], __proto__:[] } instanceof Array) {}";
 
-            Exception ex = Assert.Throws<ParseErrorException>(() => _engine.Execute(code, new ScriptParsingOptions { Tolerant = false }));
+            Exception ex = Assert.Throws<SyntaxErrorException>(() => _engine.Execute(code, new ScriptParsingOptions { Tolerant = false }));
             Assert.Contains("Duplicate __proto__ fields are not allowed in object literals", ex.Message);
 
             ex = Assert.Throws<JavaScriptException>(() => _engine.Execute($"eval('{code}')"));
@@ -2865,8 +2865,8 @@ x.test = {
             Assert.Equal("Cannot delete property 'prototype' of function Boolean() { [native code] }", ex.Message);
 
             const string source2 = "'use strict'; delete foobar;";
-            ex = Assert.Throws<JavaScriptException>(() => engine.Evaluate(source2));
-            Assert.Equal("Delete of an unqualified identifier in strict mode.", ex.Message);
+            var ex2 = Assert.Throws<SyntaxErrorException>(() => engine.Evaluate(source2));
+            Assert.Equal("Delete of an unqualified identifier in strict mode", ex2.Description);
         }
 
         [Fact]
@@ -3011,13 +3011,13 @@ x.test = {
                 switch (beforeEvaluateTriggeredCount)
                 {
                     case 1:
-                        Assert.Equal("module1", ast.Location.Source);
+                        Assert.Equal("module1", ast.Location.SourceFile);
                         Assert.Collection(ast.Body,
                             node => Assert.IsType<ImportDeclaration>(node)
                         );
                         break;
                     case 2:
-                        Assert.Equal("module2", ast.Location.Source);
+                        Assert.Equal("module2", ast.Location.SourceFile);
                         Assert.Collection(ast.Body,
                             node => Assert.IsType<ExportDefaultDeclaration>(node)
                         );
@@ -3058,7 +3058,7 @@ x.test = {
             {
                 beforeEvaluateTriggered = true;
                 Assert.Equal(engine, sender);
-                Assert.Equal(expectedSource, ast.Location.Source);
+                Assert.Equal(expectedSource, ast.Location.SourceFile);
                 Assert.Collection(ast.Body, node => Assert.True(TestHelpers.IsLiteral(node, "dummy")));
             };
 

+ 2 - 2
Jint.Tests/Runtime/ErrorTests.cs

@@ -72,7 +72,7 @@ var b = function(v) {
             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.Source);
+            Assert.Equal("custom.js", e.Location.SourceFile);
 
             var stack = e.JavaScriptStackTrace;
             EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:16
@@ -99,7 +99,7 @@ var b = function(v) {
             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.Source);
+            Assert.Equal("custom.js", e.Location.SourceFile);
 
             var stack = e.JavaScriptStackTrace;
             EqualIgnoringNewLineDifferences(@"   at a (v) custom.js:3:9

+ 5 - 5
Jint.Tests/Runtime/ModuleTests.cs

@@ -112,8 +112,8 @@ public class ModuleTests
         _engine.Modules.Add("my-module", "import { invalid } from 'imported';");
 
         var exc = Assert.Throws<JavaScriptException>(() =>  _engine.Modules.Import("my-module"));
-        Assert.Equal("Error while loading module: error in module 'imported': Line 1: Missing initializer in const declaration", exc.Message);
-        Assert.Equal("imported", exc.Location.Source);
+        Assert.Equal("Error while loading module: error in module 'imported': Missing initializer in const declaration (imported:1:21)", exc.Message);
+        Assert.Equal("imported", exc.Location.SourceFile);
     }
 
     [Fact]
@@ -123,8 +123,8 @@ public class ModuleTests
         _engine.Modules.Add("my-module", "import { value } from 'imported';");
 
         var exc = Assert.Throws<JavaScriptException>(() =>  _engine.Modules.Import("my-module"));
-        Assert.Equal("Error while loading module: error in module 'imported': Line 1: Unexpected identifier", exc.Message);
-        Assert.Equal("imported", exc.Location.Source);
+        Assert.Equal("Error while loading module: error in module 'imported': Unexpected identifier 'invalid' (imported:1:8)", exc.Message);
+        Assert.Equal("imported", exc.Location.SourceFile);
     }
 
     [Fact]
@@ -134,7 +134,7 @@ public class ModuleTests
 
         var exc = Assert.Throws<JavaScriptException>(() =>  _engine.Modules.Import("my-module"));
         Assert.Equal("imported successfully", exc.Message);
-        Assert.Equal("my-module", exc.Location.Source);
+        Assert.Equal("my-module", exc.Location.SourceFile);
     }
 
     [Fact]

+ 49 - 50
Jint.Tests/Runtime/ParserOptionsPropagationTests.cs

@@ -51,45 +51,44 @@ public class ParserOptionsPropagationTests
     }
 
     [Theory]
-    // NOTE: Can't test eval as Esprima can't parse eval code in non-tolerant mode.
-    //[InlineData(SourceKind.Script, @"'' + eval('!!({g\\u0065t y() {} })')", false, false, null)]
-    //[InlineData(SourceKind.Script, @"'' + eval('!!({g\\u0065t y() {} })')", true, false, null)]
-    //[InlineData(SourceKind.Script, @"({g\u0065t x() {} }) + eval('!!({g\\u0065t y() {} })')", false, true, "[object Object]true")]
-    //[InlineData(SourceKind.Script, @"({g\u0065t x() {} }) + eval('!!({g\\u0065t y() {} })')", true, true, "[object Object]true")]
-    //[InlineData(SourceKind.ModuleViaBuilder, @"export default '' + eval('!!({g\\u0065t y() {} })')", false, false, null)]
-    //[InlineData(SourceKind.ModuleViaBuilder, @"export default '' + eval('!!({g\\u0065t y() {} })')", true, false, null)]
-    //[InlineData(SourceKind.ModuleViaBuilder, @"export default ({g\u0065t x() {} }) + eval('!!({g\\u0065t y() {} })')", false, true, "[object Object]true")]
-    //[InlineData(SourceKind.ModuleViaBuilder, @"export default ({g\u0065t x() {} }) + eval('!!({g\\u0065t y() {} })')", true, true, "[object Object]true")]
-    //[InlineData(SourceKind.ModuleViaFactory, @"export default '' + eval('!!({g\\u0065t y() {} })')", false, false, null)]
-    //[InlineData(SourceKind.ModuleViaFactory, @"export default '' + eval('!!({g\\u0065t y() {} })')", true, false, null)]
-    //[InlineData(SourceKind.ModuleViaFactory, @"export default ({g\u0065t x() {} }) + eval('!!({g\\u0065t y() {} })')", false, true, "[object Object]true")]
-    //[InlineData(SourceKind.ModuleViaFactory, @"export default ({g\u0065t x() {} }) + eval('!!({g\\u0065t y() {} })')", true, true, "[object Object]true")]
-
-    [InlineData(SourceKind.Script, @"'' + new Function('return !!({g\\u0065t y() {} })')()", false, false, null)]
-    [InlineData(SourceKind.Script, @"'' + new Function('return !!({g\\u0065t y() {} })')()", true, false, null)]
-    [InlineData(SourceKind.Script, @"({g\u0065t x() {} }) + new Function('return !!({g\\u0065t y() {} })')()", false, true, "[object Object]true")]
-    [InlineData(SourceKind.Script, @"({g\u0065t x() {} }) + new Function('return !!({g\\u0065t y() {} })')()", true, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new Function('return !!({g\\u0065t y() {} })')()", false, false, null)]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new Function('return !!({g\\u0065t y() {} })')()", true, false, null)]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default ({g\u0065t x() {} }) + new Function('return !!({g\\u0065t y() {} })')()", false, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default ({g\u0065t x() {} }) + new Function('return !!({g\\u0065t y() {} })')()", true, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new Function('return !!({g\\u0065t y() {} })')()", false, false, null)]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new Function('return !!({g\\u0065t y() {} })')()", true, false, null)]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default ({g\u0065t x() {} }) + new Function('return !!({g\\u0065t y() {} })')()", false, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default ({g\u0065t x() {} }) + new Function('return !!({g\\u0065t y() {} })')()", true, true, "[object Object]true")]
-
-    [InlineData(SourceKind.Script, @"'' + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", false, false, null)]
-    [InlineData(SourceKind.Script, @"'' + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", true, false, null)]
-    [InlineData(SourceKind.Script, @"({g\u0065t x() {} }) + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", false, true, "[object Object]true")]
-    [InlineData(SourceKind.Script, @"({g\u0065t x() {} }) + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", true, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", false, false, null)]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", true, false, null)]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default ({g\u0065t x() {} }) + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", false, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaBuilder, @"export default ({g\u0065t x() {} }) + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", true, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", false, false, null)]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", true, false, null)]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default ({g\u0065t x() {} }) + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", false, true, "[object Object]true")]
-    [InlineData(SourceKind.ModuleViaFactory, @"export default ({g\u0065t x() {} }) + new ShadowRealm().evaluate('!!({g\\u0065t y() {} })')", true, true, "[object Object]true")]
+    [InlineData(SourceKind.Script, @"'' + eval('(1, 2,)')", false, false, null)]
+    [InlineData(SourceKind.Script, @"'' + eval('(1, 2,)')", true, false, null)]
+    [InlineData(SourceKind.Script, @"('',) + eval('(1, 2,)')", false, true, "2")]
+    [InlineData(SourceKind.Script, @"('',) + eval('(1, 2,)')", true, true, "2")]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + eval('(1, 2,)')", false, false, null)]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + eval('(1, 2,)')", true, false, null)]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default ('',) + eval('(1, 2,)')", false, true, "2")]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default ('',) + eval('(1, 2,)')", true, true, "2")]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + eval('(1, 2,)')", false, false, null)]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + eval('(1, 2,)')", true, false, null)]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default ('',) + eval('(1, 2,)')", false, true, "2")]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default ('',) + eval('(1, 2,)')", true, true, "2")]
+
+    [InlineData(SourceKind.Script, @"'' + new Function('return (1, 2,)')()", false, false, null)]
+    [InlineData(SourceKind.Script, @"'' + new Function('return (1, 2,)')()", true, false, null)]
+    [InlineData(SourceKind.Script, @"('',) + new Function('return (1, 2,)')()", false, true, "2")]
+    [InlineData(SourceKind.Script, @"('',) + new Function('return (1, 2,)')()", true, true, "2")]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new Function('return (1, 2,)')()", false, false, null)]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new Function('return (1, 2,)')()", true, false, null)]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default ('',) + new Function('return (1, 2,)')()", false, true, "2")]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default ('',) + new Function('return (1, 2,)')()", true, true, "2")]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new Function('return (1, 2,)')()", false, false, null)]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new Function('return (1, 2,)')()", true, false, null)]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default ('',) + new Function('return (1, 2,)')()", false, true, "2")]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default ('',) + new Function('return (1, 2,)')()", true, true, "2")]
+
+    [InlineData(SourceKind.Script, @"'' + new ShadowRealm().evaluate('(1, 2,)')", false, false, null)]
+    [InlineData(SourceKind.Script, @"'' + new ShadowRealm().evaluate('(1, 2,)')", true, false, null)]
+    [InlineData(SourceKind.Script, @"('',) + new ShadowRealm().evaluate('(1, 2,)')", false, true, "2")]
+    [InlineData(SourceKind.Script, @"('',) + new ShadowRealm().evaluate('(1, 2,)')", true, true, "2")]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new ShadowRealm().evaluate('(1, 2,)')", false, false, null)]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default '' + new ShadowRealm().evaluate('(1, 2,)')", true, false, null)]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default ('',) + new ShadowRealm().evaluate('(1, 2,)')", false, true, "2")]
+    [InlineData(SourceKind.ModuleViaBuilder, @"export default ('',) + new ShadowRealm().evaluate('(1, 2,)')", true, true, "2")]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new ShadowRealm().evaluate('(1, 2,)')", false, false, null)]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default '' + new ShadowRealm().evaluate('(1, 2,)')", true, false, null)]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default ('',) + new ShadowRealm().evaluate('(1, 2,)')", false, true, "2")]
+    [InlineData(SourceKind.ModuleViaFactory, @"export default ('',) + new ShadowRealm().evaluate('(1, 2,)')", true, true, "2")]
     public void DynamicCodeShouldBeParsedWithCallerParserOptions(SourceKind sourceKind, string code, bool prepare, bool tolerant, string? expectedReturnValue)
     {
         Engine engine;
@@ -160,14 +159,14 @@ public class ParserOptionsPropagationTests
 
     [Theory]
     [InlineData(false, false, null)]
-    [InlineData(false, true, "true")]
+    [InlineData(false, true, "2")]
     [InlineData(true, false, null)]
-    [InlineData(true, true, "true")]
+    [InlineData(true, true, "2")]
     public void TransitivelyImportedModuleShouldBeParsedWithOwnParserOptions(bool mainTolerant, bool otherTolerant, string? expectedReturnValue)
     {
         var engine = new Engine();
-        engine.Modules.Add("main", o => o.AddSource("import { x } from 'other'; export default x").WithOptions(_ => ModuleParsingOptions.Default with { Tolerant = mainTolerant }));
-        engine.Modules.Add("other", o => o.AddSource("export const x = '' + new Function('return !!({g\\\\u0065t y() {} })')()").WithOptions(_ => ModuleParsingOptions.Default with { Tolerant = otherTolerant }));
+        engine.Modules.Add("main", o => o.AddSource("import { x } from 'other'; export default x").WithOptions(o => o with { Tolerant = mainTolerant }));
+        engine.Modules.Add("other", o => o.AddSource("export const x = '' + eval('(1, 2,)')").WithOptions(o => o with { Tolerant = otherTolerant }));
 
         var evalAction = () =>
         {
@@ -192,24 +191,24 @@ public class ParserOptionsPropagationTests
         var engine = new Engine();
 
         var parsingOptions = ScriptParsingOptions.Default with { AllowReturnOutsideFunction = true, Tolerant = true };
-        Assert.Equal("true", engine.Evaluate("return '' + new Function('return !!({g\\\\u0065t y() {} })')()", parsingOptions));
+        Assert.Equal("2", engine.Evaluate("return '' + eval('(1, 2,)')", parsingOptions));
 
         var shadowRealm1 = engine.Intrinsics.ShadowRealm.Construct();
         var shadowRealm2 = engine.Intrinsics.ShadowRealm.Construct();
 
-        var ex = Assert.Throws<JavaScriptException>(() => shadowRealm1.Evaluate("'' + new Function('return !!({g\\\\u0065t y() {} })')()", parsingOptions with { Tolerant = false }));
+        var ex = Assert.Throws<JavaScriptException>(() => shadowRealm1.Evaluate("'' + eval('(1, 2,)')", parsingOptions with { Tolerant = false }));
         Assert.True(ex.Error.InstanceofOperator(engine.Intrinsics.TypeError));
 
-        Assert.Equal("true", engine.Evaluate("'' + new Function('return !!({g\\\\u0065t y() {} })')()", parsingOptions));
+        Assert.Equal("2", engine.Evaluate("'' + eval('(1, 2,)')", parsingOptions));
 
-        ex = Assert.Throws<JavaScriptException>(() => shadowRealm2.Evaluate("'' + new Function('return !!({g\\\\u0065t y() {} })')()", parsingOptions with { Tolerant = false }));
+        ex = Assert.Throws<JavaScriptException>(() => shadowRealm2.Evaluate("'' + eval('(1, 2,)')", parsingOptions with { Tolerant = false }));
         Assert.True(ex.Error.InstanceofOperator(engine.Intrinsics.TypeError));
 
-        Assert.Equal("true", shadowRealm1.Evaluate("'' + new Function('return !!({g\\\\u0065t y() {} })')()", parsingOptions));
+        Assert.Equal("2", shadowRealm1.Evaluate("'' + eval('(1, 2,)')", parsingOptions));
 
-        ex = Assert.Throws<JavaScriptException>(() => engine.Evaluate("'' + new Function('return !!({g\\\\u0065t y() {} })')()", parsingOptions with { Tolerant = false }));
+        ex = Assert.Throws<JavaScriptException>(() => engine.Evaluate("'' + eval('(1, 2,)')", parsingOptions with { Tolerant = false }));
         Assert.True(ex.Error.InstanceofOperator(engine.Intrinsics.SyntaxError));
 
-        Assert.Equal("true", shadowRealm2.Evaluate("'' + new Function('return !!({g\\\\u0065t y() {} })')()", parsingOptions));
+        Assert.Equal("2", shadowRealm2.Evaluate("'' + new Function('return (1, 2,)')()", parsingOptions));
     }
 }

+ 45 - 29
Jint/AstExtensions.cs

@@ -13,6 +13,8 @@ namespace Jint
 {
     public static class AstExtensions
     {
+        internal static readonly SourceLocation DefaultLocation;
+
         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)
@@ -37,7 +39,7 @@ namespace Jint
             JsValue key;
             if (expression is Literal literal)
             {
-                key = literal.TokenType == TokenKind.NullLiteral ? JsValue.Null : LiteralKeyToString(literal);
+                key = literal.Kind == TokenKind.NullLiteral ? JsValue.Null : LiteralKeyToString(literal);
             }
             else if (!resolveComputed && expression is Identifier identifier)
             {
@@ -92,6 +94,12 @@ namespace Jint
                 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>
@@ -109,12 +117,12 @@ namespace Jint
                 return false;
             }
 
-            if ((node as IFunction)?.Id is not null)
+            if (node is IFunction { Id: not null })
             {
                 return true;
             }
 
-            if ((node as ClassExpression)?.Id is not null)
+            if (node is ClassExpression { Id: not null })
             {
                 return true;
             }
@@ -141,26 +149,30 @@ namespace Jint
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal static bool IsOptional<T>(this T node) where T : Expression
         {
-            switch (node)
-            {
-                case MemberExpression { Optional: true }:
-                case CallExpression { Optional: true }:
-                    return true;
-                default:
-                    return false;
+            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
-            if (literal.Value is double d)
+            else if (literal is NumericLiteral numericLiteral)
             {
-                return TypeConverter.ToString(d);
+                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 literal.Value as string ?? Convert.ToString(literal.Value, provider: null) ?? "";
         }
 
         internal static void GetBoundNames(this VariableDeclaration variableDeclaration, List<Key> target)
@@ -222,7 +234,7 @@ namespace Jint
                     for (var i = 0; i < objectPatternProperties.Count; i++)
                     {
                         var property = objectPatternProperties[i];
-                        if (property is Property p)
+                        if (property is AssignmentProperty p)
                         {
                             GetBoundNames(p.Value, target);
                         }
@@ -322,7 +334,7 @@ namespace Jint
 
         internal static void GetImportEntries(this ImportDeclaration import, List<ImportEntry> importEntries, HashSet<ModuleRequest> requestedModules)
         {
-            var source = import.Source.StringValue!;
+            var source = import.Source.Value;
             var specifiers = import.Specifiers;
             var attributes = GetAttributes(import.Attributes);
             requestedModules.Add(new ModuleRequest(source, attributes));
@@ -355,7 +367,8 @@ namespace Jint
             for (var i = 0; i < importAttributes.Count; i++)
             {
                 var attribute = importAttributes[i];
-                attributes[i] = new ModuleImportAttribute(attribute.Key.ToString(), attribute.Value.StringValue!);
+                var key = attribute.Key is Identifier identifier ? identifier.Name : ((StringLiteral) attribute.Key).Value;
+                attributes[i] = new ModuleImportAttribute(key, attribute.Value.Value);
             }
             return attributes;
         }
@@ -369,15 +382,15 @@ namespace Jint
                     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.StringValue!, []));
-                    exportEntries.Add(new(allDeclaration.Exported?.GetModuleKey(), new ModuleRequest(allDeclaration.Source.StringValue!, []), "*", null));
+                    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?.StringValue!, [])
+                            ? new ModuleRequest(namedDeclaration.Source.Value, [])
                             : null;
 
                         GetExportEntries(false, namedDeclaration.Declaration!, exportEntries, moduleRequest);
@@ -389,7 +402,7 @@ namespace Jint
                             var specifier = specifiers[i];
                             if (namedDeclaration.Source != null)
                             {
-                                exportEntries.Add(new(specifier.Exported.GetModuleKey(), new ModuleRequest(namedDeclaration.Source.StringValue!, []), specifier.Local.GetModuleKey(), null));
+                                exportEntries.Add(new(specifier.Exported.GetModuleKey(), new ModuleRequest(namedDeclaration.Source.Value, []), specifier.Local.GetModuleKey(), null));
                             }
                             else
                             {
@@ -400,14 +413,14 @@ namespace Jint
 
                     if (namedDeclaration.Source is not null)
                     {
-                        requestedModules.Add(new ModuleRequest(namedDeclaration.Source.StringValue!, []));
+                        requestedModules.Add(new ModuleRequest(namedDeclaration.Source.Value, []));
                     }
 
                     break;
             }
         }
 
-        private static void GetExportEntries(bool defaultExport, StatementListItem declaration, List<ExportEntry> exportEntries, ModuleRequest? moduleRequest = null)
+        private static void GetExportEntries(bool defaultExport, StatementOrExpression declaration, List<ExportEntry> exportEntries, ModuleRequest? moduleRequest = null)
         {
             var names = GetExportNames(declaration);
 
@@ -429,7 +442,7 @@ namespace Jint
             }
         }
 
-        private static List<Key> GetExportNames(StatementListItem declaration)
+        private static List<Key> GetExportNames(StatementOrExpression declaration)
         {
             var result = new List<Key>();
 
@@ -461,7 +474,7 @@ namespace Jint
 
         private static string GetModuleKey(this Expression expression)
         {
-            return (expression as Identifier)?.Name ?? (expression as Literal)!.StringValue!;
+            return (expression as Identifier)?.Name ?? ((StringLiteral) expression).Value;
         }
 
         internal readonly record struct Record(JsValue Key, ScriptFunction Closure);
@@ -469,7 +482,7 @@ namespace Jint
         /// <summary>
         /// Creates a dummy node that can be used when only location available and node is required.
         /// </summary>
-        internal static SyntaxElement CreateLocationNode(in SourceLocation location)
+        internal static Node CreateLocationNode(in SourceLocation location)
         {
             return new MinimalSyntaxElement(location);
         }
@@ -483,12 +496,15 @@ namespace Jint
             validator.Visit(script);
         }
 
-        private sealed class MinimalSyntaxElement : SyntaxElement
+        private sealed class MinimalSyntaxElement : Node
         {
-            public MinimalSyntaxElement(in SourceLocation location)
+            public MinimalSyntaxElement(in SourceLocation location) : base(NodeType.Unknown)
             {
                 Location = location;
             }
+
+            protected override IEnumerator<Node>? GetChildNodes() => throw new NotImplementedException();
+            protected override object? Accept(AstVisitor visitor) => throw new NotImplementedException();
         }
 
         private sealed class PrivateIdentifierValidator : AstVisitor

+ 16 - 42
Jint/Engine.Ast.cs

@@ -22,7 +22,7 @@ public partial class Engine
         options ??= ScriptPreparationOptions.Default;
         var astAnalyzer = new AstAnalyzer(options);
         var parserOptions = options.GetParserOptions();
-        var preparedScript = new Parser(parserOptions with { OnNodeCreated = astAnalyzer.NodeVisitor }).ParseScript(code, source, strict);
+        var preparedScript = new Parser(parserOptions with { OnNode = astAnalyzer.NodeVisitor }).ParseScript(code, source, strict);
         return new Prepared<Script>(preparedScript, parserOptions);
     }
 
@@ -37,7 +37,7 @@ public partial class Engine
         options ??= ModulePreparationOptions.Default;
         var astAnalyzer = new AstAnalyzer(options);
         var parserOptions = options.GetParserOptions();
-        var preparedModule = new Parser(parserOptions with { OnNodeCreated = astAnalyzer.NodeVisitor }).ParseModule(code, source);
+        var preparedModule = new Parser(parserOptions with { OnNode = astAnalyzer.NodeVisitor }).ParseModule(code, source);
         return new Prepared<Module>(preparedModule, parserOptions);
     }
 
@@ -67,66 +67,40 @@ public partial class Engine
                         _bindingNames[name] = bindingName = new Environment.BindingName(JsString.CachedCreate(name));
                     }
 
-                    node.AssociatedData = new JintIdentifierExpression(identifier, bindingName);
+                    node.UserData = new JintIdentifierExpression(identifier, bindingName);
                     break;
 
                 case NodeType.Literal:
                     var literal = (Literal) node;
 
                     var constantValue = JintLiteralExpression.ConvertToJsValue(literal);
-                    node.AssociatedData = constantValue is not null ? new JintConstantExpression(literal, constantValue) : null;
-
-                    if (node.AssociatedData is null && literal.TokenType == TokenKind.RegularExpression
-                        && !_canCompileNegativeLookaroundAssertions && _preparationOptions.ParsingOptions.CompileRegex != false)
-                    {
-                        var regExpLiteral = (RegExpLiteral) literal;
-                        var regExpParseResult = regExpLiteral.ParseResult;
-
-                        // only compile if there's no negative lookahead, it works incorrectly under NET 7 and NET 8
-                        // https://github.com/dotnet/runtime/issues/97455
-                        if (regExpParseResult.Success && regExpLiteral.Raw.Contains("(?!"))
-                        {
-                            if (!_regexes.TryGetValue(regExpLiteral.Raw, out var regex))
-                            {
-                                regex = regExpParseResult.Regex!;
-                                if ((regex.Options & RegexOptions.Compiled) != RegexOptions.None)
-                                {
-                                    regex = new Regex(regex.ToString(), regex.Options & ~RegexOptions.Compiled, regex.MatchTimeout);
-                                }
-
-                                _regexes[regExpLiteral.Raw] = regex;
-                            }
-
-                            regExpLiteral.AssociatedData = regex;
-                        }
-                    }
-
+                    node.UserData = constantValue is not null ? new JintConstantExpression(literal, constantValue) : null;
                     break;
 
                 case NodeType.MemberExpression:
-                    node.AssociatedData = JintMemberExpression.InitializeDeterminedProperty((MemberExpression) node, cache: true);
+                    node.UserData = JintMemberExpression.InitializeDeterminedProperty((MemberExpression) node, cache: true);
                     break;
 
                 case NodeType.ArrowFunctionExpression:
                 case NodeType.FunctionDeclaration:
                 case NodeType.FunctionExpression:
                     var function = (IFunction) node;
-                    node.AssociatedData = JintFunctionDefinition.BuildState(function);
+                    node.UserData = JintFunctionDefinition.BuildState(function);
                     break;
 
                 case NodeType.Program:
-                    node.AssociatedData = new CachedHoistingScope((Program) node);
+                    node.UserData = new CachedHoistingScope((Program) node);
                     break;
 
                 case NodeType.UnaryExpression:
-                    node.AssociatedData = JintUnaryExpression.BuildConstantExpression((UnaryExpression) node);
+                    node.UserData = JintUnaryExpression.BuildConstantExpression((NonUpdateUnaryExpression) node);
                     break;
 
                 case NodeType.BinaryExpression:
-                    var binaryExpression = (BinaryExpression) node;
+                    var binaryExpression = (NonLogicalBinaryExpression) node;
                     if (_preparationOptions.FoldConstants
-                        && binaryExpression.Operator != BinaryOperator.InstanceOf
-                        && binaryExpression.Operator != BinaryOperator.In
+                        && binaryExpression.Operator != Operator.InstanceOf
+                        && binaryExpression.Operator != Operator.In
                         && binaryExpression is { Left: Literal leftLiteral, Right: Literal rightLiteral })
                     {
                         var left = JintLiteralExpression.ConvertToJsValue(leftLiteral);
@@ -139,7 +113,7 @@ public partial class Engine
                             {
                                 var result = JintBinaryExpression.Build(binaryExpression);
                                 var context = new EvaluationContext();
-                                node.AssociatedData = new JintConstantExpression(binaryExpression, (JsValue) result.EvaluateWithoutNodeTracking(context));
+                                node.UserData = new JintConstantExpression(binaryExpression, (JsValue) result.EvaluateWithoutNodeTracking(context));
                             }
                             catch
                             {
@@ -157,7 +131,7 @@ public partial class Engine
                         var returnValue = JintLiteralExpression.ConvertToJsValue(returnedLiteral);
                         if (returnValue is not null)
                         {
-                            node.AssociatedData = new ConstantStatement(returnStatement, CompletionType.Return, returnValue);
+                            node.UserData = new ConstantStatement(returnStatement, CompletionType.Return, returnValue);
                         }
                     }
                     break;
@@ -223,13 +197,13 @@ internal static class AstPreparationExtensions
 {
     internal static HoistingScope GetHoistingScope(this Program program)
     {
-        return program.AssociatedData is CachedHoistingScope cached ? cached.Scope : HoistingScope.GetProgramLevelDeclarations(program);
+        return program.UserData is CachedHoistingScope cached ? cached.Scope : HoistingScope.GetProgramLevelDeclarations(program);
     }
 
     internal static List<Key> GetVarNames(this Program program, HoistingScope hoistingScope)
     {
         List<Key> boundNames;
-        if (program.AssociatedData is CachedHoistingScope cached)
+        if (program.UserData is CachedHoistingScope cached)
         {
             boundNames = cached.VarNames;
         }
@@ -245,7 +219,7 @@ internal static class AstPreparationExtensions
     internal static List<CachedHoistingScope.CachedLexicalName> GetLexNames(this Program program, HoistingScope hoistingScope)
     {
         List<CachedHoistingScope.CachedLexicalName> boundNames;
-        if (program.AssociatedData is CachedHoistingScope cached)
+        if (program.UserData is CachedHoistingScope cached)
         {
             boundNames = cached.LexNames;
         }

+ 3 - 8
Jint/Engine.Defaults.cs

@@ -6,13 +6,8 @@ public partial class Engine
 
     internal static readonly ParserOptions BaseParserOptions = ParserOptions.Default with
     {
-        Tolerant = true,
-
-        // This should be kept sync with https://github.com/sebastienros/esprima-dotnet/blob/v3.0.4/test/Esprima.Tests/JavaScriptParserTests.cs#L14-L18
-#if DEBUG
-        MaxAssignmentDepth = 200,
-#else
-        MaxAssignmentDepth = 500,
-#endif
+        EcmaVersion = EcmaVersion.ES2023,
+        ExperimentalESFeatures = ExperimentalESFeatures.ImportAttributes | ExperimentalESFeatures.RegExpDuplicateNamedCapturingGroups,
+        Tolerant = false,
     };
 }

+ 1 - 1
Jint/Engine.Modules.cs

@@ -64,7 +64,7 @@ public partial class Engine
         private BuilderModule LoadFromBuilder(string specifier, ModuleBuilder moduleBuilder, ResolvedSpecifier moduleResolution)
         {
             var parsedModule = moduleBuilder.Parse();
-            var module = new BuilderModule(_engine, _engine.Realm, parsedModule, location: parsedModule.Program!.Location.Source, async: false);
+            var module = new BuilderModule(_engine, _engine.Realm, parsedModule, location: parsedModule.Program!.Location.SourceFile, async: false);
             _modules[moduleResolution.Key] = module;
             moduleBuilder.BindExportedValues(module);
             _builders.Remove(specifier);

+ 21 - 25
Jint/Engine.cs

@@ -29,8 +29,8 @@ namespace Jint
     {
         private static readonly Options _defaultEngineOptions = new();
 
-        private readonly ParserOptions _defaultParserOptions;
         private readonly Parser _defaultParser;
+        private ParserOptions? _defaultModuleParserOptions; // cache default ParserOptions for ModuleBuilder instances
 
         private readonly ExecutionContextStack _executionContexts;
         private JsValue _completionValue = JsValue.Undefined;
@@ -144,8 +144,8 @@ namespace Jint
             CallStack = new JintCallStack(Options.Constraints.MaxRecursionDepth >= 0);
             _stackGuard = new StackGuard(this);
 
-            _defaultParserOptions = ScriptParsingOptions.Default.GetParserOptions(Options);
-            _defaultParser = new Parser(_defaultParserOptions);
+            var defaultParserOptions = ScriptParsingOptions.Default.GetParserOptions(Options);
+            _defaultParser = new Parser(defaultParserOptions);
         }
 
         private void Reset()
@@ -164,7 +164,7 @@ namespace Jint
         // having a proper execution context established
         internal Realm? _realmInConstruction;
 
-        internal SyntaxElement? _lastSyntaxElement;
+        internal Node? _lastSyntaxElement;
 
         internal Realm Realm => _realmInConstruction ?? ExecutionContext.Realm;
 
@@ -191,27 +191,23 @@ namespace Jint
 
         public DebugHandler Debugger => _debugger ??= new DebugHandler(this, Options.Debugger.InitialStepMode);
 
-        // TODO: needed
+        internal ParserOptions DefaultModuleParserOptions => _defaultModuleParserOptions ??= ModuleParsingOptions.Default.GetParserOptions(Options);
+
         internal ParserOptions GetActiveParserOptions()
         {
-            return _executionContexts?.GetActiveParserOptions() ?? _defaultParserOptions;
+            return _executionContexts?.GetActiveParserOptions() ?? _defaultParser.Options;
         }
 
-        internal Parser GetParserFor(ScriptParsingOptions parsingOptions, out ParserOptions parserOptions)
+        internal Parser GetParserFor(ScriptParsingOptions parsingOptions)
         {
-            if (ReferenceEquals(parsingOptions, ScriptParsingOptions.Default))
-            {
-                parserOptions = _defaultParserOptions;
-                return _defaultParser;
-            }
-
-            parserOptions = parsingOptions.GetParserOptions(Options);
-            return new Parser(parserOptions);
+            return ReferenceEquals(parsingOptions, ScriptParsingOptions.Default)
+                ? _defaultParser
+                : new Parser(parsingOptions.GetParserOptions(Options));
         }
 
         internal Parser GetParserFor(ParserOptions parserOptions)
         {
-            return ReferenceEquals(parserOptions, _defaultParserOptions) ? _defaultParser : new Parser(parserOptions);
+            return ReferenceEquals(parserOptions, _defaultParser.Options) ? _defaultParser : new Parser(parserOptions);
         }
 
         internal void EnterExecutionContext(
@@ -345,7 +341,7 @@ namespace Jint
         public JsValue Evaluate(string code, string? source = null)
         {
             var script = _defaultParser.ParseScript(code, source ?? "<anonymous>", _isStrict);
-            return Evaluate(new Prepared<Script>(script, _defaultParserOptions));
+            return Evaluate(new Prepared<Script>(script, _defaultParser.Options));
         }
 
         /// <summary>
@@ -359,9 +355,9 @@ namespace Jint
         /// </summary>
         public JsValue Evaluate(string code, string source, ScriptParsingOptions parsingOptions)
         {
-            var parser = GetParserFor(parsingOptions, out var parserOptions);
+            var parser = GetParserFor(parsingOptions);
             var script = parser.ParseScript(code, source, _isStrict);
-            return Evaluate(new Prepared<Script>(script, parserOptions));
+            return Evaluate(new Prepared<Script>(script, parser.Options));
         }
 
         /// <summary>
@@ -376,7 +372,7 @@ namespace Jint
         public Engine Execute(string code, string? source = null)
         {
             var script = _defaultParser.ParseScript(code, source ?? "<anonymous>", _isStrict);
-            return Execute(new Prepared<Script>(script, _defaultParserOptions));
+            return Execute(new Prepared<Script>(script, _defaultParser.Options));
         }
 
         /// <summary>
@@ -390,9 +386,9 @@ namespace Jint
         /// </summary>
         public Engine Execute(string code, string source, ScriptParsingOptions parsingOptions)
         {
-            var parser = GetParserFor(parsingOptions, out var parserOptions);
+            var parser = GetParserFor(parsingOptions);
             var script = parser.ParseScript(code, source, _isStrict);
-            return Execute(new Prepared<Script>(script, parserOptions));
+            return Execute(new Prepared<Script>(script, parser.Options));
         }
 
         /// <summary>
@@ -408,7 +404,7 @@ namespace Jint
             var script = preparedScript.Program;
             var parserOptions = preparedScript.ParserOptions;
             var strict = _isStrict || script.Strict;
-            ExecuteWithConstraints(strict, () => ScriptEvaluation(new ScriptRecord(Realm, script, script.Location.Source), parserOptions));
+            ExecuteWithConstraints(strict, () => ScriptEvaluation(new ScriptRecord(Realm, script, script.Location.SourceFile), parserOptions));
 
             return this;
         }
@@ -536,7 +532,7 @@ namespace Jint
             }
         }
 
-        internal void RunBeforeExecuteStatementChecks(StatementListItem? statement)
+        internal void RunBeforeExecuteStatementChecks(StatementOrExpression? statement)
         {
             // Avoid allocating the enumerator because we run this loop very often.
             foreach (var constraint in _constraints)
@@ -878,7 +874,7 @@ namespace Jint
         /// <summary>
         /// Gets the last evaluated <see cref="Node"/>.
         /// </summary>
-        internal SyntaxElement GetLastSyntaxElement()
+        internal Node GetLastSyntaxElement()
         {
             return _lastSyntaxElement!;
         }

+ 49 - 0
Jint/Extensions/Character.cs

@@ -0,0 +1,49 @@
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace Jint.Extensions
+{
+    internal static class Character
+    {
+        [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;
+        }
+
+        [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 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;
+
+            return (long) (shift & mask) < 0 ? true : false;
+        }
+    }
+}

+ 1 - 1
Jint/Jint.csproj

@@ -35,7 +35,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Esprima" />
+    <PackageReference Include="Acornima" />
     <PackageReference Include="Meziantou.Analyzer" PrivateAssets="all" />
   </ItemGroup>
 

+ 0 - 9
Jint/Messages.cs

@@ -1,9 +0,0 @@
-namespace Jint;
-
-/// <summary>
-/// Helper to map Esprima error messages.
-/// </summary>
-internal static class Messages
-{
-    public const string InvalidLHSInAssignment = "Invalid left-hand side in assignment";
-}

+ 12 - 13
Jint/Native/Function/ClassDefinition.cs

@@ -21,7 +21,7 @@ internal sealed class ClassDefinition
 
     static ClassDefinition()
     {
-        var parser = new Parser();
+        var parser = new Parser(Engine.BaseParserOptions);
 
         // generate missing constructor AST only once
         static MethodDefinition CreateConstructorMethodDefinition(Parser parser, string source)
@@ -32,7 +32,7 @@ internal sealed class ClassDefinition
         }
 
         _superConstructor = CreateConstructorMethodDefinition(parser, "class temp extends X { constructor(...args) { super(...args); } }");
-        _defaultSuperCall = (CallExpression) ((ExpressionStatement) _superConstructor.Value.Body.Body[0]).Expression;
+        _defaultSuperCall = (CallExpression) ((NonSpecialExpressionStatement) _superConstructor.Value.Body.Body[0]).Expression;
         _emptyConstructor = CreateConstructorMethodDefinition(parser, "class temp { constructor() {} }");
     }
 
@@ -155,14 +155,14 @@ internal sealed class ClassDefinition
             var instanceFields = new List<ClassFieldDefinition>();
             var staticElements = new List<object>();
 
-            foreach (var e in elements)
+            foreach (IClassElement e in elements)
             {
                 if (e is MethodDefinition { Kind: PropertyKind.Constructor })
                 {
                     continue;
                 }
 
-                var isStatic = e is MethodDefinition { Static: true } or AccessorProperty { Static: true } or PropertyDefinition { Static: true } or StaticBlock;
+                var isStatic = e.Static;
 
                 var target = !isStatic ? proto : F;
                 var element = ClassElementEvaluation(engine, target, e);
@@ -239,13 +239,14 @@ internal sealed class ClassDefinition
     /// <summary>
     /// https://tc39.es/ecma262/#sec-static-semantics-classelementevaluation
     /// </summary>
-    private static object? ClassElementEvaluation(Engine engine, ObjectInstance target, ClassElement e)
+    private static object? ClassElementEvaluation(Engine engine, ObjectInstance target, IClassElement e)
     {
         return e switch
         {
             PropertyDefinition p => ClassFieldDefinitionEvaluation(engine, target, p),
             MethodDefinition m => MethodDefinitionEvaluation(engine, target, m, enumerable: false),
             StaticBlock s => ClassStaticBlockDefinitionEvaluation(engine, target, s),
+            // AccessorProperty ap => throw new NotImplementedException(), // not implemented yet
             _ => null
         };
     }
@@ -277,12 +278,12 @@ internal sealed class ClassDefinition
     private sealed class ClassFieldFunction : Node, IFunction
     {
         private readonly NodeList<Node> _nodeList;
-        private readonly BlockStatement _statement;
+        private readonly FunctionBody _statement;
 
         public ClassFieldFunction(Expression expression) : base(NodeType.ExpressionStatement)
         {
             var nodeList = NodeList.Create<Statement>(new [] { new ReturnStatement(expression) });
-            _statement = new BlockStatement(nodeList);
+            _statement = new FunctionBody(nodeList, strict: true);
         }
 
         protected override object Accept(AstVisitor visitor) => throw new NotImplementedException();
@@ -291,10 +292,9 @@ internal sealed class ClassDefinition
 
         public ref readonly NodeList<Node> Params => ref _nodeList;
 
-        public StatementListItem Body => _statement;
+        public StatementOrExpression Body => _statement;
         public bool Generator => false;
         public bool Expression => false;
-        public bool Strict => true;
         public bool Async => false;
     }
 
@@ -319,12 +319,12 @@ internal sealed class ClassDefinition
 
     private sealed class ClassStaticBlockFunction : Node, IFunction
     {
-        private readonly BlockStatement _statement;
+        private readonly FunctionBody _statement;
         private readonly NodeList<Node> _params;
 
         public ClassStaticBlockFunction(StaticBlock staticBlock) : base(NodeType.StaticBlock)
         {
-            _statement = new BlockStatement(staticBlock.Body);
+            _statement = new FunctionBody(staticBlock.Body, strict: true);
             _params = new NodeList<Node>();
         }
 
@@ -332,10 +332,9 @@ internal sealed class ClassDefinition
 
         public Identifier? Id => null;
         public ref readonly NodeList<Node> Params => ref _params;
-        public StatementListItem Body => _statement;
+        public StatementOrExpression Body => _statement;
         public bool Generator => false;
         public bool Expression => false;
-        public bool Strict => false;
         public bool Async => false;
     }
 

+ 10 - 4
Jint/Native/Function/EvalFunction.cs

@@ -73,9 +73,15 @@ public sealed class EvalFunction : Function
 
         Script? script = null;
         var parserOptions = _engine.GetActiveParserOptions();
-        var adjustedParserOptions = !parserOptions.Tolerant || parserOptions.AllowReturnOutsideFunction
-            ? parserOptions with { Tolerant = true, AllowReturnOutsideFunction = false }
-            : parserOptions;
+        var adjustedParserOptions = parserOptions with
+        {
+            AllowReturnOutsideFunction = false,
+            AllowNewTargetOutsideFunction = true,
+            AllowSuperOutsideMethod = true,
+            // This is a workaround, just makes some tests pass. Actually, we need these checks (done either by the parser or by the runtime).
+            // TODO: implement a correct solution
+            CheckPrivateFields = false
+        };
         var parser = _engine.GetParserFor(adjustedParserOptions);
         try
         {
@@ -83,7 +89,7 @@ public sealed class EvalFunction : Function
         }
         catch (ParseErrorException e)
         {
-            if (string.Equals(e.Description, Messages.InvalidLHSInAssignment, StringComparison.Ordinal))
+            if (string.Equals(e.Error.Code, "InvalidLhsInAssignment", StringComparison.Ordinal))
             {
                 ExceptionHelper.ThrowReferenceError(callerRealm, (string?) null);
             }

+ 2 - 2
Jint/Native/Function/FunctionInstance.Dynamic.cs

@@ -148,7 +148,7 @@ public partial class Function
                 parserOptions = parserOptions with { AllowReturnOutsideFunction = true };
             }
             Parser parser = new(parserOptions);
-            function = (IFunction) parser.ParseScript(functionExpression, source: null, _engine._isStrict).Body[0];
+            function = (IFunction) parser.ParseScript(functionExpression, strict: _engine._isStrict).Body[0];
         }
         catch (ParseErrorException ex)
         {
@@ -161,7 +161,7 @@ public partial class Function
         PrivateEnvironment? privateEnv = null;
 
         var definition = new JintFunctionDefinition(function);
-        Function F = OrdinaryFunctionCreate(proto, definition, function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateEnv);
+        Function F = OrdinaryFunctionCreate(proto, definition, function.IsStrict() ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateEnv);
         F.SetFunctionName(_functionNameAnonymous, force: true);
 
         if (kind == FunctionKind.Generator)

+ 2 - 2
Jint/Native/Generator/GeneratorInstance.cs

@@ -78,7 +78,7 @@ internal sealed class GeneratorInstance : ObjectInstance
                 return new IteratorResult(_engine, abruptCompletion.Value, JsBoolean.True);
             }
 
-            ExceptionHelper.ThrowJavaScriptException(_engine, abruptCompletion.Value, (SourceLocation) default);
+            ExceptionHelper.ThrowJavaScriptException(_engine, abruptCompletion.Value, AstExtensions.DefaultLocation);
         }
 
         var genContext = _generatorContext;
@@ -95,7 +95,7 @@ internal sealed class GeneratorInstance : ObjectInstance
 
         if (_error is not null)
         {
-            ExceptionHelper.ThrowJavaScriptException(_engine, _error, (SourceLocation) default);
+            ExceptionHelper.ThrowJavaScriptException(_engine, _error, AstExtensions.DefaultLocation);
         }
 
         return ResumeExecution(genContext, new EvaluationContext(_engine));

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

@@ -3,6 +3,7 @@ using System.Globalization;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Text;
+using Jint.Extensions;
 using Jint.Native.Object;
 using Jint.Native.String;
 using Jint.Runtime;

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

@@ -104,7 +104,9 @@ namespace Jint.Native.RegExp
             var parserOptions = _engine.GetActiveParserOptions();
             try
             {
-                var regExpParseResult = Scanner.AdaptRegExp(p, f, compiled: false, parserOptions.RegexTimeout);
+                var regExpParseResult = Tokenizer.AdaptRegExp(p, f, compiled: false, parserOptions.RegexTimeout,
+                    ecmaVersion: parserOptions.EcmaVersion,
+                    experimentalESFeatures: parserOptions.ExperimentalESFeatures);
 
                 if (!regExpParseResult.Success)
                 {

+ 3 - 3
Jint/Native/ShadowRealm/ShadowRealm.cs

@@ -110,13 +110,13 @@ public sealed class ShadowRealm : ObjectInstance
         Script script;
         try
         {
-            script = parser.ParseScript(sourceText, source: null, _engine._isStrict);
+            script = parser.ParseScript(sourceText, strict: _engine._isStrict);
         }
         catch (ParseErrorException e)
         {
-            if (string.Equals(e.Description, Messages.InvalidLHSInAssignment, StringComparison.Ordinal))
+            if (string.Equals(e.Error.Code, "InvalidLhsInAssignment", StringComparison.Ordinal))
             {
-                ExceptionHelper.ThrowReferenceError(callerRealm, Messages.InvalidLHSInAssignment);
+                ExceptionHelper.ThrowReferenceError(callerRealm, e.Description);
             }
             else
             {

+ 1 - 7
Jint/ParsingOptions.cs

@@ -25,11 +25,8 @@ namespace Jint
 
         /// <summary>
         /// Gets or sets whether to parse the source code in tolerant mode.
-        /// Defaults to <see langword="true"/>.
+        /// Defaults to <see langword="false"/>.
         /// </summary>
-        /// <remarks>
-        /// Please note that there is a plan to change the default to <see langword="false"/> in the next major version.
-        /// </remarks>
         bool Tolerant { get; init; }
     }
 
@@ -47,9 +44,6 @@ namespace Jint
         /// Gets or sets whether to allow return statements at the top level.
         /// Defaults to <see langword="true"/>.
         /// </summary>
-        /// <remarks>
-        /// Please note that there is a plan to change the default to <see langword="false"/> in the next major version.
-        /// </remarks>
         public bool AllowReturnOutsideFunction { get; init; } = _defaultParserOptions.AllowReturnOutsideFunction;
 
         /// <inheritdoc/>

+ 6 - 5
Jint/Runtime/CallStack/CallStackElement.cs

@@ -19,17 +19,18 @@ namespace Jint.Runtime.CallStack
         public readonly JintExpression? Expression;
         public readonly CallStackExecutionContext CallingExecutionContext;
 
-        public SourceLocation Location
+        public ref readonly SourceLocation Location
         {
             get
             {
-                var expressionLocation = Expression?._expression.Location;
-                if (expressionLocation != null && expressionLocation.Value != default)
+                ref readonly var expressionLocation = ref (Expression is not null ? ref Expression._expression.LocationRef : ref AstExtensions.DefaultLocation);
+                if (expressionLocation != default)
                 {
-                    return expressionLocation.Value;
+                    return ref expressionLocation;
                 }
 
-                return ((Node?) Function._functionDefinition?.Function)?.Location ?? default;
+                var function = (Node?) Function._functionDefinition?.Function;
+                return ref (function is not null ? ref function.LocationRef : ref AstExtensions.DefaultLocation);
             }
         }
 

+ 2 - 2
Jint/Runtime/CallStack/JintCallStack.cs

@@ -149,7 +149,7 @@ namespace Jint.Runtime.CallStack
                 }
 
                 sb.Append(' ');
-                sb.Append(loc.Source);
+                sb.Append(loc.SourceFile);
                 sb.Append(':');
                 sb.Append(loc.End.Line.ToString(CultureInfo.InvariantCulture));
                 sb.Append(':');
@@ -202,7 +202,7 @@ namespace Jint.Runtime.CallStack
                 return identifier.Name ?? "";
             }
 
-            if (expression is StaticMemberExpression staticMemberExpression)
+            if (expression is MemberExpression { Computed: false } staticMemberExpression)
             {
                 return GetPropertyKey(staticMemberExpression.Object) + "." +
                        GetPropertyKey(staticMemberExpression.Property);

+ 3 - 3
Jint/Runtime/Completion.cs

@@ -23,9 +23,9 @@ public readonly struct Completion
     private static readonly Node _emptyNode = new Identifier("");
     private static readonly Completion _emptyCompletion = new(CompletionType.Normal, JsEmpty.Instance, _emptyNode);
 
-    internal readonly SyntaxElement _source;
+    internal readonly Node _source;
 
-    public Completion(CompletionType type, JsValue value, SyntaxElement source)
+    public Completion(CompletionType type, JsValue value, Node source)
     {
         Debug.Assert(value is not null);
 
@@ -36,7 +36,7 @@ public readonly struct Completion
 
     public readonly CompletionType Type;
     public readonly JsValue Value;
-    public ref readonly SourceLocation Location => ref _source.Location;
+    public readonly ref readonly SourceLocation Location => ref _source.LocationRef;
 
     public static ref readonly Completion Empty() => ref _emptyCompletion;
 

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

@@ -18,7 +18,7 @@ public sealed record BreakLocation
 
     }
 
-    public BreakLocation(string? source, Esprima.Position position) : this(source, position.Line, position.Column)
+    public BreakLocation(string? source, Position position) : this(source, position.Line, position.Column)
     {
     }
 

+ 3 - 2
Jint/Runtime/Debugger/CallFrame.cs

@@ -7,6 +7,7 @@ namespace Jint.Runtime.Debugger
     public sealed class CallFrame
     {
         private readonly CallStackExecutionContext _context;
+        private SourceLocation _location;
         private readonly CallStackElement? _element;
         private readonly Lazy<DebugScopes> _scopeChain;
 
@@ -18,7 +19,7 @@ namespace Jint.Runtime.Debugger
         {
             _element = element;
             _context = context;
-            Location = location;
+            _location = location;
             ReturnValue = returnValue;
 
             _scopeChain = new Lazy<DebugScopes>(() => new DebugScopes(Environment));
@@ -41,7 +42,7 @@ namespace Jint.Runtime.Debugger
         /// <summary>
         /// Currently executing source location in this call frame.
         /// </summary>
-        public SourceLocation Location { get; }
+        public ref SourceLocation Location => ref _location;
 
         /// <summary>
         /// The scope chain of this call frame.

+ 2 - 2
Jint/Runtime/Debugger/DebugHandler.cs

@@ -173,7 +173,7 @@ namespace Jint.Runtime.Debugger
 
             var bodyLocation = functionBody.Location;
             var functionBodyEnd = bodyLocation.End;
-            var location = SourceLocation.From(functionBodyEnd, functionBodyEnd, bodyLocation.Source);
+            var location = SourceLocation.From(functionBodyEnd, functionBodyEnd, bodyLocation.SourceFile);
 
             CheckBreakPointAndPause(node: null, location, returnValue);
         }
@@ -188,7 +188,7 @@ namespace Jint.Runtime.Debugger
             // Even if we matched a breakpoint, if we're stepping, the reason we're pausing is the step.
             // Still, we need to include the breakpoint at this location, in case the debugger UI needs to update
             // e.g. a hit count.
-            var breakLocation = new BreakLocation(location.Source, location.Start);
+            var breakLocation = new BreakLocation(location.SourceFile, location.Start);
             var breakPoint = BreakPoints.FindMatch(this, breakLocation);
 
             PauseType pauseType;

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

@@ -55,7 +55,7 @@ namespace Jint.Runtime.Debugger
         /// The current source Location.
         /// For return points, this starts and ends at the end of the function body.
         /// </summary>
-        public SourceLocation Location => CurrentCallFrame.Location;
+        public ref readonly SourceLocation Location => ref CurrentCallFrame.Location;
 
         /// <summary>
         /// Not implemented. Will always return 0.

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

@@ -209,7 +209,7 @@ namespace Jint.Runtime.Environments
 
                 try
                 {
-                    if (property is Property p)
+                    if (property is AssignmentProperty p)
                     {
                         var propertyName = p.GetKey(_engine);
                         processedProperties?.Add(propertyName.ToString());
@@ -326,7 +326,7 @@ namespace Jint.Runtime.Environments
 
             if (argument.IsUndefined())
             {
-                var expression = right.As<Expression>();
+                var expression = (Expression) right;
                 var jintExpression = JintExpression.Build(expression);
 
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;

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

@@ -27,7 +27,7 @@ internal sealed class EvaluationContext
     public readonly Engine Engine;
     public bool DebugMode => Engine._isDebugMode;
 
-    public SyntaxElement LastSyntaxElement
+    public Node LastSyntaxElement
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         get => Engine.GetLastSyntaxElement();
@@ -41,7 +41,7 @@ internal sealed class EvaluationContext
     public string? Target;
     public CompletionType Completion;
 
-    public void RunBeforeExecuteStatementChecks(StatementListItem statement)
+    public void RunBeforeExecuteStatementChecks(StatementOrExpression statement)
     {
         if (_shouldRunBeforeExecuteStatementChecks)
         {

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

@@ -300,7 +300,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             var source = TypeConverter.ToObject(context.Engine.Realm, argument);
             for (var i = 0; i < pattern.Properties.Count; i++)
             {
-                if (pattern.Properties[i] is Property p)
+                if (pattern.Properties[i] is AssignmentProperty p)
                 {
                     JsValue sourceKey;
                     var identifier = p.Key as Identifier;

+ 29 - 30
Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs

@@ -4,7 +4,6 @@ using Jint.Native.Function;
 using Jint.Runtime.Environments;
 
 using Environment = Jint.Runtime.Environments.Environment;
-using Operator = Esprima.Ast.AssignmentOperator;
 
 namespace Jint.Runtime.Interpreter.Expressions
 {
@@ -27,7 +26,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         internal static JintExpression Build(AssignmentExpression expression)
         {
-            if (expression.Operator == Operator.Assign)
+            if (expression.Operator == Operator.Assignment)
             {
                 if (expression.Left is DestructuringPattern)
                 {
@@ -80,7 +79,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             {
                 switch (_operator)
                 {
-                    case Operator.PlusAssign:
+                    case Operator.AdditionAssignment:
                     {
                         var rval = _right.GetValue(context);
                         if (AreIntegerOperands(originalLeftValue, rval))
@@ -115,7 +114,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                         break;
                     }
 
-                    case Operator.MinusAssign:
+                    case Operator.SubtractionAssignment:
                     {
                         var rval = _right.GetValue(context);
                         if (AreIntegerOperands(originalLeftValue, rval))
@@ -134,7 +133,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                         break;
                     }
 
-                    case Operator.TimesAssign:
+                    case Operator.MultiplicationAssignment:
                     {
                         var rval = _right.GetValue(context);
                         if (AreIntegerOperands(originalLeftValue, rval))
@@ -157,14 +156,14 @@ namespace Jint.Runtime.Interpreter.Expressions
                         break;
                     }
 
-                    case Operator.DivideAssign:
+                    case Operator.DivisionAssignment:
                     {
                         var rval = _right.GetValue(context);
                         newLeftValue = Divide(context, originalLeftValue, rval);
                         break;
                     }
 
-                    case Operator.ModuloAssign:
+                    case Operator.RemainderAssignment:
                     {
                         var rval = _right.GetValue(context);
                         if (originalLeftValue.IsUndefined() || rval.IsUndefined())
@@ -179,49 +178,49 @@ namespace Jint.Runtime.Interpreter.Expressions
                         break;
                     }
 
-                    case Operator.BitwiseAndAssign:
+                    case Operator.BitwiseAndAssignment:
                     {
                         var rval = _right.GetValue(context);
                         newLeftValue = TypeConverter.ToInt32(originalLeftValue) & TypeConverter.ToInt32(rval);
                         break;
                     }
 
-                    case Operator.BitwiseOrAssign:
+                    case Operator.BitwiseOrAssignment:
                     {
                         var rval = _right.GetValue(context);
                         newLeftValue = TypeConverter.ToInt32(originalLeftValue) | TypeConverter.ToInt32(rval);
                         break;
                     }
 
-                    case Operator.BitwiseXorAssign:
+                    case Operator.BitwiseXorAssignment:
                     {
                         var rval = _right.GetValue(context);
                         newLeftValue = TypeConverter.ToInt32(originalLeftValue) ^ TypeConverter.ToInt32(rval);
                         break;
                     }
 
-                    case Operator.LeftShiftAssign:
+                    case Operator.LeftShiftAssignment:
                     {
                         var rval = _right.GetValue(context);
                         newLeftValue = TypeConverter.ToInt32(originalLeftValue) << (int) (TypeConverter.ToUint32(rval) & 0x1F);
                         break;
                     }
 
-                    case Operator.RightShiftAssign:
+                    case Operator.RightShiftAssignment:
                     {
                         var rval = _right.GetValue(context);
                         newLeftValue = TypeConverter.ToInt32(originalLeftValue) >> (int) (TypeConverter.ToUint32(rval) & 0x1F);
                         break;
                     }
 
-                    case Operator.UnsignedRightShiftAssign:
+                    case Operator.UnsignedRightShiftAssignment:
                     {
                         var rval = _right.GetValue(context);
                         newLeftValue = (uint) TypeConverter.ToInt32(originalLeftValue) >> (int) (TypeConverter.ToUint32(rval) & 0x1F);
                         break;
                     }
 
-                    case Operator.NullishAssign:
+                    case Operator.NullishCoalescingAssignment:
                     {
                         if (!originalLeftValue.IsNullOrUndefined())
                         {
@@ -233,7 +232,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                         break;
                     }
 
-                    case Operator.AndAssign:
+                    case Operator.LogicalAndAssignment:
                     {
                         if (!TypeConverter.ToBoolean(originalLeftValue))
                         {
@@ -245,7 +244,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                         break;
                     }
 
-                    case Operator.OrAssign:
+                    case Operator.LogicalOrAssignment:
                     {
                         if (TypeConverter.ToBoolean(originalLeftValue))
                         {
@@ -257,7 +256,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                         break;
                     }
 
-                    case Operator.ExponentiationAssign:
+                    case Operator.ExponentiationAssignment:
                     {
                         var rval = _right.GetValue(context);
                         if (!originalLeftValue.IsBigInt() && !rval.IsBigInt())
@@ -298,41 +297,41 @@ namespace Jint.Runtime.Interpreter.Expressions
             string? operatorClrName = null;
             switch (_operator)
             {
-                case Operator.PlusAssign:
+                case Operator.AdditionAssignment:
                     operatorClrName = "op_Addition";
                     break;
-                case Operator.MinusAssign:
+                case Operator.SubtractionAssignment:
                     operatorClrName = "op_Subtraction";
                     break;
-                case Operator.TimesAssign:
+                case Operator.MultiplicationAssignment:
                     operatorClrName = "op_Multiply";
                     break;
-                case Operator.DivideAssign:
+                case Operator.DivisionAssignment:
                     operatorClrName = "op_Division";
                     break;
-                case Operator.ModuloAssign:
+                case Operator.RemainderAssignment:
                     operatorClrName = "op_Modulus";
                     break;
-                case Operator.BitwiseAndAssign:
+                case Operator.BitwiseAndAssignment:
                     operatorClrName = "op_BitwiseAnd";
                     break;
-                case Operator.BitwiseOrAssign:
+                case Operator.BitwiseOrAssignment:
                     operatorClrName = "op_BitwiseOr";
                     break;
-                case Operator.BitwiseXorAssign:
+                case Operator.BitwiseXorAssignment:
                     operatorClrName = "op_ExclusiveOr";
                     break;
-                case Operator.LeftShiftAssign:
+                case Operator.LeftShiftAssignment:
                     operatorClrName = "op_LeftShift";
                     break;
-                case Operator.RightShiftAssign:
+                case Operator.RightShiftAssignment:
                     operatorClrName = "op_RightShift";
                     break;
-                case Operator.UnsignedRightShiftAssign:
+                case Operator.UnsignedRightShiftAssignment:
                     operatorClrName = "op_UnsignedRightShift";
                     break;
-                case Operator.ExponentiationAssign:
-                case Operator.Assign:
+                case Operator.ExponentiationAssignment:
+                case Operator.Assignment:
                 default:
                     break;
             }

+ 31 - 33
Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs

@@ -10,8 +10,6 @@ using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Runtime.Interop;
 
-using Operator = Esprima.Ast.BinaryOperator;
-
 namespace Jint.Runtime.Interpreter.Expressions
 {
     internal abstract class JintBinaryExpression : JintExpression
@@ -23,7 +21,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         private JintExpression _right = null!;
         private bool _initialized;
 
-        private JintBinaryExpression(BinaryExpression expression) : base(expression)
+        private JintBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
         {
             // TODO check https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
         }
@@ -36,7 +34,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 return;
             }
 
-            var expression = (BinaryExpression) _expression;
+            var expression = (NonLogicalBinaryExpression) _expression;
             _left = Build(expression.Left);
             _right = Build(expression.Right);
             _initialized = true;
@@ -90,45 +88,45 @@ namespace Jint.Runtime.Interpreter.Expressions
             return false;
         }
 
-        internal static JintExpression Build(BinaryExpression expression)
+        internal static JintExpression Build(NonLogicalBinaryExpression expression)
         {
             JintBinaryExpression? result = null;
             switch (expression.Operator)
             {
-                case Operator.StrictlyEqual:
+                case Operator.StrictEquality:
                     result = new StrictlyEqualBinaryExpression(expression);
                     break;
-                case Operator.StrictlyNotEqual:
+                case Operator.StrictInequality:
                     result = new StrictlyNotEqualBinaryExpression(expression);
                     break;
-                case Operator.Less:
+                case Operator.LessThan:
                     result = new LessBinaryExpression(expression);
                     break;
-                case Operator.Greater:
+                case Operator.GreaterThan:
                     result = new GreaterBinaryExpression(expression);
                     break;
-                case Operator.Plus:
+                case Operator.Addition:
                     result = new PlusBinaryExpression(expression);
                     break;
-                case Operator.Minus:
+                case Operator.Subtraction:
                     result = new MinusBinaryExpression(expression);
                     break;
-                case Operator.Times:
+                case Operator.Multiplication:
                     result = new TimesBinaryExpression(expression);
                     break;
-                case Operator.Divide:
+                case Operator.Division:
                     result = new DivideBinaryExpression(expression);
                     break;
-                case Operator.Equal:
+                case Operator.Equality:
                     result = new EqualBinaryExpression(expression);
                     break;
-                case Operator.NotEqual:
+                case Operator.Inequality:
                     result = new EqualBinaryExpression(expression, invert: true);
                     break;
-                case Operator.GreaterOrEqual:
+                case Operator.GreaterThanOrEqual:
                     result = new CompareBinaryExpression(expression, leftFirst: true);
                     break;
-                case Operator.LessOrEqual:
+                case Operator.LessThanOrEqual:
                     result = new CompareBinaryExpression(expression, leftFirst: false);
                     break;
                 case Operator.BitwiseAnd:
@@ -145,7 +143,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 case Operator.Exponentiation:
                     result = new ExponentiationBinaryExpression(expression);
                     break;
-                case Operator.Modulo:
+                case Operator.Remainder:
                     result = new ModuloBinaryExpression(expression);
                     break;
                 case Operator.In:
@@ -198,7 +196,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class StrictlyEqualBinaryExpression : JintBinaryExpression
         {
-            public StrictlyEqualBinaryExpression(BinaryExpression expression) : base(expression)
+            public StrictlyEqualBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -215,7 +213,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class StrictlyNotEqualBinaryExpression : JintBinaryExpression
         {
-            public StrictlyNotEqualBinaryExpression(BinaryExpression expression) : base(expression)
+            public StrictlyNotEqualBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -231,7 +229,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class LessBinaryExpression : JintBinaryExpression
         {
-            public LessBinaryExpression(BinaryExpression expression) : base(expression)
+            public LessBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -256,7 +254,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class GreaterBinaryExpression : JintBinaryExpression
         {
-            public GreaterBinaryExpression(BinaryExpression expression) : base(expression)
+            public GreaterBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -281,7 +279,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class PlusBinaryExpression : JintBinaryExpression
         {
-            public PlusBinaryExpression(BinaryExpression expression) : base(expression)
+            public PlusBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -326,7 +324,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class MinusBinaryExpression : JintBinaryExpression
         {
-            public MinusBinaryExpression(BinaryExpression expression) : base(expression)
+            public MinusBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -366,7 +364,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class TimesBinaryExpression : JintBinaryExpression
         {
-            public TimesBinaryExpression(BinaryExpression expression) : base(expression)
+            public TimesBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -409,7 +407,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class DivideBinaryExpression : JintBinaryExpression
         {
-            public DivideBinaryExpression(BinaryExpression expression) : base(expression)
+            public DivideBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -436,7 +434,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         {
             private readonly bool _invert;
 
-            public EqualBinaryExpression(BinaryExpression expression, bool invert = false) : base(expression)
+            public EqualBinaryExpression(NonLogicalBinaryExpression expression, bool invert = false) : base(expression)
             {
                 _invert = invert;
             }
@@ -467,7 +465,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         {
             private readonly bool _leftFirst;
 
-            public CompareBinaryExpression(BinaryExpression expression, bool leftFirst) : base(expression)
+            public CompareBinaryExpression(NonLogicalBinaryExpression expression, bool leftFirst) : base(expression)
             {
                 _leftFirst = leftFirst;
             }
@@ -495,7 +493,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class InstanceOfBinaryExpression : JintBinaryExpression
         {
-            public InstanceOfBinaryExpression(BinaryExpression expression) : base(expression)
+            public InstanceOfBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -511,7 +509,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class ExponentiationBinaryExpression : JintBinaryExpression
         {
-            public ExponentiationBinaryExpression(BinaryExpression expression) : base(expression)
+            public ExponentiationBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -638,7 +636,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class InBinaryExpression : JintBinaryExpression
         {
-            public InBinaryExpression(BinaryExpression expression) : base(expression)
+            public InBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -668,7 +666,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         private sealed class ModuloBinaryExpression : JintBinaryExpression
         {
-            public ModuloBinaryExpression(BinaryExpression expression) : base(expression)
+            public ModuloBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
             }
 
@@ -783,7 +781,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
             private readonly Operator _operator;
 
-            public BitwiseBinaryExpression(BinaryExpression expression) : base(expression)
+            public BitwiseBinaryExpression(NonLogicalBinaryExpression expression) : base(expression)
             {
                 _operator = expression.Operator;
             }

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

@@ -89,7 +89,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         protected internal static JintExpression Build(Expression expression)
         {
-            if (expression.AssociatedData is JintExpression preparedExpression)
+            if (expression.UserData is JintExpression preparedExpression)
             {
                 return preparedExpression;
             }
@@ -99,18 +99,18 @@ namespace Jint.Runtime.Interpreter.Expressions
                 NodeType.AssignmentExpression => JintAssignmentExpression.Build((AssignmentExpression) expression),
                 NodeType.ArrayExpression => JintArrayExpression.Build((ArrayExpression) expression),
                 NodeType.ArrowFunctionExpression => new JintArrowFunctionExpression((ArrowFunctionExpression) expression),
-                NodeType.BinaryExpression => JintBinaryExpression.Build((BinaryExpression) expression),
+                NodeType.BinaryExpression => JintBinaryExpression.Build((NonLogicalBinaryExpression) expression),
                 NodeType.CallExpression => new JintCallExpression((CallExpression) expression),
                 NodeType.ConditionalExpression => new JintConditionalExpression((ConditionalExpression) expression),
                 NodeType.FunctionExpression => new JintFunctionExpression((FunctionExpression) expression),
                 NodeType.Identifier => new JintIdentifierExpression((Identifier) expression),
                 NodeType.PrivateIdentifier => new JintPrivateIdentifierExpression((PrivateIdentifier) expression),
                 NodeType.Literal => JintLiteralExpression.Build((Literal) expression),
-                NodeType.LogicalExpression => ((BinaryExpression) expression).Operator switch
+                NodeType.LogicalExpression => ((LogicalExpression) expression).Operator switch
                 {
-                    BinaryOperator.LogicalAnd => new JintLogicalAndExpression((BinaryExpression) expression),
-                    BinaryOperator.LogicalOr => new JintLogicalOrExpression((BinaryExpression) expression),
-                    BinaryOperator.NullishCoalescing => new NullishCoalescingExpression((BinaryExpression) expression),
+                    Operator.LogicalAnd => new JintLogicalAndExpression((LogicalExpression) expression),
+                    Operator.LogicalOr => new JintLogicalOrExpression((LogicalExpression) expression),
+                    Operator.NullishCoalescing => new NullishCoalescingExpression((LogicalExpression) expression),
                     _ => null
                 },
                 NodeType.MemberExpression => new JintMemberExpression((MemberExpression) expression),
@@ -119,7 +119,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 NodeType.SequenceExpression => new JintSequenceExpression((SequenceExpression) expression),
                 NodeType.ThisExpression => new JintThisExpression((ThisExpression) expression),
                 NodeType.UpdateExpression => new JintUpdateExpression((UpdateExpression) expression),
-                NodeType.UnaryExpression => JintUnaryExpression.Build((UnaryExpression) expression),
+                NodeType.UnaryExpression => JintUnaryExpression.Build((NonUpdateUnaryExpression) expression),
                 NodeType.SpreadElement => new JintSpreadExpression((SpreadElement) expression),
                 NodeType.TemplateLiteral => new JintTemplateLiteralExpression((TemplateLiteral) expression),
                 NodeType.TaggedTemplateExpression => new JintTaggedTemplateExpression((TaggedTemplateExpression) expression),

+ 10 - 12
Jint/Runtime/Interpreter/Expressions/JintLiteralExpression.cs

@@ -14,7 +14,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         internal static JintExpression Build(Literal expression)
         {
-            var value = expression.AssociatedData ??= ConvertToJsValue(expression) ?? _nullMarker;
+            var value = expression.UserData ??= ConvertToJsValue(expression) ?? _nullMarker;
 
             if (value is JsValue constant)
             {
@@ -26,16 +26,15 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         internal static JsValue? ConvertToJsValue(Literal literal)
         {
-            switch (literal.TokenType)
+            switch (literal.Kind)
             {
                 case TokenKind.BooleanLiteral:
-                    return literal.BooleanValue!.Value ? JsBoolean.True : JsBoolean.False;
+                    return ((BooleanLiteral) literal).Value ? JsBoolean.True : JsBoolean.False;
                 case TokenKind.NullLiteral:
                     return JsValue.Null;
                 case TokenKind.NumericLiteral:
                     {
-                        // unbox only once
-                        var numericValue = (double) literal.Value!;
+                        var numericValue = ((NumericLiteral) literal).Value;
                         var intValue = (int) numericValue;
                         return numericValue == intValue
                                && (intValue != 0 || BitConverter.DoubleToInt64Bits(numericValue) != JsNumber.NegativeZeroBits)
@@ -43,10 +42,10 @@ namespace Jint.Runtime.Interpreter.Expressions
                             : JsNumber.Create(numericValue);
                     }
                 case TokenKind.StringLiteral:
-                    return JsString.Create((string) literal.Value!);
+                    return JsString.Create(((StringLiteral) literal).Value);
                 case TokenKind.BigIntLiteral:
-                    return JsBigInt.Create((BigInteger) literal.Value!);
-                case TokenKind.RegularExpression:
+                    return JsBigInt.Create(((BigIntLiteral) literal).Value);
+                case TokenKind.RegExpLiteral:
                     break;
             }
 
@@ -65,14 +64,13 @@ namespace Jint.Runtime.Interpreter.Expressions
         private JsValue ResolveValue(EvaluationContext context)
         {
             var expression = (Literal) _expression;
-            if (expression.TokenType == TokenKind.RegularExpression)
+            if (expression is RegExpLiteral regExpLiteral)
             {
-                var regExpLiteral = (RegExpLiteral) expression;
                 var regExpParseResult = regExpLiteral.ParseResult;
                 if (regExpParseResult.Success)
                 {
-                    var regex = regExpLiteral.AssociatedData as Regex ?? regExpParseResult.Regex!;
-                    return context.Engine.Realm.Intrinsics.RegExp.Construct(regex, regExpLiteral.Regex.Pattern, regExpLiteral.Regex.Flags, regExpParseResult);
+                    var regex = regExpLiteral.UserData as Regex ?? regExpParseResult.Regex!;
+                    return context.Engine.Realm.Intrinsics.RegExp.Construct(regex, regExpLiteral.RegExp.Pattern, regExpLiteral.RegExp.Flags, regExpParseResult);
                 }
 
                 ExceptionHelper.ThrowSyntaxError(context.Engine.Realm, $"Unsupported regular expression. {regExpParseResult.ConversionError!.Description}");

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

@@ -8,13 +8,13 @@ namespace Jint.Runtime.Interpreter.Expressions
         private JintExpression _right = null!;
         private bool _initialized;
 
-        public JintLogicalAndExpression(BinaryExpression expression) : base(expression)
+        public JintLogicalAndExpression(LogicalExpression expression) : base(expression)
         {
         }
 
         private void Initialize()
         {
-            var expression = (BinaryExpression) _expression;
+            var expression = (LogicalExpression) _expression;
             _left = Build(expression.Left);
             _right = Build(expression.Right);
         }

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

@@ -7,7 +7,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         private readonly JintExpression _left;
         private readonly JintExpression _right;
 
-        public JintLogicalOrExpression(BinaryExpression expression) : base(expression)
+        public JintLogicalOrExpression(LogicalExpression expression) : base(expression)
         {
             _left = Build(expression.Left);
             _right = Build(expression.Right);

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

@@ -45,7 +45,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             {
                 _objectExpression = Build(_memberExpression.Object);
 
-                _determinedProperty ??= _expression.AssociatedData as JsValue ?? InitializeDeterminedProperty(_memberExpression, cache: false);
+                _determinedProperty ??= _expression.UserData as JsValue ?? InitializeDeterminedProperty(_memberExpression, cache: false);
 
                 if (ReferenceEquals(_determinedProperty, _nullMarker))
                 {

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

@@ -76,7 +76,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             {
                 string? propName = null;
                 var property = properties[i];
-                if (property is Property p)
+                if (property is Acornima.Ast.ObjectProperty p)
                 {
                     if (p.Key is Literal literal)
                     {

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

@@ -84,7 +84,7 @@ internal sealed class JintTaggedTemplateExpression : JintExpression
         for (uint i = 0; i < elements.Count; ++i)
         {
             var templateElementValue = elements[(int) i].Value;
-            template.SetIndexValue(i, templateElementValue.Cooked, updateLength: false);
+            template.SetIndexValue(i, templateElementValue.Cooked ?? JsValue.Undefined, updateLength: false);
             rawObj.SetIndexValue(i, templateElementValue.Raw, updateLength: false);
         }
 

+ 7 - 8
Jint/Runtime/Interpreter/Expressions/JintUnaryExpression.cs

@@ -7,7 +7,6 @@ using System.Numerics;
 using System.Reflection;
 
 using Environment = Jint.Runtime.Environments.Environment;
-using Operator = Esprima.Ast.UnaryOperator;
 
 namespace Jint.Runtime.Interpreter.Expressions
 {
@@ -19,13 +18,13 @@ namespace Jint.Runtime.Interpreter.Expressions
         private readonly JintExpression _argument;
         private readonly Operator _operator;
 
-        private JintUnaryExpression(UnaryExpression expression) : base(expression)
+        private JintUnaryExpression(NonUpdateUnaryExpression expression) : base(expression)
         {
             _argument = Build(expression.Argument);
             _operator = expression.Operator;
         }
 
-        internal static JintExpression Build(UnaryExpression expression)
+        internal static JintExpression Build(NonUpdateUnaryExpression expression)
         {
             if (expression.Operator == Operator.TypeOf)
             {
@@ -35,9 +34,9 @@ namespace Jint.Runtime.Interpreter.Expressions
             return BuildConstantExpression(expression) ?? new JintUnaryExpression(expression);
         }
 
-        internal static JintExpression? BuildConstantExpression(UnaryExpression expression)
+        internal static JintExpression? BuildConstantExpression(NonUpdateUnaryExpression expression)
         {
-            if (expression is { Operator: Operator.Minus, Argument: Literal literal })
+            if (expression is { Operator: Operator.UnaryNegation, Argument: Literal literal })
             {
                 var value = JintLiteralExpression.ConvertToJsValue(literal);
                 if (value is not null)
@@ -55,7 +54,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         {
             private readonly JintExpression _argument;
 
-            public JintTypeOfExpression(UnaryExpression expression) : base(expression)
+            public JintTypeOfExpression(NonUpdateUnaryExpression expression) : base(expression)
             {
                 _argument = Build(expression.Argument);
             }
@@ -138,7 +137,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             var engine = context.Engine;
             switch (_operator)
             {
-                case Operator.Plus:
+                case Operator.UnaryPlus:
                 {
                     var v = _argument.GetValue(context);
                     if (context.OperatorOverloadingAllowed &&
@@ -149,7 +148,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
                     return TypeConverter.ToNumber(v);
                 }
-                case Operator.Minus:
+                case Operator.UnaryNegation:
                 {
                     var v = _argument.GetValue(context);
                     if (context.OperatorOverloadingAllowed &&

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

@@ -22,11 +22,11 @@ namespace Jint.Runtime.Interpreter.Expressions
             var expression = (UpdateExpression) _expression;
             _prefix = expression.Prefix;
             _argument = Build(expression.Argument);
-            if (expression.Operator == UnaryOperator.Increment)
+            if (expression.Operator == Operator.Increment)
             {
                 _change = 1;
             }
-            else if (expression.Operator == UnaryOperator.Decrement)
+            else if (expression.Operator == Operator.Decrement)
             {
                 _change = -1;
             }

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

@@ -9,7 +9,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         private readonly JintExpression? _right;
         private readonly JsValue? _constant;
 
-        public NullishCoalescingExpression(BinaryExpression expression) : base(expression)
+        public NullishCoalescingExpression(LogicalExpression expression) : base(expression)
         {
             _left = Build(expression.Left);
 

+ 7 - 6
Jint/Runtime/Interpreter/JintFunctionDefinition.cs

@@ -25,9 +25,9 @@ internal sealed class JintFunctionDefinition
         Name = !string.IsNullOrEmpty(function.Id?.Name) ? function.Id!.Name : null;
     }
 
-    public bool Strict => Function.Strict;
+    public bool Strict => Function.IsStrict();
 
-    public FunctionThisMode ThisMode => Function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global;
+    public FunctionThisMode ThisMode => Function.IsStrict() ? FunctionThisMode.Strict : FunctionThisMode.Global;
 
     /// <summary>
     /// https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
@@ -171,7 +171,7 @@ internal sealed class JintFunctionDefinition
     internal State Initialize()
     {
         var node = (Node) Function;
-        var state = (State) (node.AssociatedData ??= BuildState(Function));
+        var state = (State) (node.UserData ??= BuildState(Function));
         return state;
     }
 
@@ -210,7 +210,8 @@ internal sealed class JintFunctionDefinition
 
         ProcessParameters(function, state, out var hasArguments);
 
-        var hoistingScope = HoistingScope.GetFunctionLevelDeclarations(function.Strict, function);
+        var strict = function.IsStrict();
+        var hoistingScope = HoistingScope.GetFunctionLevelDeclarations(strict, function);
         var functionDeclarations = hoistingScope._functionDeclarations;
         var lexicalNames = hoistingScope._lexicalNames;
         state.VarNames = hoistingScope._varNames;
@@ -236,7 +237,7 @@ internal sealed class JintFunctionDefinition
         const string ParameterNameArguments = "arguments";
 
         state.ArgumentsObjectNeeded = true;
-        var thisMode = function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global;
+        var thisMode = strict ? FunctionThisMode.Strict : FunctionThisMode.Global;
         if (function.Type == NodeType.ArrowFunctionExpression)
         {
             thisMode = FunctionThisMode.Lexical;
@@ -393,7 +394,7 @@ internal sealed class JintFunctionDefinition
                 for (var i = 0; i < objectPatternProperties.Count; i++)
                 {
                     var property = objectPatternProperties[i];
-                    if (property is Property p)
+                    if (property is AssignmentProperty p)
                     {
                         GetBoundNames(
                             p.Value,

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

@@ -19,7 +19,7 @@ namespace Jint.Runtime.Interpreter
         private readonly bool _generator;
 
         public JintStatementList(IFunction function)
-            : this((BlockStatement) function.Body)
+            : this((FunctionBody) function.Body)
         {
             _generator = function.Generator;
         }
@@ -155,13 +155,13 @@ namespace Jint.Runtime.Interpreter
             return CreateThrowCompletion(error.ErrorConstructor, error.Message, engine._lastSyntaxElement ?? s!._statement);
         }
 
-        private static Completion CreateThrowCompletion(ErrorConstructor errorConstructor, string? message, SyntaxElement s)
+        private static Completion CreateThrowCompletion(ErrorConstructor errorConstructor, string? message, Node s)
         {
             var error = errorConstructor.Construct(message);
             return new Completion(CompletionType.Throw, error, s);
         }
 
-        private static Completion CreateThrowCompletion(ErrorConstructor errorConstructor, Exception e, SyntaxElement s)
+        private static Completion CreateThrowCompletion(ErrorConstructor errorConstructor, Exception e, Node s)
         {
             var error = errorConstructor.Construct(e.Message);
             return new Completion(CompletionType.Throw, error, s);
@@ -169,7 +169,7 @@ namespace Jint.Runtime.Interpreter
 
         private static Completion CreateThrowCompletion(JintStatement? s, JavaScriptException v)
         {
-            SyntaxElement source = s!._statement;
+            Node source = s!._statement;
             if (v.Location != default)
             {
                 source = AstExtensions.CreateLocationNode(v.Location);

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

@@ -3,13 +3,13 @@ using Environment = Jint.Runtime.Environments.Environment;
 
 namespace Jint.Runtime.Interpreter.Statements
 {
-    internal sealed class JintBlockStatement : JintStatement<BlockStatement>
+    internal sealed class JintBlockStatement : JintStatement<NestedBlockStatement>
     {
         private JintStatementList? _statementList;
         private JintStatement? _singleStatement;
         private List<Declaration>? _lexicalDeclarations;
 
-        public JintBlockStatement(BlockStatement blockStatement) : base(blockStatement)
+        public JintBlockStatement(NestedBlockStatement blockStatement) : base(blockStatement)
         {
         }
 

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

@@ -44,7 +44,7 @@ namespace Jint.Runtime.Interpreter.Statements
 
         protected abstract Completion ExecuteInternal(EvaluationContext context);
 
-        public ref readonly SourceLocation Location => ref _statement.Location;
+        public ref readonly SourceLocation Location => ref _statement.LocationRef;
 
         /// <summary>
         /// Opportunity to build one-time structures and caching based on lexical context.
@@ -56,14 +56,14 @@ namespace Jint.Runtime.Interpreter.Statements
 
         protected internal static JintStatement Build(Statement statement)
         {
-            if (statement.AssociatedData is JintStatement preparedStatement)
+            if (statement.UserData is JintStatement preparedStatement)
             {
                 return preparedStatement;
             }
 
             JintStatement? result = statement.Type switch
             {
-                NodeType.BlockStatement => new JintBlockStatement((BlockStatement) statement),
+                NodeType.BlockStatement => new JintBlockStatement((NestedBlockStatement) statement),
                 NodeType.ReturnStatement => new JintReturnStatement((ReturnStatement) statement),
                 NodeType.VariableDeclaration => new JintVariableDeclaration((VariableDeclaration) statement),
                 NodeType.BreakStatement => new JintBreakStatement((BreakStatement) statement),
@@ -99,7 +99,7 @@ namespace Jint.Runtime.Interpreter.Statements
             return result;
         }
 
-        internal static JsValue? FastResolve(StatementListItem statement)
+        internal static JsValue? FastResolve(StatementOrExpression statement)
         {
             if (statement is ReturnStatement rs && rs.Argument is Literal l)
             {

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

@@ -15,7 +15,7 @@ internal readonly struct ProbablyBlockStatement
 
     public ProbablyBlockStatement(Statement statement)
     {
-        if (statement is BlockStatement blockStatement)
+        if (statement is NestedBlockStatement blockStatement)
         {
             _blockStatement = new JintBlockStatement(blockStatement);
         }

+ 3 - 2
Jint/Runtime/Modules/CyclicModule.cs

@@ -32,6 +32,7 @@ public abstract class CyclicModule : Module
     private int _pendingAsyncDependencies;
 
     internal JsValue _evalResult;
+    private SourceLocation _abnormalCompletionLocation;
 
     internal CyclicModule(Engine engine, Realm realm, string location, bool async) : base(engine, realm, location)
     {
@@ -39,7 +40,7 @@ public abstract class CyclicModule : Module
 
     internal ModuleStatus Status { get; private set; }
 
-    internal SourceLocation AbnormalCompletionLocation { get; private set; }
+    internal ref readonly SourceLocation AbnormalCompletionLocation => ref _abnormalCompletionLocation;
 
     /// <summary>
     /// https://tc39.es/ecma262/#sec-moduledeclarationlinking
@@ -131,7 +132,7 @@ public abstract class CyclicModule : Module
                 m._evalError = result;
             }
 
-            AbnormalCompletionLocation = result.Location;
+            _abnormalCompletionLocation = result.Location;
             capability.Reject.Call(Undefined, new[] { result.Value });
         }
         else

+ 11 - 20
Jint/Runtime/Modules/ModuleBuilder.cs

@@ -12,7 +12,6 @@ public sealed class ModuleBuilder
     private readonly List<string> _sourceRaw = new();
     private readonly Dictionary<string, JsValue> _exports = new(StringComparer.Ordinal);
     private readonly ParserOptions _defaultParserOptions;
-    private readonly Parser _defaultParser;
     private ModuleParsingOptions _parsingOptions;
 
     internal ModuleBuilder(Engine engine, string specifier)
@@ -20,20 +19,7 @@ public sealed class ModuleBuilder
         _engine = engine;
         _specifier = specifier;
         _parsingOptions = ModuleParsingOptions.Default;
-        _defaultParserOptions = _parsingOptions.GetParserOptions(engine.Options);
-        _defaultParser = new Parser(_defaultParserOptions);
-    }
-
-    private Parser GetParserFor(ModuleParsingOptions parsingOptions, out ParserOptions parserOptions)
-    {
-        if (ReferenceEquals(parsingOptions, ModuleParsingOptions.Default))
-        {
-            parserOptions = _defaultParserOptions;
-            return _defaultParser;
-        }
-
-        parserOptions = parsingOptions.GetParserOptions(_engine.Options);
-        return new Parser(parserOptions);
+        _defaultParserOptions = _engine.DefaultModuleParserOptions;
     }
 
     public ModuleBuilder AddSource(string code)
@@ -48,6 +34,11 @@ public sealed class ModuleBuilder
 
     public ModuleBuilder AddModule(in Prepared<AstModule> preparedModule)
     {
+        if (!preparedModule.IsValid)
+        {
+            ExceptionHelper.ThrowInvalidPreparedModuleArgumentException(nameof(preparedModule));
+        }
+
         if (_sourceRaw.Count > 0)
         {
             throw new InvalidOperationException("Cannot have both source text and pre-compiled.");
@@ -139,16 +130,16 @@ public sealed class ModuleBuilder
     {
         if (_module != null) return _module.Value;
 
-        ParserOptions parserOptions;
+        var parserOptions = ReferenceEquals(_parsingOptions, ModuleParsingOptions.Default)
+            ? _defaultParserOptions
+            : _parsingOptions.GetParserOptions(_engine.Options);
+
         if (_sourceRaw.Count <= 0)
         {
-            parserOptions = ReferenceEquals(_parsingOptions, ModuleParsingOptions.Default)
-                ? _defaultParserOptions
-                : _parsingOptions.GetParserOptions(_engine.Options);
             return new Prepared<AstModule>(new AstModule(NodeList.Create(Array.Empty<Statement>())), parserOptions);
         }
 
-        var parser = GetParserFor(_parsingOptions, out parserOptions);
+        var parser = new Parser(parserOptions);
         try
         {
             var source = _sourceRaw.Count == 1 ? _sourceRaw[0] : string.Join(Environment.NewLine, _sourceRaw);

+ 5 - 5
Jint/Runtime/Modules/ModuleFactory.cs

@@ -36,7 +36,7 @@ public static class ModuleFactory
         }
         catch (Exception)
         {
-            ExceptionHelper.ThrowJavaScriptException(engine, $"Could not load module {source}", (SourceLocation) default);
+            ExceptionHelper.ThrowJavaScriptException(engine, $"Could not load module {source}", AstExtensions.DefaultLocation);
             module = null;
         }
 
@@ -49,16 +49,16 @@ public static class ModuleFactory
     /// </summary>
     /// <remarks>
     /// The returned modules location (see <see cref="Module.Location"/>) will be set
-    /// to <see cref="SourceLocation.Source"/> of the <paramref name="preparedModule"/>.
+    /// to <see cref="SourceLocation.SourceFile"/> of the <paramref name="preparedModule"/>.
     /// </remarks>
-    public static Module BuildSourceTextModule(Engine engine, Prepared<AstModule> preparedModule)
+    public static Module BuildSourceTextModule(Engine engine, in Prepared<AstModule> preparedModule)
     {
         if (!preparedModule.IsValid)
         {
             ExceptionHelper.ThrowInvalidPreparedModuleArgumentException(nameof(preparedModule));
         }
 
-        return new SourceTextModule(engine, engine.Realm, preparedModule, preparedModule.Program!.Location.Source, async: false);
+        return new SourceTextModule(engine, engine.Realm, preparedModule, preparedModule.Program!.Location.SourceFile, async: false);
     }
 
     /// <summary>
@@ -81,7 +81,7 @@ public static class ModuleFactory
         }
         catch (Exception)
         {
-            ExceptionHelper.ThrowJavaScriptException(engine, $"Could not load module {source}", (SourceLocation) default);
+            ExceptionHelper.ThrowJavaScriptException(engine, $"Could not load module {source}", AstExtensions.DefaultLocation);
             module = null;
         }
 

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

@@ -16,7 +16,7 @@ public abstract class ModuleLoader : IModuleLoader
         }
         catch (Exception)
         {
-            ExceptionHelper.ThrowJavaScriptException(engine, $"Could not load module {resolved.ModuleRequest.Specifier}", (SourceLocation) default);
+            ExceptionHelper.ThrowJavaScriptException(engine, $"Could not load module {resolved.ModuleRequest.Specifier}", AstExtensions.DefaultLocation);
             return default!;
         }
 

+ 3 - 1
Jint/Runtime/TypeConverter.cs

@@ -7,6 +7,7 @@ using Jint.Native.Object;
 using Jint.Native.String;
 using Jint.Native.Symbol;
 using Jint.Runtime.Interop;
+using Jint.Extensions;
 
 namespace Jint.Runtime
 {
@@ -587,7 +588,8 @@ namespace Jint.Runtime
         {
             if (!TryStringToBigInt(str, out var result))
             {
-                throw new ParseErrorException(" Cannot convert " + str + " to a BigInt");
+                // TODO: this doesn't seem a JS syntax error, use a dedicated exception type?
+                throw new SyntaxError("CannotConvertToBigInt", " Cannot convert " + str + " to a BigInt").ToException();
             }
 
             return result;