JintNewExpression.cs 2.6 KB

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