2
0
Эх сурвалжийг харах

Improve error location reporting (#1273)

Marko Lahma 2 жил өмнө
parent
commit
41309de576

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

@@ -10,9 +10,9 @@ public class EngineLimitTests
     public void ShouldAllowReasonableCallStackDepth()
     public void ShouldAllowReasonableCallStackDepth()
     {
     {
 #if RELEASE
 #if RELEASE
-        const int FunctionNestingCount = 650;
+        const int FunctionNestingCount = 690;
 #else
 #else
-        const int FunctionNestingCount = 340;
+        const int FunctionNestingCount = 350;
 #endif
 #endif
 
 
         // generate call tree
         // generate call tree

+ 18 - 0
Jint.Tests/Runtime/ErrorTests.cs

@@ -423,6 +423,24 @@ executeFile(""first-file.js"");",
             EqualIgnoringNewLineDifferences(Expected, e.JavaScriptStackTrace);
             EqualIgnoringNewLineDifferences(Expected, e.JavaScriptStackTrace);
         }
         }
 
 
+        [Fact]
+        public void ShouldReportCorrectColumn()
+        {
+            var e = Assert.Throws<JavaScriptException>(() =>
+            {
+                var engine = new Engine();
+                engine.Execute(@"var $variable1 = 611;
+var _variable2 = 711;
+var variable3 = 678;
+
+$variable1 + -variable2 - variable3;");
+            });
+
+            Assert.Equal(5, e.Location.Start.Line);
+            Assert.Equal(14, e.Location.Start.Column);
+            Assert.Equal("   at <anonymous>:5:15", e.JavaScriptStackTrace);
+        }
+
         private static void EqualIgnoringNewLineDifferences(string expected, string actual)
         private static void EqualIgnoringNewLineDifferences(string expected, string actual)
         {
         {
             expected = expected.Replace("\r\n", "\n");
             expected = expected.Replace("\r\n", "\n");

+ 0 - 1
Jint/Engine.Modules.cs

@@ -1,5 +1,4 @@
 using Esprima;
 using Esprima;
-using Esprima.Ast;
 using Jint.Native;
 using Jint.Native;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Native.Promise;
 using Jint.Native.Promise;

+ 8 - 4
Jint/Runtime/ExceptionHelper.cs

@@ -52,7 +52,8 @@ namespace Jint.Runtime
         [DoesNotReturn]
         [DoesNotReturn]
         public static void ThrowReferenceError(Realm realm, string? message)
         public static void ThrowReferenceError(Realm realm, string? message)
         {
         {
-            throw new JavaScriptException(realm.Intrinsics.ReferenceError, message);
+            var location = realm.GlobalObject.Engine.GetLastSyntaxElement()?.Location ?? default;
+            throw new JavaScriptException(realm.Intrinsics.ReferenceError, message).SetJavaScriptLocation(location);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
@@ -64,19 +65,22 @@ namespace Jint.Runtime
         [DoesNotReturn]
         [DoesNotReturn]
         public static void ThrowTypeError(Realm realm, string? message = null)
         public static void ThrowTypeError(Realm realm, string? message = null)
         {
         {
-            throw new JavaScriptException(realm.Intrinsics.TypeError, message);
+            var location = realm.GlobalObject.Engine.GetLastSyntaxElement()?.Location ?? default;
+            throw new JavaScriptException(realm.Intrinsics.TypeError, message).SetJavaScriptLocation(location);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
         public static void ThrowRangeError(Realm realm, string? message = null)
         public static void ThrowRangeError(Realm realm, string? message = null)
         {
         {
-            throw new JavaScriptException(realm.Intrinsics.RangeError, message);
+            var location = realm.GlobalObject.Engine.GetLastSyntaxElement()?.Location ?? default;
+            throw new JavaScriptException(realm.Intrinsics.RangeError, message).SetJavaScriptLocation(location);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
         public static void ThrowUriError(Realm realm)
         public static void ThrowUriError(Realm realm)
         {
         {
-            throw new JavaScriptException(realm.Intrinsics.UriError);
+            var location = realm.GlobalObject.Engine.GetLastSyntaxElement()?.Location ?? default;
+            throw new JavaScriptException(realm.Intrinsics.UriError).SetJavaScriptLocation(location);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]

+ 21 - 17
Jint/Runtime/Interpreter/JintStatementList.cs

@@ -1,5 +1,6 @@
 using Esprima.Ast;
 using Esprima.Ast;
 using Jint.Native;
 using Jint.Native;
+using Jint.Native.Error;
 using Jint.Runtime.Environments;
 using Jint.Runtime.Environments;
 using Jint.Runtime.Interpreter.Statements;
 using Jint.Runtime.Interpreter.Statements;
 
 
@@ -104,33 +105,36 @@ namespace Jint.Runtime.Interpreter
             }
             }
             catch (JavaScriptException v)
             catch (JavaScriptException v)
             {
             {
-                SyntaxElement source = s!._statement;
-                if (v.Location != default)
-                {
-                    source = EsprimaExtensions.CreateLocationNode(v.Location);
-                }
-                var completion = new Completion(CompletionType.Throw, v.Error, null, source);
-                return completion;
+                return CreateThrowCompletion(s, v);
             }
             }
             catch (TypeErrorException e)
             catch (TypeErrorException e)
             {
             {
-                var error = engine.Realm.Intrinsics.TypeError.Construct(new JsValue[]
-                {
-                    e.Message
-                });
-                return new Completion(CompletionType.Throw, error, null, s!._statement);
+                return CreateThrowCompletion(engine.Realm.Intrinsics.TypeError, e, s!);
             }
             }
             catch (RangeErrorException e)
             catch (RangeErrorException e)
             {
             {
-                var error = engine.Realm.Intrinsics.RangeError.Construct(new JsValue[]
-                {
-                    e.Message
-                });
-                c = new Completion(CompletionType.Throw, error, null, s!._statement);
+                return CreateThrowCompletion(engine.Realm.Intrinsics.RangeError, e, s!);
             }
             }
             return new Completion(c.Type, lastValue ?? JsValue.Undefined, c.Target, c._source);
             return new Completion(c.Type, lastValue ?? JsValue.Undefined, c.Target, c._source);
         }
         }
 
 
+        private static Completion CreateThrowCompletion(ErrorConstructor errorConstructor, Exception e, JintStatement s)
+        {
+            var error = errorConstructor.Construct(new JsValue[] { e.Message });
+            return new Completion(CompletionType.Throw, error, null, s._statement);
+        }
+
+        private static Completion CreateThrowCompletion(JintStatement? s, JavaScriptException v)
+        {
+            SyntaxElement source = s!._statement;
+            if (v.Location != default)
+            {
+                source = EsprimaExtensions.CreateLocationNode(v.Location);
+            }
+
+            return new Completion(CompletionType.Throw, v.Error, null, source);
+        }
+
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-blockdeclarationinstantiation
         /// https://tc39.es/ecma262/#sec-blockdeclarationinstantiation
         /// </summary>
         /// </summary>

+ 0 - 1
Jint/Runtime/Interpreter/Statements/JintSwitchBlock.cs

@@ -1,4 +1,3 @@
-using Esprima;
 using Esprima.Ast;
 using Esprima.Ast;
 using Jint.Native;
 using Jint.Native;
 using Jint.Runtime.Environments;
 using Jint.Runtime.Environments;

+ 5 - 5
Jint/Runtime/JavaScriptException.cs

@@ -61,21 +61,21 @@ public class JavaScriptException : JintException
         return this;
         return this;
     }
     }
 
 
-    private class JavaScriptErrorWrapperException : JintException
+    private sealed class JavaScriptErrorWrapperException : JintException
     {
     {
         private string? _callStack;
         private string? _callStack;
         private Location _location;
         private Location _location;
 
 
-        public JsValue Error { get; }
-
-        public ref readonly Location Location => ref _location;
-
         internal JavaScriptErrorWrapperException(JsValue error, string? message = null)
         internal JavaScriptErrorWrapperException(JsValue error, string? message = null)
             : base(message ?? GetMessage(error))
             : base(message ?? GetMessage(error))
         {
         {
             Error = error;
             Error = error;
         }
         }
 
 
+        public JsValue Error { get; }
+
+        public ref readonly Location Location => ref _location;
+
         internal void SetLocation(Location location)
         internal void SetLocation(Location location)
         {
         {
             _location = location;
             _location = location;