JintLiteralExpression.cs 3.1 KB

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