diff --git a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index ae90f88fee2..99bc6f24cb7 100644 --- a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -1091,6 +1091,7 @@ void generate_prototype_implementation(const IDL::Interface& interface) generator.append(R"~~~( #include +#include #include #include #include @@ -1100,6 +1101,7 @@ void generate_prototype_implementation(const IDL::Interface& interface) #include #include #include +#include #include #include #include @@ -1115,6 +1117,7 @@ void generate_prototype_implementation(const IDL::Interface& interface) #include #include #include +#include #include #include #include @@ -1407,6 +1410,55 @@ JS_DEFINE_NATIVE_SETTER(@prototype_class@::@attribute.setter_callback@) function_generator.set("function.name:snakecase", snake_name(function.name)); function_generator.append(R"~~~( +#ifndef EXCEPTION_OR_TEMPLATES +#define EXCEPTION_OR_TEMPLATES + +template +struct IsExceptionOr : AK::FalseType { +}; + +template +struct IsExceptionOr> : AK::TrueType { +}; + +template +ALWAYS_INLINE bool throw_dom_exception(JS::VM& vm, JS::GlobalObject& global_object, ExceptionOr& result) +{ + if (result.is_exception()) { + vm.throw_exception(global_object, DOMExceptionWrapper::create(global_object, const_cast(result.exception()))); + return true; + } + return false; +} + +template()()), typename Ret = typename Conditional::value && !IsVoid::value, T, JS::Value>::Type> +Ret throw_dom_exception_if_needed(auto&& vm, auto&& global_object, F&& fn) { + if constexpr (IsExceptionOr::value) { + auto&& result = fn(); + if (throw_dom_exception(vm, global_object, result)) + return JS::Value(); + if constexpr (requires(T v) { v.value(); }) + return result.value(); + return JS::Value(); + } else if constexpr (IsVoid::value) { + fn(); + return JS::js_undefined(); + } else { + return fn(); + } +} + +template +bool should_return_empty(T&& value) +{ + if constexpr (IsSame::value) + return value.is_empty(); + return false; +} + + +#endif + JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@function.name:snakecase@) { auto* impl = impl_from(vm, global_object); @@ -1420,15 +1472,11 @@ JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@function.name:snakecase@) generate_arguments(generator, function.parameters, arguments_builder); function_generator.set(".arguments", arguments_builder.string_view()); - if (function.return_type.name != "undefined") { - function_generator.append(R"~~~( - auto retval = impl->@function.name:snakecase@(@.arguments@); + function_generator.append(R"~~~( + auto retval = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->@function.name:snakecase@(@.arguments@); }); + if (should_return_empty(retval)) + return JS::Value(); )~~~"); - } else { - function_generator.append(R"~~~( - impl->@function.name:snakecase@(@.arguments@); -)~~~"); - } generate_return_statement(function.return_type);