JintNewExpression.cs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. namespace Jint.Runtime.Interpreter.Expressions
  4. {
  5. internal sealed class JintNewExpression : JintExpression
  6. {
  7. private JintExpression _calleeExpression = null!;
  8. private JintExpression[] _jintArguments = Array.Empty<JintExpression>();
  9. private bool _hasSpreads;
  10. public JintNewExpression(NewExpression expression) : base(expression)
  11. {
  12. _initialized = false;
  13. }
  14. protected override void Initialize(EvaluationContext context)
  15. {
  16. var expression = (NewExpression) _expression;
  17. _calleeExpression = Build(expression.Callee);
  18. if (expression.Arguments.Count <= 0)
  19. {
  20. return;
  21. }
  22. _jintArguments = new JintExpression[expression.Arguments.Count];
  23. for (var i = 0; i < _jintArguments.Length; i++)
  24. {
  25. var argument = expression.Arguments[i];
  26. _jintArguments[i] = Build(argument);
  27. _hasSpreads |= argument.Type == Nodes.SpreadElement;
  28. }
  29. }
  30. protected override object EvaluateInternal(EvaluationContext context)
  31. {
  32. var engine = context.Engine;
  33. // todo: optimize by defining a common abstract class or interface
  34. var jsValue = _calleeExpression.GetValue(context);
  35. JsValue[] arguments;
  36. if (_jintArguments.Length == 0)
  37. {
  38. arguments = Array.Empty<JsValue>();
  39. }
  40. else if (_hasSpreads)
  41. {
  42. arguments = BuildArgumentsWithSpreads(context, _jintArguments);
  43. }
  44. else
  45. {
  46. arguments = engine._jsValueArrayPool.RentArray(_jintArguments.Length);
  47. BuildArguments(context, _jintArguments, arguments);
  48. }
  49. // Reset the location to the "new" keyword so that if an Error object is
  50. // constructed below, the stack trace will capture the correct location.
  51. context.LastSyntaxElement = _expression;
  52. if (!jsValue.IsConstructor)
  53. {
  54. ExceptionHelper.ThrowTypeError(engine.Realm, _calleeExpression.SourceText + " is not a constructor");
  55. }
  56. // construct the new instance using the Function's constructor method
  57. var instance = engine.Construct(jsValue, arguments, jsValue, _calleeExpression);
  58. engine._jsValueArrayPool.ReturnArray(arguments);
  59. return instance;
  60. }
  61. }
  62. }