فهرست منبع

LibWeb: Use ArrayBufferView for ReadableStreamBYOBReader

Which means that we now have support for DataViews.

Using the ArrayBufferView class also seems to make this read a whole
bunch nicer as well.
Shannon Booth 1 سال پیش
والد
کامیت
673329e1bd

+ 4 - 1
Tests/LibWeb/Text/expected/Streams/ReadableStreamBYOBReader-read.txt

@@ -1,3 +1,6 @@
-About to read! [object ReadableStreamBYOBReader]
+About to read into Uint8Array with [object ReadableStreamBYOBReader]
+Total bytes: 34
+'This is some data to be read! 🦬'
+About to read into DataView with [object ReadableStreamBYOBReader]
 Total bytes: 34
 'This is some data to be read! 🦬'

+ 9 - 4
Tests/LibWeb/Text/input/Streams/ReadableStreamBYOBReader-read.html

@@ -1,6 +1,6 @@
 <script src="../include.js"></script>
 <script>
- asyncTest(async done => {
+ async function testByobRead(type) {
     const array = ['This is some data to be read! 🦬'];
     let blob = new Blob(array);
 
@@ -11,15 +11,14 @@
     let bytesReceived = 0;
     let offset = 0;
 
-    println(`About to read! ${reader}`);
+    println(`About to read into ${type.prototype.constructor.name} with ${reader}`);
 
     while (true) {
-      let result = await reader.read(new Uint8Array(buffer, offset, buffer.byteLength - offset));
+      let result = await reader.read(new type(buffer, offset, buffer.byteLength - offset));
 
       if (result.done) {
         println(`Total bytes: ${bytesReceived}`);
         println(`'${new TextDecoder().decode(result.value.buffer.slice(0, bytesReceived))}'`);
-        done();
         return;
       }
 
@@ -27,5 +26,11 @@
       offset += result.value.byteLength;
       bytesReceived += result.value.byteLength;
     }
+  }
+
+  asyncTest(async done => {
+    await testByobRead(Uint8Array);
+    await testByobRead(DataView);
+    done();
   });
 </script>

+ 18 - 19
Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp

@@ -34,6 +34,7 @@
 #include <LibWeb/Streams/WritableStreamDefaultController.h>
 #include <LibWeb/Streams/WritableStreamDefaultWriter.h>
 #include <LibWeb/WebIDL/AbstractOperations.h>
+#include <LibWeb/WebIDL/Buffers.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 #include <LibWeb/WebIDL/Promise.h>
 
@@ -659,15 +660,11 @@ JS::Value readable_byte_stream_controller_convert_pull_into_descriptor(JS::Realm
 }
 
 // https://streams.spec.whatwg.org/#readable-byte-stream-controller-pull-into
-void readable_byte_stream_controller_pull_into(ReadableByteStreamController& controller, JS::Value view_value, ReadIntoRequest& read_into_request)
+void readable_byte_stream_controller_pull_into(ReadableByteStreamController& controller, WebIDL::ArrayBufferView& view, ReadIntoRequest& read_into_request)
 {
     auto& vm = controller.vm();
     auto& realm = controller.realm();
 
-    // FIXME: Support DataView
-    auto& view_object = view_value.as_object();
-    auto const& view = verify_cast<JS::TypedArrayBase>(view_object);
-
     // 1. Let stream be controller.[[stream]].
     auto stream = controller.stream();
 
@@ -678,32 +675,34 @@ void readable_byte_stream_controller_pull_into(ReadableByteStreamController& con
     JS::NativeFunction* ctor = realm.intrinsics().data_view_constructor();
 
     // 4. If view has a [[TypedArrayName]] internal slot (i.e., it is not a DataView),
-    if (!is<JS::DataView>(view_object)) {
+    if (view.bufferable_object().has<JS::NonnullGCPtr<JS::TypedArrayBase>>()) {
+        auto const& typed_array = view.bufferable_object().get<JS::NonnullGCPtr<JS::TypedArrayBase>>();
+
         // 1. Set elementSize to the element size specified in the typed array constructors table for view.[[TypedArrayName]].
-        element_size = view.element_size();
+        element_size = typed_array->element_size();
 
         // 2. Set ctor to the constructor specified in the typed array constructors table for view.[[TypedArrayName]].
-        if (is<JS::Int16Array>(view_object))
+        if (is<JS::Int16Array>(*typed_array))
             ctor = realm.intrinsics().int16_array_constructor();
-        else if (is<JS::Int32Array>(view_object))
+        else if (is<JS::Int32Array>(*typed_array))
             ctor = realm.intrinsics().int32_array_constructor();
-        else if (is<JS::Int8Array>(view_object))
+        else if (is<JS::Int8Array>(*typed_array))
             ctor = realm.intrinsics().int8_array_constructor();
-        else if (is<JS::Uint8Array>(view_object))
+        else if (is<JS::Uint8Array>(*typed_array))
             ctor = realm.intrinsics().uint8_array_constructor();
-        else if (is<JS::Uint16Array>(view_object))
+        else if (is<JS::Uint16Array>(*typed_array))
             ctor = realm.intrinsics().uint16_array_constructor();
-        else if (is<JS::Uint32Array>(view_object))
+        else if (is<JS::Uint32Array>(*typed_array))
             ctor = realm.intrinsics().uint32_array_constructor();
-        else if (is<JS::Uint8ClampedArray>(view_object))
+        else if (is<JS::Uint8ClampedArray>(*typed_array))
             ctor = realm.intrinsics().uint8_clamped_array_constructor();
-        else if (is<JS::BigInt64Array>(view_object))
+        else if (is<JS::BigInt64Array>(*typed_array))
             ctor = realm.intrinsics().big_int64_array_constructor();
-        else if (is<JS::BigUint64Array>(view_object))
+        else if (is<JS::BigUint64Array>(*typed_array))
             ctor = realm.intrinsics().big_uint64_array_constructor();
-        else if (is<JS::Float32Array>(view_object))
+        else if (is<JS::Float32Array>(*typed_array))
             ctor = realm.intrinsics().float32_array_constructor();
-        else if (is<JS::Float64Array>(view_object))
+        else if (is<JS::Float64Array>(*typed_array))
             ctor = realm.intrinsics().float64_array_constructor();
         else
             VERIFY_NOT_REACHED();
@@ -812,7 +811,7 @@ void readable_byte_stream_controller_pull_into(ReadableByteStreamController& con
 }
 
 // https://streams.spec.whatwg.org/#readable-stream-byob-reader-read
-void readable_stream_byob_reader_read(ReadableStreamBYOBReader& reader, JS::Value view, ReadIntoRequest& read_into_request)
+void readable_stream_byob_reader_read(ReadableStreamBYOBReader& reader, WebIDL::ArrayBufferView& view, ReadIntoRequest& read_into_request)
 {
     // 1. Let stream be reader.[[stream]].
     auto stream = reader.stream();

+ 2 - 2
Userland/Libraries/LibWeb/Streams/AbstractOperations.h

@@ -54,8 +54,8 @@ WebIDL::ExceptionOr<void> readable_stream_reader_generic_release(ReadableStreamG
 void readable_stream_default_reader_error_read_requests(ReadableStreamDefaultReader&, JS::Value error);
 void readable_stream_byob_reader_error_read_into_requests(ReadableStreamBYOBReader&, JS::Value error);
 JS::Value readable_byte_stream_controller_convert_pull_into_descriptor(JS::Realm&, PullIntoDescriptor const&);
-void readable_byte_stream_controller_pull_into(ReadableByteStreamController&, JS::Value view_value, ReadIntoRequest&);
-void readable_stream_byob_reader_read(ReadableStreamBYOBReader&, JS::Value view, ReadIntoRequest&);
+void readable_byte_stream_controller_pull_into(ReadableByteStreamController&, WebIDL::ArrayBufferView&, ReadIntoRequest&);
+void readable_stream_byob_reader_read(ReadableStreamBYOBReader&, WebIDL::ArrayBufferView&, ReadIntoRequest&);
 void readable_byte_stream_controller_fill_head_pull_into_descriptor(ReadableByteStreamController const&, u64 size, PullIntoDescriptor&);
 
 WebIDL::ExceptionOr<void> readable_stream_default_reader_read(ReadableStreamDefaultReader&, ReadRequest&);

+ 6 - 8
Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBReader.cpp

@@ -11,6 +11,7 @@
 #include <LibWeb/Streams/AbstractOperations.h>
 #include <LibWeb/Streams/ReadableStream.h>
 #include <LibWeb/Streams/ReadableStreamBYOBReader.h>
+#include <LibWeb/WebIDL/Buffers.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 
 namespace Web::Streams {
@@ -103,29 +104,26 @@ private:
 };
 
 // https://streams.spec.whatwg.org/#byob-reader-read
-WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> ReadableStreamBYOBReader::read(JS::Value view_value)
+WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> ReadableStreamBYOBReader::read(JS::Handle<WebIDL::ArrayBufferView>& view)
 {
     auto& realm = this->realm();
 
-    // FIXME: Support DataViews
-    auto& view = verify_cast<JS::TypedArrayBase>(view_value.as_object());
-
     // 1. If view.[[ByteLength]] is 0, return a promise rejected with a TypeError exception.
-    if (view.byte_length() == 0) {
+    if (view->byte_length() == 0) {
         auto exception = JS::TypeError::create(realm, "Cannot read in an empty buffer"sv);
         auto promise_capability = WebIDL::create_rejected_promise(realm, exception);
         return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise()) };
     }
 
     // 2. If view.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]] is 0, return a promise rejected with a TypeError exception.
-    if (view.viewed_array_buffer()->byte_length() == 0) {
+    if (view->viewed_array_buffer()->byte_length() == 0) {
         auto exception = JS::TypeError::create(realm, "Cannot read in an empty buffer"sv);
         auto promise_capability = WebIDL::create_rejected_promise(realm, exception);
         return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise()) };
     }
 
     // 3. If ! IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true, return a promise rejected with a TypeError exception.
-    if (view.viewed_array_buffer()->is_detached()) {
+    if (view->viewed_array_buffer()->is_detached()) {
         auto exception = JS::TypeError::create(realm, "Cannot read in a detached buffer"sv);
         auto promise_capability = WebIDL::create_rejected_promise(realm, exception);
         return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise()) };
@@ -151,7 +149,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> ReadableStreamBYOBReader::rea
     auto read_into_request = heap().allocate_without_realm<BYOBReaderReadIntoRequest>(realm, promise_capability);
 
     // 7. Perform ! ReadableStreamBYOBReaderRead(this, view, readIntoRequest).
-    readable_stream_byob_reader_read(*this, view_value, *read_into_request);
+    readable_stream_byob_reader_read(*this, *view, *read_into_request);
 
     // 8. Return promise.
     return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise()) };

+ 1 - 1
Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBReader.h

@@ -45,7 +45,7 @@ public:
 
     virtual ~ReadableStreamBYOBReader() override = default;
 
-    WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> read(JS::Value);
+    WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> read(JS::Handle<WebIDL::ArrayBufferView>&);
 
     void release_lock();
 

+ 1 - 2
Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBReader.idl

@@ -7,8 +7,7 @@
 interface ReadableStreamBYOBReader {
     constructor(ReadableStream stream);
 
-    // FIXME: This should accept an ArrayBufferView
-    Promise<ReadableStreamReadResult> read(any view);
+    Promise<ReadableStreamReadResult> read(ArrayBufferView view);
 
     undefined releaseLock();
 };