JintLiteralExpression.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using System.Numerics;
  2. using Esprima;
  3. using Esprima.Ast;
  4. using Jint.Native;
  5. namespace Jint.Runtime.Interpreter.Expressions
  6. {
  7. internal sealed class JintLiteralExpression : JintExpression
  8. {
  9. private JintLiteralExpression(Literal expression) : base(expression)
  10. {
  11. }
  12. internal static JintExpression Build(Literal expression)
  13. {
  14. var constantValue = ConvertToJsValue(expression);
  15. if (constantValue is not null)
  16. {
  17. return new JintConstantExpression(expression, constantValue);
  18. }
  19. return new JintLiteralExpression(expression);
  20. }
  21. internal static JsValue? ConvertToJsValue(Literal literal)
  22. {
  23. if (literal.TokenType == TokenType.BooleanLiteral)
  24. {
  25. return literal.BooleanValue!.Value ? JsBoolean.True : JsBoolean.False;
  26. }
  27. if (literal.TokenType == TokenType.NullLiteral)
  28. {
  29. return JsValue.Null;
  30. }
  31. if (literal.TokenType == TokenType.NumericLiteral)
  32. {
  33. // unbox only once
  34. var numericValue = (double) literal.Value!;
  35. var intValue = (int) numericValue;
  36. return numericValue == intValue
  37. && (intValue != 0 || BitConverter.DoubleToInt64Bits(numericValue) != JsNumber.NegativeZeroBits)
  38. ? JsNumber.Create(intValue)
  39. : JsNumber.Create(numericValue);
  40. }
  41. if (literal.TokenType == TokenType.StringLiteral)
  42. {
  43. return JsString.Create((string) literal.Value!);
  44. }
  45. if (literal.TokenType == TokenType.BigIntLiteral)
  46. {
  47. return JsBigInt.Create((BigInteger) literal.Value!);
  48. }
  49. return null;
  50. }
  51. public override Completion GetValue(EvaluationContext context)
  52. {
  53. // need to notify correct node when taking shortcut
  54. context.LastSyntaxElement = _expression;
  55. JsValue value = ResolveValue(context);
  56. return new(CompletionType.Normal, value, _expression);
  57. }
  58. protected override ExpressionResult EvaluateInternal(EvaluationContext context) => NormalCompletion(ResolveValue(context));
  59. private JsValue ResolveValue(EvaluationContext context)
  60. {
  61. var expression = (Literal) _expression;
  62. if (expression.TokenType == TokenType.RegularExpression)
  63. {
  64. return context.Engine.Realm.Intrinsics.RegExp.Construct((System.Text.RegularExpressions.Regex) expression.Value!, expression.Regex!.Pattern, expression.Regex.Flags);
  65. }
  66. return JsValue.FromObject(context.Engine, expression.Value);
  67. }
  68. }
  69. }