JavascriptParserTests.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using Jint.Parser;
  7. using Jint.Parser.Ast;
  8. using Xunit;
  9. using Xunit.Extensions;
  10. namespace Jint.Tests.Parser
  11. {
  12. public class JavascriptParserTests
  13. {
  14. private readonly JavaScriptParser _parser = new JavaScriptParser();
  15. private string GetEmbeddedFile(string filename)
  16. {
  17. const string prefix = "Jint.Tests.Parser.Scripts.";
  18. var assembly = typeof(JavascriptParserTests).GetTypeInfo().Assembly;
  19. var scriptPath = prefix + filename;
  20. using (var stream = assembly.GetManifestResourceStream(scriptPath))
  21. {
  22. using (var sr = new StreamReader(stream))
  23. {
  24. return sr.ReadToEnd();
  25. }
  26. }
  27. }
  28. [Theory]
  29. [InlineData("jQuery.js", "1.9.1")]
  30. [InlineData("underscore.js", "1.5.2")]
  31. [InlineData("backbone.js", "1.1.0")]
  32. [InlineData("mootools.js", "1.4.5")]
  33. [InlineData("angular.js", "1.2.5")]
  34. [InlineData("JSXTransformer.js", "0.10.0")]
  35. [InlineData("handlebars.js", "2.0.0")]
  36. public void ShouldParseScriptFile(string file, string version)
  37. {
  38. var parser = new JavaScriptParser();
  39. var source = GetEmbeddedFile(file);
  40. var sw = new Stopwatch();
  41. var program = parser.Parse(source);
  42. Console.WriteLine("Parsed {0} {1} ({3} KB) in {2} ms", file, version, sw.ElapsedMilliseconds, (int)source.Length/1024);
  43. Assert.NotNull(program);
  44. }
  45. [Fact]
  46. public void ShouldParseThis()
  47. {
  48. var program = _parser.Parse("this");
  49. var body = program.Body;
  50. Assert.NotNull(body);
  51. Assert.Single(body);
  52. Assert.Equal(SyntaxNodes.ThisExpression, body.First().As<ExpressionStatement>().Expression.Type);
  53. }
  54. [Fact]
  55. public void ShouldParseNull()
  56. {
  57. var program = _parser.Parse("null");
  58. var body = program.Body;
  59. Assert.NotNull(body);
  60. Assert.Single(body);
  61. Assert.Equal(SyntaxNodes.Literal, body.First().As<ExpressionStatement>().Expression.Type);
  62. Assert.Equal(null, body.First().As<ExpressionStatement>().Expression.As<Literal>().Value);
  63. Assert.Equal("null", body.First().As<ExpressionStatement>().Expression.As<Literal>().Raw);
  64. }
  65. [Fact]
  66. public void ShouldParseNumeric()
  67. {
  68. var program = _parser.Parse(
  69. @"
  70. 42
  71. ");
  72. var body = program.Body;
  73. Assert.NotNull(body);
  74. Assert.Single(body);
  75. Assert.Equal(SyntaxNodes.Literal, body.First().As<ExpressionStatement>().Expression.Type);
  76. Assert.Equal(42d, body.First().As<ExpressionStatement>().Expression.As<Literal>().Value);
  77. Assert.Equal("42", body.First().As<ExpressionStatement>().Expression.As<Literal>().Raw);
  78. }
  79. [Fact]
  80. public void ShouldParseBinaryExpression()
  81. {
  82. BinaryExpression binary;
  83. var program = _parser.Parse("(1 + 2 ) * 3");
  84. var body = program.Body;
  85. Assert.NotNull(body);
  86. Assert.Single(body);
  87. Assert.NotNull(binary = body.First().As<ExpressionStatement>().Expression.As<BinaryExpression>());
  88. Assert.Equal(3d, binary.Right.As<Literal>().Value);
  89. Assert.Equal(BinaryOperator.Times, binary.Operator);
  90. Assert.Equal(1d, binary.Left.As<BinaryExpression>().Left.As<Literal>().Value);
  91. Assert.Equal(2d, binary.Left.As<BinaryExpression>().Right.As<Literal>().Value);
  92. Assert.Equal(BinaryOperator.Plus, binary.Left.As<BinaryExpression>().Operator);
  93. }
  94. [Theory]
  95. [InlineData(0, "0")]
  96. [InlineData(42, "42")]
  97. [InlineData(0.14, "0.14")]
  98. [InlineData(3.14159, "3.14159")]
  99. [InlineData(6.02214179e+23, "6.02214179e+23")]
  100. [InlineData(1.492417830e-10, "1.492417830e-10")]
  101. [InlineData(0, "0x0")]
  102. [InlineData(0, "0x0;")]
  103. [InlineData(0xabc, "0xabc")]
  104. [InlineData(0xdef, "0xdef")]
  105. [InlineData(0X1A, "0X1A")]
  106. [InlineData(0x10, "0x10")]
  107. [InlineData(0x100, "0x100")]
  108. [InlineData(0X04, "0X04")]
  109. [InlineData(02, "02")]
  110. [InlineData(10, "012")]
  111. [InlineData(10, "0012")]
  112. [InlineData(1.189008226412092e+38, "0x5973772948c653ac1971f1576e03c4d4")]
  113. [InlineData(18446744073709552000d, "0xffffffffffffffff")]
  114. public void ShouldParseNumericLiterals(object expected, string source)
  115. {
  116. Literal literal;
  117. var program = _parser.Parse(source);
  118. var body = program.Body;
  119. Assert.NotNull(body);
  120. Assert.Single(body);
  121. Assert.NotNull(literal = body.First().As<ExpressionStatement>().Expression.As<Literal>());
  122. Assert.Equal(Convert.ToDouble(expected), Convert.ToDouble(literal.Value));
  123. }
  124. [Theory]
  125. [InlineData("Hello", @"'Hello'")]
  126. [InlineData("\n\r\t\v\b\f\\\'\"\0", @"'\n\r\t\v\b\f\\\'\""\0'")]
  127. [InlineData("\u0061", @"'\u0061'")]
  128. [InlineData("\x61", @"'\x61'")]
  129. [InlineData("Hello\nworld", @"'Hello\nworld'")]
  130. [InlineData("Hello\\\nworld", @"'Hello\\\nworld'")]
  131. public void ShouldParseStringLiterals(string expected, string source)
  132. {
  133. Literal literal;
  134. var program = _parser.Parse(source);
  135. var body = program.Body;
  136. Assert.NotNull(body);
  137. Assert.Single(body);
  138. Assert.NotNull(literal = body.First().As<ExpressionStatement>().Expression.As<Literal>());
  139. Assert.Equal(expected, literal.Value);
  140. }
  141. [Theory]
  142. [InlineData(@"{ x
  143. ++y }")]
  144. [InlineData(@"{ x
  145. --y }")]
  146. [InlineData(@"var x /* comment */;
  147. { var x = 14, y = 3
  148. z; }")]
  149. [InlineData(@"while (true) { continue
  150. there; }")]
  151. [InlineData(@"while (true) { continue // Comment
  152. there; }")]
  153. [InlineData(@"while (true) { continue /* Multiline
  154. Comment */there; }")]
  155. [InlineData(@"while (true) { break
  156. there; }")]
  157. [InlineData(@"while (true) { break // Comment
  158. there; }")]
  159. [InlineData(@"while (true) { break /* Multiline
  160. Comment */there; }")]
  161. [InlineData(@"(function(){ return
  162. x; })")]
  163. [InlineData(@"(function(){ return // Comment
  164. x; })")]
  165. [InlineData(@"(function(){ return/* Multiline
  166. Comment */x; })")]
  167. [InlineData(@"{ throw error
  168. error; }")]
  169. [InlineData(@"{ throw error// Comment
  170. error; }")]
  171. [InlineData(@"{ throw error/* Multiline
  172. Comment */error; }")]
  173. public void ShouldInsertSemicolons(string source)
  174. {
  175. var program = _parser.Parse(source);
  176. var body = program.Body;
  177. Assert.NotNull(body);
  178. }
  179. [Fact]
  180. public void ShouldProvideLocationForMultiLinesStringLiterals()
  181. {
  182. var source = @"'\
  183. \
  184. '
  185. ";
  186. var program = _parser.Parse(source);
  187. var expr = program.Body.First().As<ExpressionStatement>().Expression;
  188. Assert.Equal(1, expr.Location.Start.Line);
  189. Assert.Equal(0, expr.Location.Start.Column);
  190. Assert.Equal(3, expr.Location.End.Line);
  191. Assert.Equal(1, expr.Location.End.Column);
  192. }
  193. }
  194. }