DataViewConstructor.cs 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Jint.Native.ArrayBuffer;
  2. using Jint.Native.Function;
  3. using Jint.Native.Object;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. namespace Jint.Native.DataView
  7. {
  8. /// <summary>
  9. /// https://tc39.es/ecma262/#sec-dataview-constructor
  10. /// </summary>
  11. public sealed class DataViewConstructor : FunctionInstance, IConstructor
  12. {
  13. private static readonly JsString _functionName = new("DataView");
  14. internal DataViewConstructor(
  15. Engine engine,
  16. Realm realm,
  17. FunctionPrototype functionPrototype,
  18. ObjectPrototype objectPrototype)
  19. : base(engine, realm, _functionName)
  20. {
  21. _prototype = functionPrototype;
  22. PrototypeObject = new DataViewPrototype(engine, realm, this, objectPrototype);
  23. _length = new PropertyDescriptor(1, PropertyFlag.Configurable);
  24. _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
  25. }
  26. public DataViewPrototype PrototypeObject { get; }
  27. protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
  28. {
  29. ExceptionHelper.ThrowTypeError(_realm, "Constructor DataView requires 'new'");
  30. return Undefined;
  31. }
  32. ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
  33. {
  34. if (newTarget.IsUndefined())
  35. {
  36. ExceptionHelper.ThrowTypeError(_realm);
  37. }
  38. var buffer = arguments.At(0) as ArrayBufferInstance;
  39. var byteOffset = arguments.At(1);
  40. var byteLength = arguments.At(2);
  41. if (buffer is null)
  42. {
  43. ExceptionHelper.ThrowTypeError(_realm, "First argument to DataView constructor must be an ArrayBuffer");
  44. }
  45. var offset = TypeConverter.ToIndex(_realm, byteOffset);
  46. if (buffer.IsDetachedBuffer)
  47. {
  48. ExceptionHelper.ThrowTypeError(_realm);
  49. }
  50. var bufferByteLength = (uint) buffer.ArrayBufferByteLength;
  51. if (offset > bufferByteLength)
  52. {
  53. ExceptionHelper.ThrowRangeError(_realm, "Start offset " + offset + " is outside the bounds of the buffer");
  54. }
  55. uint viewByteLength;
  56. if (byteLength.IsUndefined())
  57. {
  58. viewByteLength = bufferByteLength - offset;
  59. }
  60. else
  61. {
  62. viewByteLength = TypeConverter.ToIndex(_realm, byteLength);
  63. if (offset + viewByteLength > bufferByteLength)
  64. {
  65. ExceptionHelper.ThrowRangeError(_realm, "Invalid DataView length");
  66. }
  67. }
  68. var o = OrdinaryCreateFromConstructor(
  69. newTarget,
  70. static intrinsics => intrinsics.DataView.PrototypeObject,
  71. static (Engine engine, Realm _, object _) => new DataViewInstance(engine));
  72. if (buffer.IsDetachedBuffer)
  73. {
  74. ExceptionHelper.ThrowTypeError(_realm);
  75. }
  76. o._viewedArrayBuffer = buffer;
  77. o._byteLength = viewByteLength;
  78. o._byteOffset = offset;
  79. return o;
  80. }
  81. }
  82. }