DataView.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Runtime/DataView.h>
  7. namespace JS {
  8. JS_DEFINE_ALLOCATOR(DataView);
  9. NonnullGCPtr<DataView> DataView::create(Realm& realm, ArrayBuffer* viewed_buffer, ByteLength byte_length, size_t byte_offset)
  10. {
  11. return realm.heap().allocate<DataView>(realm, viewed_buffer, move(byte_length), byte_offset, realm.intrinsics().data_view_prototype());
  12. }
  13. DataView::DataView(ArrayBuffer* viewed_buffer, ByteLength byte_length, size_t byte_offset, Object& prototype)
  14. : Object(ConstructWithPrototypeTag::Tag, prototype)
  15. , m_viewed_array_buffer(viewed_buffer)
  16. , m_byte_length(move(byte_length))
  17. , m_byte_offset(byte_offset)
  18. {
  19. }
  20. void DataView::visit_edges(Visitor& visitor)
  21. {
  22. Base::visit_edges(visitor);
  23. visitor.visit(m_viewed_array_buffer);
  24. }
  25. // 25.3.1.2 MakeDataViewWithBufferWitnessRecord ( obj, order ), https://tc39.es/ecma262/#sec-makedataviewwithbufferwitnessrecord
  26. DataViewWithBufferWitness make_data_view_with_buffer_witness_record(DataView const& data_view, ArrayBuffer::Order order)
  27. {
  28. // 1. Let buffer be obj.[[ViewedArrayBuffer]].
  29. auto* buffer = data_view.viewed_array_buffer();
  30. ByteLength byte_length { 0 };
  31. // 2. If IsDetachedBuffer(buffer) is true, then
  32. if (buffer->is_detached()) {
  33. // a. Let byteLength be detached.
  34. byte_length = ByteLength::detached();
  35. }
  36. // 3. Else,
  37. else {
  38. // a. Let byteLength be ArrayBufferByteLength(buffer, order).
  39. byte_length = array_buffer_byte_length(*buffer, order);
  40. }
  41. // 4. Return the DataView With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }.
  42. return { .object = data_view, .cached_buffer_byte_length = move(byte_length) };
  43. }
  44. // 25.3.1.3 GetViewByteLength ( viewRecord ), https://tc39.es/ecma262/#sec-getviewbytelength
  45. u32 get_view_byte_length(DataViewWithBufferWitness const& view_record)
  46. {
  47. // 1. Assert: IsViewOutOfBounds(viewRecord) is false.
  48. VERIFY(!is_view_out_of_bounds(view_record));
  49. // 2. Let view be viewRecord.[[Object]].
  50. auto const& view = *view_record.object;
  51. // 3. If view.[[ByteLength]] is not auto, return view.[[ByteLength]].
  52. if (!view.byte_length().is_auto())
  53. return view.byte_length().length();
  54. // 4. Assert: IsFixedLengthArrayBuffer(view.[[ViewedArrayBuffer]]) is false.
  55. VERIFY(!view.viewed_array_buffer()->is_fixed_length());
  56. // 5. Let byteOffset be view.[[ByteOffset]].
  57. auto byte_offset = view.byte_offset();
  58. // 6. Let byteLength be viewRecord.[[CachedBufferByteLength]].
  59. auto const& byte_length = view_record.cached_buffer_byte_length;
  60. // 7. Assert: byteLength is not detached.
  61. VERIFY(!byte_length.is_detached());
  62. // 8. Return byteLength - byteOffset.
  63. return byte_length.length() - byte_offset;
  64. }
  65. // 25.3.1.4 IsViewOutOfBounds ( viewRecord ), https://tc39.es/ecma262/#sec-isviewoutofbounds
  66. bool is_view_out_of_bounds(DataViewWithBufferWitness const& view_record)
  67. {
  68. // 1. Let view be viewRecord.[[Object]].
  69. auto const& view = *view_record.object;
  70. // 2. Let bufferByteLength be viewRecord.[[CachedBufferByteLength]].
  71. auto const& buffer_byte_length = view_record.cached_buffer_byte_length;
  72. // 3. Assert: IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true if and only if bufferByteLength is detached.
  73. VERIFY(view.viewed_array_buffer()->is_detached() == buffer_byte_length.is_detached());
  74. // 4. If bufferByteLength is detached, return true.
  75. if (buffer_byte_length.is_detached())
  76. return true;
  77. // 5. Let byteOffsetStart be view.[[ByteOffset]].
  78. auto byte_offset_start = view.byte_offset();
  79. u32 byte_offset_end = 0;
  80. // 6. If view.[[ByteLength]] is auto, then
  81. if (view.byte_length().is_auto()) {
  82. // a. Let byteOffsetEnd be bufferByteLength.
  83. byte_offset_end = buffer_byte_length.length();
  84. }
  85. // 7. Else,
  86. else {
  87. // a. Let byteOffsetEnd be byteOffsetStart + view.[[ByteLength]].
  88. byte_offset_end = byte_offset_start + view.byte_length().length();
  89. }
  90. // 8. If byteOffsetStart > bufferByteLength or byteOffsetEnd > bufferByteLength, return true.
  91. if ((byte_offset_start > buffer_byte_length.length()) || (byte_offset_end > buffer_byte_length.length()))
  92. return true;
  93. // 9. NOTE: 0-length DataViews are not considered out-of-bounds.
  94. // 10. Return false.
  95. return false;
  96. }
  97. }