JintNewExpression.cs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. namespace Jint.Runtime.Interpreter.Expressions
  4. {
  5. internal sealed class JintNewExpression : JintExpression
  6. {
  7. private readonly JintExpression _calleeExpression;
  8. private JintExpression[] _jintArguments;
  9. private bool _hasSpreads;
  10. public JintNewExpression(Engine engine, NewExpression expression) : base(engine, expression)
  11. {
  12. _initialized = false;
  13. _calleeExpression = Build(engine, expression.Callee);
  14. }
  15. protected override void Initialize()
  16. {
  17. var expression = (NewExpression) _expression;
  18. _jintArguments = new JintExpression[expression.Arguments.Count];
  19. for (var i = 0; i < _jintArguments.Length; i++)
  20. {
  21. _jintArguments[i] = Build(_engine, (Expression) expression.Arguments[i]);
  22. _hasSpreads |= _jintArguments[i] is JintSpreadExpression;
  23. }
  24. }
  25. protected override object EvaluateInternal()
  26. {
  27. JsValue[] arguments;
  28. if (_hasSpreads)
  29. {
  30. arguments = BuildArgumentsWithSpreads(_jintArguments);
  31. }
  32. else
  33. {
  34. arguments = _engine._jsValueArrayPool.RentArray(_jintArguments.Length);
  35. BuildArguments(_jintArguments, arguments);
  36. }
  37. // todo: optimize by defining a common abstract class or interface
  38. var jsValue = _calleeExpression.GetValue();
  39. if (!(jsValue is IConstructor callee))
  40. {
  41. return ExceptionHelper.ThrowTypeError<object>(_engine, "The object can't be used as constructor.");
  42. }
  43. // construct the new instance using the Function's constructor method
  44. var instance = callee.Construct(arguments, jsValue);
  45. _engine._jsValueArrayPool.ReturnArray(arguments);
  46. return instance;
  47. }
  48. }
  49. }