mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibWeb: Add and use a helper to reject a promise with an exception
This commit is contained in:
parent
24951a039e
commit
4bdb7dba8c
Notes:
sideshowbarker
2024-07-17 00:59:43 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/4bdb7dba8c Pull-request: https://github.com/SerenityOS/serenity/pull/23526 Reviewed-by: https://github.com/trflynn89 ✅
10 changed files with 42 additions and 52 deletions
|
@ -122,10 +122,8 @@ JS::NonnullGCPtr<JS::Promise> SubtleCrypto::digest(AlgorithmIdentifier const& al
|
|||
|
||||
// 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the digest() method.
|
||||
auto data_buffer_or_error = WebIDL::get_buffer_source_copy(*data->raw_object());
|
||||
if (data_buffer_or_error.is_error()) {
|
||||
auto promise = WebIDL::create_rejected_promise(realm, WebIDL::OperationError::create(realm, "Failed to copy bytes from ArrayBuffer"_fly_string));
|
||||
return verify_cast<JS::Promise>(*promise->promise());
|
||||
}
|
||||
if (data_buffer_or_error.is_error())
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, WebIDL::OperationError::create(realm, "Failed to copy bytes from ArrayBuffer"_fly_string));
|
||||
auto data_buffer = data_buffer_or_error.release_value();
|
||||
|
||||
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "digest".
|
||||
|
@ -133,10 +131,8 @@ JS::NonnullGCPtr<JS::Promise> SubtleCrypto::digest(AlgorithmIdentifier const& al
|
|||
|
||||
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
||||
// FIXME: Spec bug: link to https://webidl.spec.whatwg.org/#a-promise-rejected-with
|
||||
if (normalized_algorithm.is_error()) {
|
||||
auto promise = WebIDL::create_rejected_promise(realm, normalized_algorithm.release_error().release_value().value());
|
||||
return verify_cast<JS::Promise>(*promise->promise());
|
||||
}
|
||||
if (normalized_algorithm.is_error())
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, normalized_algorithm.release_error());
|
||||
|
||||
// 5. Let promise be a new Promise.
|
||||
auto promise = WebIDL::create_promise(realm);
|
||||
|
@ -219,10 +215,8 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Promise>> SubtleCrypto::import_key(Bi
|
|||
auto normalized_algorithm = normalize_an_algorithm(algorithm, "importKey"_string);
|
||||
|
||||
// 6. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
||||
if (normalized_algorithm.is_error()) {
|
||||
auto promise = WebIDL::create_rejected_promise(realm, normalized_algorithm.release_error().release_value().value());
|
||||
return verify_cast<JS::Promise>(*promise->promise());
|
||||
}
|
||||
if (normalized_algorithm.is_error())
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, normalized_algorithm.release_error());
|
||||
|
||||
// 7. Let promise be a new Promise.
|
||||
auto promise = WebIDL::create_promise(realm);
|
||||
|
|
|
@ -155,9 +155,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> consume_body(JS::Realm& realm
|
|||
{
|
||||
// 1. If object is unusable, then return a promise rejected with a TypeError.
|
||||
if (object.is_unusable()) {
|
||||
auto exception = JS::TypeError::create(realm, "Body is unusable"sv);
|
||||
auto promise_capability = WebIDL::create_rejected_promise(realm, exception);
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise().ptr()) };
|
||||
WebIDL::SimpleException exception { WebIDL::SimpleExceptionType::TypeError, "Body is unusable"sv };
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, move(exception));
|
||||
}
|
||||
|
||||
// 2. Let promise be a new promise.
|
||||
|
|
|
@ -367,11 +367,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> Blob::text()
|
|||
|
||||
// 2. Let reader be the result of getting a reader from stream. If that threw an exception, return a new promise rejected with that exception.
|
||||
auto reader_or_exception = acquire_readable_stream_default_reader(*stream);
|
||||
if (reader_or_exception.is_exception()) {
|
||||
auto throw_completion = Bindings::dom_exception_to_throw_completion(vm, reader_or_exception.exception());
|
||||
auto promise_capability = WebIDL::create_rejected_promise(realm, *throw_completion.value());
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise().ptr()) };
|
||||
}
|
||||
if (reader_or_exception.is_exception())
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, reader_or_exception.release_error());
|
||||
auto reader = reader_or_exception.release_value();
|
||||
|
||||
// 3. Let promise be the result of reading all bytes from stream with reader
|
||||
|
@ -393,18 +390,14 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> Blob::text()
|
|||
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> Blob::array_buffer()
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. Let stream be the result of calling get stream on this.
|
||||
auto stream = TRY(this->get_stream());
|
||||
|
||||
// 2. Let reader be the result of getting a reader from stream. If that threw an exception, return a new promise rejected with that exception.
|
||||
auto reader_or_exception = acquire_readable_stream_default_reader(*stream);
|
||||
if (reader_or_exception.is_exception()) {
|
||||
auto throw_completion = Bindings::dom_exception_to_throw_completion(vm, reader_or_exception.exception());
|
||||
auto promise_capability = WebIDL::create_rejected_promise(realm, *throw_completion.value());
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise().ptr()) };
|
||||
}
|
||||
if (reader_or_exception.is_exception())
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, reader_or_exception.release_error());
|
||||
auto reader = reader_or_exception.release_value();
|
||||
|
||||
// 3. Let promise be the result of reading all bytes from stream with reader.
|
||||
|
|
|
@ -340,10 +340,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> HTMLMediaElement::play()
|
|||
// 2. If the media element's error attribute is not null and its code is MEDIA_ERR_SRC_NOT_SUPPORTED, then return a promise
|
||||
// rejected with a "NotSupportedError" DOMException.
|
||||
if (m_error && m_error->code() == MediaError::Code::SrcNotSupported) {
|
||||
auto error = WebIDL::NotSupportedError::create(realm, m_error->message());
|
||||
auto promise = WebIDL::create_rejected_promise(realm, error);
|
||||
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise->promise()) };
|
||||
auto exception = WebIDL::NotSupportedError::create(realm, m_error->message());
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, move(exception));
|
||||
}
|
||||
|
||||
// 3. Let promise be a new promise and append promise to the list of pending play promises.
|
||||
|
|
|
@ -110,30 +110,26 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> ReadableStreamBYOBReader::rea
|
|||
|
||||
// 1. If view.[[ByteLength]] is 0, return a promise rejected with a TypeError exception.
|
||||
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()) };
|
||||
WebIDL::SimpleException exception { WebIDL::SimpleExceptionType::TypeError, "Cannot read in an empty buffer"sv };
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, move(exception));
|
||||
}
|
||||
|
||||
// 2. If view.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]] is 0, return a promise rejected with a TypeError exception.
|
||||
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()) };
|
||||
WebIDL::SimpleException exception { WebIDL::SimpleExceptionType::TypeError, "Cannot read in an empty buffer"sv };
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, move(exception));
|
||||
}
|
||||
|
||||
// 3. If ! IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true, return a promise rejected with a TypeError exception.
|
||||
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()) };
|
||||
WebIDL::SimpleException exception { WebIDL::SimpleExceptionType::TypeError, "Cannot read in a detached buffer"sv };
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, move(exception));
|
||||
}
|
||||
|
||||
// 4. If this.[[stream]] is undefined, return a promise rejected with a TypeError exception.
|
||||
if (!m_stream) {
|
||||
auto exception = JS::TypeError::create(realm, "Cannot read from an empty stream"sv);
|
||||
auto promise_capability = WebIDL::create_rejected_promise(realm, exception);
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise()) };
|
||||
WebIDL::SimpleException exception { WebIDL::SimpleExceptionType::TypeError, "Cannot read from an empty stream"sv };
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, move(exception));
|
||||
}
|
||||
|
||||
// 5. Let promise be a new promise.
|
||||
|
|
|
@ -158,9 +158,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> ReadableStreamDefaultReader::
|
|||
|
||||
// 1. If this.[[stream]] is undefined, return a promise rejected with a TypeError exception.
|
||||
if (!m_stream) {
|
||||
auto exception = JS::TypeError::create(realm, "Cannot read from an empty stream"sv);
|
||||
auto promise_capability = WebIDL::create_rejected_promise(realm, exception);
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise()) };
|
||||
WebIDL::SimpleException exception { WebIDL::SimpleExceptionType::TypeError, "Cannot read from an empty stream"sv };
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, move(exception));
|
||||
}
|
||||
|
||||
// 2. Let promise be a new promise.
|
||||
|
|
|
@ -26,9 +26,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> ReadableStreamGenericReaderMi
|
|||
{
|
||||
// 1. If this.[[stream]] is undefined, return a promise rejected with a TypeError exception.
|
||||
if (!m_stream) {
|
||||
auto exception = JS::TypeError::create(m_realm, "No stream present to cancel"sv);
|
||||
auto promise_capability = WebIDL::create_rejected_promise(m_realm, exception);
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise().ptr()) };
|
||||
WebIDL::SimpleException exception { WebIDL::SimpleExceptionType::TypeError, "No stream present to cancel"sv };
|
||||
return WebIDL::create_rejected_promise_from_exception(m_realm, move(exception));
|
||||
}
|
||||
|
||||
// 2. Return ! ReadableStreamReaderGenericCancel(this, reason).
|
||||
|
|
|
@ -32,6 +32,8 @@ struct SimpleException {
|
|||
Variant<String, StringView> message;
|
||||
};
|
||||
|
||||
using Exception = Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion>;
|
||||
|
||||
template<typename ValueType>
|
||||
class [[nodiscard]] ExceptionOr {
|
||||
public:
|
||||
|
@ -78,7 +80,7 @@ public:
|
|||
VERIFY(completion.is_error());
|
||||
}
|
||||
|
||||
ExceptionOr(Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> exception)
|
||||
ExceptionOr(Exception exception)
|
||||
: m_result_or_exception(move(exception))
|
||||
{
|
||||
if (auto* completion = m_result_or_exception.template get_pointer<JS::Completion>())
|
||||
|
@ -100,7 +102,7 @@ public:
|
|||
return move(m_result_or_exception.template get<ValueType>());
|
||||
}
|
||||
|
||||
Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> exception() const
|
||||
Exception exception() const
|
||||
{
|
||||
return m_result_or_exception.template downcast<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion>();
|
||||
}
|
||||
|
@ -118,7 +120,7 @@ public:
|
|||
|
||||
// These are for compatibility with the TRY() macro in AK.
|
||||
[[nodiscard]] bool is_error() const { return is_exception(); }
|
||||
Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> release_error() { return exception(); }
|
||||
Exception release_error() { return exception(); }
|
||||
|
||||
private:
|
||||
// https://webidl.spec.whatwg.org/#idl-exceptions
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||
#include <LibWeb/Bindings/HostDefined.h>
|
||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
#include <LibWeb/WebIDL/Promise.h>
|
||||
|
||||
namespace Web::WebIDL {
|
||||
|
@ -295,4 +294,11 @@ void wait_for_all(JS::Realm& realm, Vector<JS::NonnullGCPtr<Promise>> const& pro
|
|||
}
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<JS::Promise> create_rejected_promise_from_exception(JS::Realm& realm, Exception exception)
|
||||
{
|
||||
auto throw_completion = Bindings::dom_exception_to_throw_completion(realm.vm(), move(exception));
|
||||
auto promise_capability = WebIDL::create_rejected_promise(realm, *throw_completion.value());
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise_capability->promise().ptr()) };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <LibJS/Runtime/Value.h>
|
||||
#include <LibJS/SafeFunction.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
||||
namespace Web::WebIDL {
|
||||
|
||||
|
@ -31,4 +32,7 @@ JS::NonnullGCPtr<JS::Promise> upon_rejection(Promise const&, ReactionSteps);
|
|||
void mark_promise_as_handled(Promise const&);
|
||||
void wait_for_all(JS::Realm&, Vector<JS::NonnullGCPtr<Promise>> const& promises, Function<void(Vector<JS::Value> const&)> success_steps, Function<void(JS::Value)> failure_steps);
|
||||
|
||||
// Non-spec, convenience method.
|
||||
JS::NonnullGCPtr<JS::Promise> create_rejected_promise_from_exception(JS::Realm&, Exception);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue