JintLiteralExpression.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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.UserData ??= 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.Kind)
  24. {
  25. case TokenKind.BooleanLiteral:
  26. return ((BooleanLiteral) literal).Value ? JsBoolean.True : JsBoolean.False;
  27. case TokenKind.NullLiteral:
  28. return JsValue.Null;
  29. case TokenKind.NumericLiteral:
  30. {
  31. var numericValue = ((NumericLiteral) literal).Value;
  32. var intValue = (int) numericValue;
  33. return numericValue == intValue
  34. && (intValue != 0 || BitConverter.DoubleToInt64Bits(numericValue) != JsNumber.NegativeZeroBits)
  35. ? JsNumber.Create(intValue)
  36. : JsNumber.Create(numericValue);
  37. }
  38. case TokenKind.StringLiteral:
  39. return JsString.Create(((StringLiteral) literal).Value);
  40. case TokenKind.BigIntLiteral:
  41. return JsBigInt.Create(((BigIntLiteral) literal).Value);
  42. case TokenKind.RegExpLiteral:
  43. break;
  44. }
  45. return null;
  46. }
  47. public override JsValue GetValue(EvaluationContext context)
  48. {
  49. // need to notify correct node when taking shortcut
  50. context.LastSyntaxElement = _expression;
  51. return ResolveValue(context);
  52. }
  53. protected override object EvaluateInternal(EvaluationContext context) => ResolveValue(context);
  54. private JsValue ResolveValue(EvaluationContext context)
  55. {
  56. var expression = (Literal) _expression;
  57. if (expression is RegExpLiteral regExpLiteral)
  58. {
  59. var regExpParseResult = regExpLiteral.ParseResult;
  60. if (regExpParseResult.Success)
  61. {
  62. var regex = regExpLiteral.UserData as Regex ?? regExpParseResult.Regex!;
  63. return context.Engine.Realm.Intrinsics.RegExp.Construct(regex, regExpLiteral.RegExp.Pattern, regExpLiteral.RegExp.Flags, regExpParseResult);
  64. }
  65. ExceptionHelper.ThrowSyntaxError(context.Engine.Realm, $"Unsupported regular expression. {regExpParseResult.ConversionError!.Description}");
  66. }
  67. return JsValue.FromObject(context.Engine, expression.Value);
  68. }
  69. }
  70. }