diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp index 167c3eb667..3d93baa7ae 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp @@ -1334,6 +1334,25 @@ WebIDL::ExceptionOr> writable_stream_default_w return writable_stream_close(*stream); } +// https://streams.spec.whatwg.org/#writable-stream-default-writer-ensure-closed-promise-rejected +void writable_stream_default_writer_ensure_closed_promise_rejected(WritableStreamDefaultWriter& writer, JS::Value error) +{ + auto& realm = writer.realm(); + + // 1. If writer.[[closedPromise]].[[PromiseState]] is "pending", reject writer.[[closedPromise]] with error. + auto& closed_promise = verify_cast(*writer.closed_promise()->promise()); + if (closed_promise.state() == JS::Promise::State::Pending) { + WebIDL::reject_promise(realm, *writer.closed_promise(), error); + } + // 2. Otherwise, set writer.[[closedPromise]] to a promise rejected with error. + else { + writer.set_closed_promise(WebIDL::create_rejected_promise(realm, error)); + } + + // 3. Set writer.[[closedPromise]].[[PromiseIsHandled]] to true. + WebIDL::mark_promise_as_handled(*writer.closed_promise()); +} + // https://streams.spec.whatwg.org/#writable-stream-default-writer-ensure-ready-promise-rejected void writable_stream_default_writer_ensure_ready_promise_rejected(WritableStreamDefaultWriter& writer, JS::Value error) { @@ -1374,6 +1393,36 @@ Optional writable_stream_default_writer_get_desired_size(WritableStreamD return writable_stream_default_controller_get_desired_size(*stream->controller()); } +// https://streams.spec.whatwg.org/#writable-stream-default-writer-release +WebIDL::ExceptionOr writable_stream_default_writer_release(WritableStreamDefaultWriter& writer) +{ + // 1. Let stream be writer.[[stream]]. + auto stream = writer.stream(); + + // 2. Assert: stream is not undefined. + VERIFY(stream); + + // 3. Assert: stream.[[writer]] is writer. + VERIFY(stream->writer().ptr() == &writer); + + // 4. Let releasedError be a new TypeError. + auto released_error = MUST_OR_THROW_OOM(JS::TypeError::create(writer.realm(), "Writer's stream lock has been released"sv)); + + // 5. Perform ! WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError). + writable_stream_default_writer_ensure_ready_promise_rejected(writer, released_error); + + // 6. Perform ! WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError). + writable_stream_default_writer_ensure_closed_promise_rejected(writer, released_error); + + // 7. Set stream.[[writer]] to undefined. + stream->set_writer({}); + + // 8. Set writer.[[stream]] to undefined. + writer.set_stream({}); + + return {}; +} + // https://streams.spec.whatwg.org/#writable-stream-default-controller-advance-queue-if-needed WebIDL::ExceptionOr writable_stream_default_controller_advance_queue_if_needed(WritableStreamDefaultController& controller) { diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h index a104192b6c..9e198f0751 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h @@ -75,8 +75,10 @@ void writable_stream_update_backpressure(WritableStream&, bool backpressure); WebIDL::ExceptionOr> writable_stream_default_writer_abort(WritableStreamDefaultWriter&, JS::Value reason); WebIDL::ExceptionOr> writable_stream_default_writer_close(WritableStreamDefaultWriter&); +void writable_stream_default_writer_ensure_closed_promise_rejected(WritableStreamDefaultWriter&, JS::Value error); void writable_stream_default_writer_ensure_ready_promise_rejected(WritableStreamDefaultWriter&, JS::Value error); Optional writable_stream_default_writer_get_desired_size(WritableStreamDefaultWriter const&); +WebIDL::ExceptionOr writable_stream_default_writer_release(WritableStreamDefaultWriter&); WebIDL::ExceptionOr writable_stream_default_controller_advance_queue_if_needed(WritableStreamDefaultController&); void writable_stream_default_controller_clear_algorithms(WritableStreamDefaultController&); diff --git a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.cpp b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.cpp index de9c927ad0..ae98f43037 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.cpp +++ b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.cpp @@ -87,6 +87,22 @@ WebIDL::ExceptionOr> WritableStreamDefaultWriter::close() return TRY(writable_stream_default_writer_close(*this))->promise(); } +// https://streams.spec.whatwg.org/#default-writer-release-lock +WebIDL::ExceptionOr WritableStreamDefaultWriter::release_lock() +{ + // 1. Let stream be this.[[stream]]. + + // 2. If stream is undefined, return. + if (!m_stream) + return {}; + + // 3. Assert: stream.[[writer]] is not undefined. + VERIFY(m_stream->writer()); + + // 4. Perform ! WritableStreamDefaultWriterRelease(this). + return writable_stream_default_writer_release(*this); +} + WritableStreamDefaultWriter::WritableStreamDefaultWriter(JS::Realm& realm) : Bindings::PlatformObject(realm) { diff --git a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.h b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.h index e66620fae6..dbd725051b 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.h +++ b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.h @@ -29,6 +29,7 @@ public: JS::GCPtr ready(); WebIDL::ExceptionOr> abort(JS::Value reason); WebIDL::ExceptionOr> close(); + WebIDL::ExceptionOr release_lock(); JS::GCPtr closed_promise() { return m_closed_promise; } void set_closed_promise(JS::GCPtr value) { m_closed_promise = value; } diff --git a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.idl b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.idl index f1976344d2..25092d4070 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.idl +++ b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultWriter.idl @@ -10,8 +10,8 @@ interface WritableStreamDefaultWriter { Promise abort(optional any reason); Promise close(); + undefined releaseLock(); // FIXME: - // undefined releaseLock(); // Promise write(optional any chunk); };