JintLiteralExpression.cs 2.8 KB

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