diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp index 14a47493944..08ad2bc4ac7 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp @@ -65,12 +65,13 @@ void ReadableStreamDefaultReader::visit_edges(Cell::Visitor& visitor) } // https://streams.spec.whatwg.org/#read-loop -ReadLoopReadRequest::ReadLoopReadRequest(JS::VM& vm, JS::Realm& realm, ReadableStreamDefaultReader& reader, SuccessSteps success_steps, FailureSteps failure_steps) +ReadLoopReadRequest::ReadLoopReadRequest(JS::VM& vm, JS::Realm& realm, ReadableStreamDefaultReader& reader, SuccessSteps success_steps, FailureSteps failure_steps, ChunkSteps chunk_steps) : m_vm(vm) , m_realm(realm) , m_reader(reader) , m_success_steps(move(success_steps)) , m_failure_steps(move(failure_steps)) + , m_chunk_steps(move(chunk_steps)) { } @@ -89,6 +90,11 @@ void ReadLoopReadRequest::on_chunk(JS::Value chunk) // 2. Append the bytes represented by chunk to bytes. m_byte_chunks.append(buffer); + if (m_chunk_steps) { + // FIXME: Can we move the buffer out of the `chunk`? Unclear if that is safe. + m_chunk_steps(MUST(ByteBuffer::copy(buffer))); + } + // FIXME: As the spec suggests, implement this non-recursively - instead of directly. It is not too big of a deal currently // as we enqueue the entire blob buffer in one go, meaning that we only recurse a single time. Once we begin queuing // up more than one chunk at a time, we may run into stack overflow problems. @@ -195,6 +201,22 @@ void ReadableStreamDefaultReader::read_all_bytes(ReadLoopReadRequest::SuccessSte readable_stream_default_reader_read(*this, read_request); } +void ReadableStreamDefaultReader::read_all_chunks(ReadLoopReadRequest::ChunkSteps chunk_steps, ReadLoopReadRequest::SuccessSteps success_steps, ReadLoopReadRequest::FailureSteps failure_steps) +{ + // AD-HOC: Some spec steps direct us to "read all chunks" from a stream, but there isn't an AO defined to do that. + // We implement those steps by using the "read all bytes" definition, with a custom callback to receive + // each chunk that is read. + auto& realm = this->realm(); + auto& vm = realm.vm(); + + // 1. Let readRequest be a new read request with the following items: + // NOTE: items and steps in ReadLoopReadRequest. + auto read_request = heap().allocate_without_realm(vm, realm, *this, move(success_steps), move(failure_steps), move(chunk_steps)); + + // 2. Perform ! ReadableStreamDefaultReaderRead(this, readRequest). + readable_stream_default_reader_read(*this, read_request); +} + // FIXME: This function is a promise-based wrapper around "read all bytes". The spec changed this function to not use promises // in https://github.com/whatwg/streams/commit/f894acdd417926a2121710803cef593e15127964 - however, it seems that the // FileAPI blob specification has not been updated to match, see: https://github.com/w3c/FileAPI/issues/187. diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h index 3bdddc1f15c..44c227d11f1 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h @@ -42,7 +42,10 @@ public: // failureSteps, which is an algorithm accepting a JavaScript value using FailureSteps = JS::SafeFunction; - ReadLoopReadRequest(JS::VM& vm, JS::Realm& realm, ReadableStreamDefaultReader& reader, SuccessSteps success_steps, FailureSteps failure_steps); + // AD-HOC: callback triggered on every chunk received from the stream. + using ChunkSteps = JS::SafeFunction; + + ReadLoopReadRequest(JS::VM& vm, JS::Realm& realm, ReadableStreamDefaultReader& reader, SuccessSteps success_steps, FailureSteps failure_steps, ChunkSteps chunk_steps = {}); virtual void on_chunk(JS::Value chunk) override; @@ -59,6 +62,7 @@ private: Vector m_byte_chunks; SuccessSteps m_success_steps; FailureSteps m_failure_steps; + ChunkSteps m_chunk_steps; }; // https://streams.spec.whatwg.org/#readablestreamdefaultreader @@ -76,6 +80,7 @@ public: JS::NonnullGCPtr read(); void read_all_bytes(ReadLoopReadRequest::SuccessSteps, ReadLoopReadRequest::FailureSteps); + void read_all_chunks(ReadLoopReadRequest::ChunkSteps, ReadLoopReadRequest::SuccessSteps, ReadLoopReadRequest::FailureSteps); JS::NonnullGCPtr read_all_bytes_deprecated(); void release_lock();