JintLiteralExpression.cs 3.2 KB

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