ErrorTests.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using Esprima;
  2. using Jint.Runtime;
  3. using System;
  4. using System.Collections.Generic;
  5. using Xunit;
  6. namespace Jint.Tests.Runtime
  7. {
  8. public class ErrorTests
  9. {
  10. [Fact]
  11. public void CanReturnCorrectErrorMessageAndLocation1()
  12. {
  13. const string script = @"
  14. var a = {};
  15. var b = a.user.name;
  16. ";
  17. var engine = new Engine();
  18. var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
  19. Assert.Equal("Cannot read property 'name' of undefined", e.Message);
  20. Assert.Equal(4, e.Location.Start.Line);
  21. Assert.Equal(15, e.Location.Start.Column);
  22. }
  23. [Fact]
  24. public void CanReturnCorrectErrorMessageAndLocation1WithoutReferencedName()
  25. {
  26. const string script = @"
  27. var c = a(b().Length);
  28. ";
  29. var engine = new Engine();
  30. engine.SetValue("a", new Action<string>((_) => { }));
  31. engine.SetValue("b", new Func<string>(() => null));
  32. var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
  33. Assert.Equal("Cannot read property 'Length' of null", e.Message);
  34. Assert.Equal(2, e.Location.Start.Line);
  35. Assert.Equal(14, e.Location.Start.Column);
  36. }
  37. [Fact]
  38. public void CanReturnCorrectErrorMessageAndLocation2()
  39. {
  40. const string script = @"
  41. test();
  42. ";
  43. var engine = new Engine();
  44. var e = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
  45. Assert.Equal("test is not defined", e.Message);
  46. Assert.Equal(2, e.Location.Start.Line);
  47. Assert.Equal(1, e.Location.Start.Column);
  48. }
  49. [Fact]
  50. public void CanProduceCorrectStackTrace()
  51. {
  52. var engine = new Engine();
  53. engine.Execute(@"var a = function(v) {
  54. return v.xxx.yyy;
  55. }
  56. var b = function(v) {
  57. return a(v);
  58. }", new ParserOptions("custom.js"));
  59. var e = Assert.Throws<JavaScriptException>(() => engine.Execute("var x = b(7);", new ParserOptions("main.js")));
  60. Assert.Equal("Cannot read property 'yyy' of undefined", e.Message);
  61. Assert.Equal(2, e.Location.Start.Line);
  62. Assert.Equal(17, e.Location.Start.Column);
  63. Assert.Equal("custom.js", e.Location.Source);
  64. var stack = e.StackTrace;
  65. EqualIgnoringNewLineDifferences(@" at a (v) custom.js:2:18
  66. at b (v) custom.js:6:9
  67. at main.js:1:9", stack);
  68. }
  69. private class Folder
  70. {
  71. public Folder Parent { get; set; }
  72. public string Name { get; set; }
  73. }
  74. [Fact]
  75. public void CallStackBuildingShouldSkipResolvingFromEngine()
  76. {
  77. var engine = new Engine(o => o.LimitRecursion(200));
  78. var recordedFolderTraversalOrder = new List<string>();
  79. engine.SetValue("log", new Action<object>(o => recordedFolderTraversalOrder.Add(o.ToString())));
  80. var folder = new Folder
  81. {
  82. Name = "SubFolder2",
  83. Parent = new Folder
  84. {
  85. Name = "SubFolder1",
  86. Parent = new Folder
  87. {
  88. Name = "Root", Parent = null,
  89. }
  90. }
  91. };
  92. engine.SetValue("folder", folder);
  93. var javaScriptException = Assert.Throws<JavaScriptException>(() =>
  94. engine.Execute(@"
  95. var Test = {
  96. recursive: function(folderInstance) {
  97. // Enabling the guard here corrects the problem, but hides the hard fault
  98. // if (folderInstance==null) return null;
  99. log(folderInstance.Name);
  100. if (folderInstance==null) return null;
  101. return this.recursive(folderInstance.parent);
  102. }
  103. }
  104. Test.recursive(folder);"
  105. ));
  106. Assert.Equal("Cannot read property 'Name' of null", javaScriptException.Message);
  107. EqualIgnoringNewLineDifferences(@" at recursive (folderInstance) <anonymous>:6:44
  108. at recursive (folderInstance) <anonymous>:8:32
  109. at recursive (folderInstance) <anonymous>:8:32
  110. at recursive (folderInstance) <anonymous>:8:32
  111. at <anonymous>:12:17", javaScriptException.StackTrace);
  112. var expected = new List<string>
  113. {
  114. "SubFolder2", "SubFolder1", "Root"
  115. };
  116. Assert.Equal(expected, recordedFolderTraversalOrder);
  117. }
  118. [Fact]
  119. public void StackTraceCollectedOnThreeLevels()
  120. {
  121. var engine = new Engine();
  122. const string script = @"var a = function(v) {
  123. return v.xxx.yyy;
  124. }
  125. var b = function(v) {
  126. return a(v);
  127. }
  128. var x = b(7);";
  129. var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script));
  130. const string expected = @"Jint.Runtime.JavaScriptException: Cannot read property 'yyy' of undefined
  131. at a (v) <anonymous>:2:18
  132. at b (v) <anonymous>:6:12
  133. at <anonymous>:9:9";
  134. EqualIgnoringNewLineDifferences(expected, ex.ToString());
  135. }
  136. [Fact]
  137. public void StackTraceCollectedForImmediatelyInvokedFunctionExpression()
  138. {
  139. var engine = new Engine();
  140. const string script = @"function getItem(items, itemIndex) {
  141. var item = items[itemIndex];
  142. return item;
  143. }
  144. (function (getItem) {
  145. var items = null,
  146. item = getItem(items, 5)
  147. ;
  148. return item;
  149. })(getItem);";
  150. var parserOptions = new ParserOptions("get-item.js")
  151. {
  152. AdaptRegexp = true,
  153. Tolerant = true
  154. };
  155. var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script, parserOptions));
  156. const string expected = @"Jint.Runtime.JavaScriptException: Cannot read property '5' of null
  157. at getItem (items, itemIndex) get-item.js:2:22
  158. at (anonymous) (getItem) get-item.js:9:16
  159. at get-item.js:13:2";
  160. EqualIgnoringNewLineDifferences(expected, ex.ToString());
  161. }
  162. private static void EqualIgnoringNewLineDifferences(string expected, string actual)
  163. {
  164. expected = expected.Replace("\r\n", "\n");
  165. actual = actual.Replace("\r\n", "\n");
  166. Assert.Equal(expected, actual);
  167. }
  168. }
  169. }