diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2023-04-02 08:27:37 -0700 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-04-09 21:45:39 +0200 |
commit | c421b6113c3f5e7cef3013e77a59da8db999f2c9 (patch) | |
tree | 0ec03e07ded02215f7ea4667dee66f315758570f /Userland | |
parent | ae2d67c28b2a598f7d487557e4194d62e625329a (diff) | |
download | serenity-c421b6113c3f5e7cef3013e77a59da8db999f2c9.zip |
LibWeb: Implement WritableStream.abort()
Diffstat (limited to 'Userland')
5 files changed, 72 insertions, 3 deletions
diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp index e9bd5bca9a..2fb167a3bc 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp @@ -8,6 +8,7 @@ #include <LibJS/Runtime/PromiseCapability.h> #include <LibJS/Runtime/PromiseConstructor.h> #include <LibWeb/Bindings/ExceptionOrUtils.h> +#include <LibWeb/DOM/AbortSignal.h> #include <LibWeb/Streams/AbstractOperations.h> #include <LibWeb/Streams/ReadableStream.h> #include <LibWeb/Streams/ReadableStreamDefaultController.h> @@ -839,6 +840,59 @@ WebIDL::ExceptionOr<void> set_up_writable_stream_default_writer(WritableStreamDe return {}; } +// https://streams.spec.whatwg.org/#writable-stream-abort +WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> writable_stream_abort(WritableStream& stream, JS::Value reason) +{ + auto& realm = stream.realm(); + + // 1. If stream.[[state]] is "closed" or "errored", return a promise resolved with undefined. + auto state = stream.state(); + if (state == WritableStream::State::Closed || state == WritableStream::State::Errored) + return WebIDL::create_resolved_promise(realm, JS::js_undefined()); + + // 2. Signal abort on stream.[[controller]].[[signal]] with reason. + stream.controller()->signal()->signal_abort(reason); + + // 3. Let state be stream.[[state]]. + state = stream.state(); + + // 4. If state is "closed" or "errored", return a promise resolved with undefined. + if (state == WritableStream::State::Closed || state == WritableStream::State::Errored) + return WebIDL::create_resolved_promise(realm, JS::js_undefined()); + + // 5. If stream.[[pendingAbortRequest]] is not undefined, return stream.[[pendingAbortRequest]]'s promise. + if (stream.pending_abort_request().has_value()) + return stream.pending_abort_request()->promise; + + // 6. Assert: state is "writable" or "erroring". + VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring); + + // 7. Let wasAlreadyErroring be false. + auto was_already_erroring = false; + + // 8. If state is "erroring", + if (state == WritableStream::State::Erroring) { + // 1. Set wasAlreadyErroring to true. + was_already_erroring = true; + + // 2. Set reason to undefined. + reason = JS::js_undefined(); + } + + // 9. Let promise be a new promise. + auto promise = WebIDL::create_promise(realm); + + // 10. Set stream.[[pendingAbortRequest]] to a new pending abort request whose promise is promise, reason is reason, and was already erroring is wasAlreadyErroring. + stream.set_pending_abort_request(PendingAbortRequest { promise, reason, was_already_erroring }); + + // 11. If wasAlreadyErroring is false, perform ! WritableStreamStartErroring(stream, reason). + if (!was_already_erroring) + TRY(writable_stream_start_erroring(stream, reason)); + + // 12. Return promise. + return promise; +} + // https://streams.spec.whatwg.org/#writable-stream-close WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> writable_stream_close(WritableStream& stream) { diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h index a1153d28c8..d9a97f65cc 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h @@ -56,6 +56,7 @@ WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underly WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStreamDefaultWriter>> acquire_writable_stream_default_writer(WritableStream&); bool is_writable_stream_locked(WritableStream const&); WebIDL::ExceptionOr<void> set_up_writable_stream_default_writer(WritableStreamDefaultWriter&, WritableStream&); +WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> writable_stream_abort(WritableStream&, JS::Value reason); WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> writable_stream_close(WritableStream&); bool writable_stream_close_queued_or_in_flight(WritableStream const&); diff --git a/Userland/Libraries/LibWeb/Streams/WritableStream.cpp b/Userland/Libraries/LibWeb/Streams/WritableStream.cpp index 342f5d6abf..54ab3dbcd3 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStream.cpp +++ b/Userland/Libraries/LibWeb/Streams/WritableStream.cpp @@ -76,6 +76,21 @@ WebIDL::ExceptionOr<JS::GCPtr<JS::Object>> WritableStream::close() return TRY(writable_stream_close(*this))->promise(); } +// https://streams.spec.whatwg.org/#ws-abort +WebIDL::ExceptionOr<JS::GCPtr<JS::Object>> WritableStream::abort(JS::Value reason) +{ + auto& realm = this->realm(); + + // 1. If ! IsWritableStreamLocked(this) is true, return a promise rejected with a TypeError exception. + if (is_writable_stream_locked(*this)) { + auto exception = MUST_OR_THROW_OOM(JS::TypeError::create(realm, "Cannot abort a locked stream"sv)); + return WebIDL::create_rejected_promise(realm, exception)->promise(); + } + + // 2. Return ! WritableStreamAbort(this, reason). + return TRY(writable_stream_abort(*this, reason))->promise(); +} + // https://streams.spec.whatwg.org/#ws-get-writer WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStreamDefaultWriter>> WritableStream::get_writer() { diff --git a/Userland/Libraries/LibWeb/Streams/WritableStream.h b/Userland/Libraries/LibWeb/Streams/WritableStream.h index 4f25672ffa..9e02e9a382 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStream.h +++ b/Userland/Libraries/LibWeb/Streams/WritableStream.h @@ -47,6 +47,7 @@ public: virtual ~WritableStream() = default; bool locked() const; + WebIDL::ExceptionOr<JS::GCPtr<JS::Object>> abort(JS::Value reason); WebIDL::ExceptionOr<JS::GCPtr<JS::Object>> close(); WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStreamDefaultWriter>> get_writer(); diff --git a/Userland/Libraries/LibWeb/Streams/WritableStream.idl b/Userland/Libraries/LibWeb/Streams/WritableStream.idl index 35bb0913a0..19977cfb85 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStream.idl +++ b/Userland/Libraries/LibWeb/Streams/WritableStream.idl @@ -7,9 +7,7 @@ interface WritableStream { readonly attribute boolean locked; - // FIXME: - // Promise<undefined> abort(optional any reason); - + Promise<undefined> abort(optional any reason); Promise<undefined> close(); WritableStreamDefaultWriter getWriter(); }; |