mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:54:58 +00:00

These instances were detected by searching for files that include AK/StdLibExtras.h, but don't match the regex: \\b(abs|AK_REPLACED_STD_NAMESPACE|array_size|ceil_div|clamp|exchange|for ward|is_constant_evaluated|is_power_of_two|max|min|mix|move|_RawPtr|RawP tr|round_up_to_power_of_two|swap|to_underlying)\\b (Without the linebreaks.) This regex is pessimistic, so there might be more files that don't actually use any "extra stdlib" functions. In theory, one might use LibCPP to detect things like this automatically, but let's do this one step after another.
113 lines
2.9 KiB
C++
113 lines
2.9 KiB
C++
/*
|
|
* Copyright (c) 2021-2022, the SerenityOS developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Optional.h>
|
|
#include <LibJS/Runtime/VM.h>
|
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
|
|
|
namespace Web::Bindings {
|
|
|
|
template<typename>
|
|
constexpr bool IsExceptionOr = false;
|
|
|
|
template<typename T>
|
|
constexpr bool IsExceptionOr<WebIDL::ExceptionOr<T>> = true;
|
|
|
|
template<typename>
|
|
constexpr bool IsThrowCompletionOr = false;
|
|
|
|
template<typename T>
|
|
constexpr bool IsThrowCompletionOr<JS::ThrowCompletionOr<T>> = true;
|
|
|
|
namespace Detail {
|
|
|
|
template<typename T>
|
|
struct ExtractExceptionOrValueType {
|
|
using Type = T;
|
|
};
|
|
|
|
template<typename T>
|
|
struct ExtractExceptionOrValueType<WebIDL::ExceptionOr<T>> {
|
|
using Type = T;
|
|
};
|
|
|
|
template<typename T>
|
|
struct ExtractExceptionOrValueType<JS::ThrowCompletionOr<T>> {
|
|
using Type = T;
|
|
};
|
|
|
|
template<>
|
|
struct ExtractExceptionOrValueType<void> {
|
|
using Type = JS::Value;
|
|
};
|
|
|
|
template<>
|
|
struct ExtractExceptionOrValueType<WebIDL::ExceptionOr<Empty>> {
|
|
using Type = JS::Value;
|
|
};
|
|
|
|
template<>
|
|
struct ExtractExceptionOrValueType<WebIDL::ExceptionOr<void>> {
|
|
using Type = JS::Value;
|
|
};
|
|
|
|
ALWAYS_INLINE JS::Completion dom_exception_to_throw_completion(JS::VM& vm, auto&& exception)
|
|
{
|
|
return exception.visit(
|
|
[&](WebIDL::SimpleException const& exception) {
|
|
switch (exception.type) {
|
|
#define E(x) \
|
|
case WebIDL::SimpleExceptionType::x: \
|
|
return vm.template throw_completion<JS::x>(exception.message);
|
|
|
|
ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E)
|
|
|
|
#undef E
|
|
default:
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
},
|
|
[&](JS::NonnullGCPtr<WebIDL::DOMException> const& exception) {
|
|
return throw_completion(exception);
|
|
},
|
|
[&](JS::Completion const& completion) {
|
|
return completion;
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
using ExtractExceptionOrValueType = typename Detail::ExtractExceptionOrValueType<T>::Type;
|
|
|
|
// Return type depends on the return type of 'fn' (when invoked with no args):
|
|
// void or ExceptionOr<void>: JS::ThrowCompletionOr<JS::Value>, always returns JS::js_undefined()
|
|
// ExceptionOr<T>: JS::ThrowCompletionOr<T>
|
|
// T: JS::ThrowCompletionOr<T>
|
|
template<typename F, typename T = decltype(declval<F>()()), typename Ret = Conditional<!IsExceptionOr<T> && !IsVoid<T> && !IsThrowCompletionOr<T>, T, ExtractExceptionOrValueType<T>>>
|
|
JS::ThrowCompletionOr<Ret> throw_dom_exception_if_needed(JS::VM& vm, F&& fn)
|
|
{
|
|
if constexpr (IsExceptionOr<T>) {
|
|
auto&& result = fn();
|
|
|
|
if (result.is_exception())
|
|
return Detail::dom_exception_to_throw_completion(vm, result.exception());
|
|
|
|
if constexpr (requires(T v) { v.value(); })
|
|
return result.value();
|
|
else
|
|
return JS::js_undefined();
|
|
} else if constexpr (IsVoid<T>) {
|
|
fn();
|
|
return JS::js_undefined();
|
|
} else {
|
|
return fn();
|
|
}
|
|
}
|
|
|
|
}
|