NullishCoalescingExpression.cs 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. using System.Runtime.CompilerServices;
  2. using Esprima.Ast;
  3. using Jint.Native;
  4. namespace Jint.Runtime.Interpreter.Expressions
  5. {
  6. internal sealed class NullishCoalescingExpression : JintExpression
  7. {
  8. private readonly JintExpression _left;
  9. private readonly JintExpression? _right;
  10. private readonly JsValue? _constant;
  11. public NullishCoalescingExpression(Engine engine, BinaryExpression expression) : base(expression)
  12. {
  13. _left = Build(engine, expression.Left);
  14. // we can create a fast path for common literal case like variable ?? 0
  15. if (expression.Right is Literal l)
  16. {
  17. _constant = JintLiteralExpression.ConvertToJsValue(l);
  18. }
  19. else
  20. {
  21. _right = Build(engine, expression.Right);
  22. }
  23. }
  24. public override Completion GetValue(EvaluationContext context)
  25. {
  26. // need to notify correct node when taking shortcut
  27. context.LastSyntaxElement = _expression;
  28. JsValue value = EvaluateConstantOrExpression(context);
  29. return new(CompletionType.Normal, value, _expression);
  30. }
  31. protected override ExpressionResult EvaluateInternal(EvaluationContext context)
  32. {
  33. return NormalCompletion(EvaluateConstantOrExpression(context));
  34. }
  35. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  36. private JsValue EvaluateConstantOrExpression(EvaluationContext context)
  37. {
  38. var left = _left.GetValue(context).Value;
  39. return !left.IsNullOrUndefined()
  40. ? left
  41. : _constant ?? _right!.GetValue(context).Value;
  42. }
  43. }
  44. }