diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2021-04-13 23:48:25 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-13 22:31:06 +0200 |
commit | 8ba2b5f36f5420402b71d5eaf90aa2961a0705d2 (patch) | |
tree | cf75ad87d4b01436d62c0e85c6dd513b8582cd9a /Userland | |
parent | d5def1cad0f59d2fcf589312a77a347c1f5f63a5 (diff) | |
download | serenity-8ba2b5f36f5420402b71d5eaf90aa2961a0705d2.zip |
LibWeb: Make ExceptionOr work with non-JS::Value types
Fixes #6075.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/ExceptionOrUtils.h | 45 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp | 6 |
2 files changed, 43 insertions, 8 deletions
diff --git a/Userland/Libraries/LibWeb/Bindings/ExceptionOrUtils.h b/Userland/Libraries/LibWeb/Bindings/ExceptionOrUtils.h index 463e3bc495..081c04f21e 100644 --- a/Userland/Libraries/LibWeb/Bindings/ExceptionOrUtils.h +++ b/Userland/Libraries/LibWeb/Bindings/ExceptionOrUtils.h @@ -26,6 +26,7 @@ #pragma once +#include <AK/Optional.h> #include <AK/StdLibExtras.h> #include <LibJS/Runtime/VM.h> #include <LibWeb/Bindings/DOMExceptionWrapper.h> @@ -49,16 +50,48 @@ ALWAYS_INLINE bool throw_dom_exception(JS::VM& vm, JS::GlobalObject& global_obje return false; } -template<typename F, typename T = decltype(declval<F>()()), typename Ret = Conditional<!IsExceptionOr<T> && !IsVoid<T>, T, JS::Value>> -Ret throw_dom_exception_if_needed(auto&& vm, auto&& global_object, F&& fn) +namespace Detail { + +template<typename T> +struct ExtractExceptionOrValueType { + using Type = T; +}; + +template<typename T> +struct ExtractExceptionOrValueType<DOM::ExceptionOr<T>> { + using Type = T; +}; + +template<> +struct ExtractExceptionOrValueType<void> { + using Type = JS::Value; +}; + +template<> +struct ExtractExceptionOrValueType<DOM::ExceptionOr<void>> { + using Type = JS::Value; +}; + +} + +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>: Optional<JS::Value>, always returns JS::js_undefined() +// ExceptionOr<T>: Optional<T> +// T: Optional<T> +template<typename F, typename T = decltype(declval<F>()()), typename Ret = Conditional<!IsExceptionOr<T> && !IsVoid<T>, T, ExtractExceptionOrValueType<T>>> +Optional<Ret> throw_dom_exception_if_needed(auto&& vm, auto&& global_object, F&& fn) { if constexpr (IsExceptionOr<T>) { auto&& result = fn(); if (throw_dom_exception(vm, global_object, result)) - return JS::Value(); + return {}; if constexpr (requires(T v) { v.value(); }) return result.value(); - return JS::Value(); + else + return JS::js_undefined(); } else if constexpr (IsVoid<T>) { fn(); return JS::js_undefined(); @@ -68,10 +101,10 @@ Ret throw_dom_exception_if_needed(auto&& vm, auto&& global_object, F&& fn) } template<typename T> -bool should_return_empty(T&& value) +bool should_return_empty(const Optional<T>& value) { if constexpr (IsSame<JS::Value, T>) - return value.is_empty(); + return value.has_value() && value.value().is_empty(); return false; } diff --git a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index 611fe08135..555e0d4c58 100644 --- a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -1514,9 +1514,11 @@ JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@function.name:snakecase@) function_generator.set(".arguments", arguments_builder.string_view()); function_generator.append(R"~~~( - auto retval = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->@function.cpp_name@(@.arguments@); }); - if (should_return_empty(retval)) + auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->@function.cpp_name@(@.arguments@); }); + if (should_return_empty(result)) return JS::Value(); + + [[maybe_unused]] auto retval = result.release_value(); )~~~"); generate_return_statement(function.return_type); |