BindFunctionInstance.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using Jint.Native.Object;
  2. using Jint.Runtime;
  3. namespace Jint.Native.Function
  4. {
  5. /// <summary>
  6. /// https://tc39.es/ecma262/#sec-bound-function-exotic-objects
  7. /// </summary>
  8. public sealed class BindFunctionInstance : ObjectInstance, IConstructor, ICallable
  9. {
  10. private readonly Realm _realm;
  11. public BindFunctionInstance(Engine engine,
  12. Realm realm,
  13. ObjectInstance? proto,
  14. ObjectInstance targetFunction,
  15. JsValue boundThis,
  16. JsValue[] boundArgs)
  17. : base(engine, ObjectClass.Function)
  18. {
  19. _realm = realm;
  20. _prototype = proto;
  21. BoundTargetFunction = targetFunction;
  22. BoundThis = boundThis;
  23. BoundArguments = boundArgs;
  24. }
  25. /// <summary>
  26. /// The wrapped function object.
  27. /// </summary>
  28. public JsValue BoundTargetFunction { get; }
  29. /// <summary>
  30. /// The value that is always passed as the this value when calling the wrapped function.
  31. /// </summary>
  32. public JsValue BoundThis { get; }
  33. /// <summary>
  34. /// A list of values whose elements are used as the first arguments to any call to the wrapped function.
  35. /// </summary>
  36. public JsValue[] BoundArguments { get; }
  37. JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
  38. {
  39. var f = BoundTargetFunction as FunctionInstance;
  40. if (f is null)
  41. {
  42. ExceptionHelper.ThrowTypeError(_realm);
  43. }
  44. var args = CreateArguments(arguments);
  45. var value = f.Call(BoundThis, args);
  46. _engine._jsValueArrayPool.ReturnArray(args);
  47. return value;
  48. }
  49. ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
  50. {
  51. var target = BoundTargetFunction as IConstructor;
  52. if (target is null)
  53. {
  54. ExceptionHelper.ThrowTypeError(_realm);
  55. }
  56. var args = CreateArguments(arguments);
  57. if (ReferenceEquals(this, newTarget))
  58. {
  59. newTarget = BoundTargetFunction;
  60. }
  61. var value = target.Construct(args, newTarget);
  62. _engine._jsValueArrayPool.ReturnArray(args);
  63. return value;
  64. }
  65. internal override bool OrdinaryHasInstance(JsValue v)
  66. {
  67. var f = BoundTargetFunction as FunctionInstance;
  68. if (f is null)
  69. {
  70. ExceptionHelper.ThrowTypeError(_realm);
  71. }
  72. return f.OrdinaryHasInstance(v);
  73. }
  74. private JsValue[] CreateArguments(JsValue[] arguments)
  75. {
  76. var combined = _engine._jsValueArrayPool.RentArray(BoundArguments.Length + arguments.Length);
  77. System.Array.Copy(BoundArguments, combined, BoundArguments.Length);
  78. System.Array.Copy(arguments, 0, combined, BoundArguments.Length, arguments.Length);
  79. return combined;
  80. }
  81. internal override bool IsConstructor => BoundTargetFunction.IsConstructor;
  82. public override string ToString() => "function () { [native code] }";
  83. }
  84. }