ScriptModulePreparationTests.ScriptPreparation.cs 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System.Text.RegularExpressions;
  2. using Jint.Native;
  3. using Jint.Runtime.Interpreter;
  4. using Jint.Runtime.Interpreter.Expressions;
  5. using Jint.Runtime.Interpreter.Statements;
  6. namespace Jint.Tests.Runtime;
  7. public class ScriptModulePreparationTests
  8. {
  9. [Fact]
  10. public void ScriptPreparationAcceptsReturnOutsideOfFunctions()
  11. {
  12. var preparedScript = Engine.PrepareScript("return 1;");
  13. preparedScript.Program.Body[0].Should().BeOfType<ReturnStatement>();
  14. }
  15. [Fact]
  16. public void CanPreCompileRegex()
  17. {
  18. var script = Engine.PrepareScript("var x = /[cgt]/ig; var y = /[cgt]/ig; 'g'.match(x).length;");
  19. var declaration = Assert.IsType<VariableDeclaration>(script.Program.Body[0]);
  20. var init = Assert.IsType<RegExpLiteral>(declaration.Declarations[0].Init);
  21. init.Value.ToString().Should().Be("[cgt]");
  22. (init.Value.Options & RegexOptions.Compiled).Should().Be(RegexOptions.Compiled);
  23. new Engine().Evaluate(script).AsNumber().Should().Be(1);
  24. }
  25. [Fact]
  26. public void ScriptPreparationFoldsConstants()
  27. {
  28. var preparedScript = Engine.PrepareScript("return 1 + 2;");
  29. var returnStatement = Assert.IsType<ReturnStatement>(preparedScript.Program.Body[0]);
  30. var constant = Assert.IsType<JintConstantExpression>(returnStatement.Argument?.UserData);
  31. constant.GetValue(null!).AsNumber().Should().Be(3);
  32. new Engine().Evaluate(preparedScript).AsNumber().Should().Be(3);
  33. }
  34. [Fact]
  35. public void ScriptPreparationOptimizesNegatingUnaryExpression()
  36. {
  37. var preparedScript = Engine.PrepareScript("-1");
  38. var expression = Assert.IsType<NonSpecialExpressionStatement>(preparedScript.Program.Body[0]);
  39. var unaryExpression = Assert.IsType<NonUpdateUnaryExpression>(expression.Expression);
  40. var constant = Assert.IsType<JintConstantExpression>(unaryExpression.UserData);
  41. constant.GetValue(null!).AsNumber().Should().Be(-1);
  42. new Engine().Evaluate(preparedScript).AsNumber().Should().Be(-1);
  43. }
  44. [Fact]
  45. public void ScriptPreparationOptimizesConstantReturn()
  46. {
  47. var preparedScript = Engine.PrepareScript("return false;");
  48. var statement = Assert.IsType<ReturnStatement>(preparedScript.Program.Body[0]);
  49. var returnStatement = Assert.IsType<ConstantStatement>(statement.UserData);
  50. var builtStatement = JintStatement.Build(statement);
  51. returnStatement.Should().BeSameAs(builtStatement);
  52. var result = builtStatement.Execute(new EvaluationContext( new Engine())).Value;
  53. result.Should().Be(JsBoolean.False);
  54. }
  55. [Fact]
  56. public void CompiledRegexShouldProduceSameResultAsNonCompiled()
  57. {
  58. const string Script = """JSON.stringify(/(.*?)a(?!(a+)b\2c)\2(.*)/.exec("baaabaac"))""";
  59. var engine = new Engine();
  60. var nonCompiledResult = engine.Evaluate(Script);
  61. var compiledResult = engine.Evaluate(Engine.PrepareScript(Script));
  62. nonCompiledResult.Should().Be(compiledResult);
  63. }
  64. [Fact]
  65. public void PrepareScriptShouldNotLeakAcornimaException()
  66. {
  67. var ex = Assert.Throws<ScriptPreparationException>(() => Engine.PrepareScript("class A { } A().#nonexistent = 1;"));
  68. ex.Message.Should().Be("Could not prepare script: Private field '#nonexistent' must be declared in an enclosing class (1:17)");
  69. ex.InnerException.Should().BeOfType<SyntaxErrorException>();
  70. }
  71. [Fact]
  72. public void PrepareModuleShouldNotLeakAcornimaException()
  73. {
  74. var ex = Assert.Throws<ScriptPreparationException>(() => Engine.PrepareModule("class A { } A().#nonexistent = 1;"));
  75. ex.Message.Should().Be("Could not prepare script: Private field '#nonexistent' must be declared in an enclosing class (1:17)");
  76. ex.InnerException.Should().BeOfType<SyntaxErrorException>();
  77. }
  78. }