Bläddra i källkod

LibWeb: Convert all generated bindings to ThrowCompletionOr

This also required converting URLSearchParams::for_each and the callback
function it invokes to ThrowCompletionOr. With this, the ReturnType enum
used by WrapperGenerator is removed as all callers would be using
ReturnType::Completion.
Timothy Flynn 3 år sedan
förälder
incheckning
c19c306744

+ 115 - 217
Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp

@@ -940,14 +940,8 @@ static bool is_wrappable_type(IDL::Type const& type)
     return false;
     return false;
 }
 }
 
 
-enum class ReturnType {
-    Completion,
-    Value,
-    Void,
-};
-
 template<typename ParameterType>
 template<typename ParameterType>
-static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter, String const& js_name, String const& js_suffix, String const& cpp_name, HashMap<String, IDL::Dictionary> const& dictionaries, ReturnType return_type, bool legacy_null_to_empty_string = false, bool optional = false, Optional<String> optional_default_value = {}, bool variadic = false)
+static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter, String const& js_name, String const& js_suffix, String const& cpp_name, HashMap<String, IDL::Dictionary> const& dictionaries, bool legacy_null_to_empty_string = false, bool optional = false, Optional<String> optional_default_value = {}, bool variadic = false)
 {
 {
     auto scoped_generator = generator.fork();
     auto scoped_generator = generator.fork();
     scoped_generator.set("cpp_name", make_input_acceptable_cpp(cpp_name));
     scoped_generator.set("cpp_name", make_input_acceptable_cpp(cpp_name));
@@ -963,22 +957,6 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
     if (optional_default_value.has_value())
     if (optional_default_value.has_value())
         scoped_generator.set("parameter.optional_default_value", *optional_default_value);
         scoped_generator.set("parameter.optional_default_value", *optional_default_value);
 
 
-    switch (return_type) {
-    case ReturnType::Completion:
-        scoped_generator.set("return_statement", "return JS::throw_completion(vm.exception()->value());");
-        scoped_generator.set("try_macro", "TRY");
-        break;
-    case ReturnType::Value:
-        scoped_generator.set("return_statement", "return {};");
-        scoped_generator.set("try_macro", "TRY_OR_DISCARD");
-        break;
-    case ReturnType::Void:
-        scoped_generator.set("return_statement", "return;");
-        break;
-    default:
-        VERIFY_NOT_REACHED();
-    }
-
     // FIXME: Add support for optional, variadic, nullable and default values to all types
     // FIXME: Add support for optional, variadic, nullable and default values to all types
     if (parameter.type->is_string()) {
     if (parameter.type->is_string()) {
         if (variadic) {
         if (variadic) {
@@ -987,48 +965,34 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
     @cpp_name@.ensure_capacity(vm.argument_count() - @js_suffix@);
     @cpp_name@.ensure_capacity(vm.argument_count() - @js_suffix@);
 
 
     for (size_t i = @js_suffix@; i < vm.argument_count(); ++i) {
     for (size_t i = @js_suffix@; i < vm.argument_count(); ++i) {
-        auto to_string_result = vm.argument(i).to_string(global_object);
-        if (to_string_result.is_error())
-            @return_statement@
-        @cpp_name@.append(to_string_result.release_value());
+        auto to_string_result = TRY(vm.argument(i).to_string(global_object));
+        @cpp_name@.append(move(to_string_result));
     }
     }
 )~~~");
 )~~~");
         } else if (!optional) {
         } else if (!optional) {
             if (!parameter.type->nullable) {
             if (!parameter.type->nullable) {
                 scoped_generator.append(R"~~~(
                 scoped_generator.append(R"~~~(
     String @cpp_name@;
     String @cpp_name@;
-    if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@) {
+    if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@)
         @cpp_name@ = String::empty();
         @cpp_name@ = String::empty();
-    } else {
-        auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
-        if (to_string_result.is_error())
-            @return_statement@
-        @cpp_name@ = to_string_result.release_value();
-    }
+    else
+        @cpp_name@ = TRY(@js_name@@js_suffix@.to_string(global_object));
 )~~~");
 )~~~");
             } else {
             } else {
                 scoped_generator.append(R"~~~(
                 scoped_generator.append(R"~~~(
     String @cpp_name@;
     String @cpp_name@;
-    if (!@js_name@@js_suffix@.is_nullish()) {
-        auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
-        if (to_string_result.is_error())
-            @return_statement@
-        @cpp_name@ = to_string_result.release_value();
-    }
+    if (!@js_name@@js_suffix@.is_nullish())
+        @cpp_name@ = TRY(@js_name@@js_suffix@.to_string(global_object));
 )~~~");
 )~~~");
             }
             }
         } else {
         } else {
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
     String @cpp_name@;
     String @cpp_name@;
     if (!@js_name@@js_suffix@.is_undefined()) {
     if (!@js_name@@js_suffix@.is_undefined()) {
-        if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@) {
+        if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@)
             @cpp_name@ = String::empty();
             @cpp_name@ = String::empty();
-        } else {
-            auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
-            if (to_string_result.is_error())
-                @return_statement@
-            @cpp_name@ = to_string_result.release_value();
-        }
+        else
+            @cpp_name@ = TRY(@js_name@@js_suffix@.to_string(global_object));
     })~~~");
     })~~~");
             if (optional_default_value.has_value() && (!parameter.type->nullable || optional_default_value.value() != "null")) {
             if (optional_default_value.has_value() && (!parameter.type->nullable || optional_default_value.value() != "null")) {
                 scoped_generator.append(R"~~~( else {
                 scoped_generator.append(R"~~~( else {
@@ -1045,34 +1009,27 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
     RefPtr<EventListener> @cpp_name@;
     RefPtr<EventListener> @cpp_name@;
     if (!@js_name@@js_suffix@.is_nullish()) {
     if (!@js_name@@js_suffix@.is_nullish()) {
-        if (!@js_name@@js_suffix@.is_function()) {
-            vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Function");
-            @return_statement@
-        }
+        if (!@js_name@@js_suffix@.is_function())
+            return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Function");
+
         @cpp_name@ = adopt_ref(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function())));
         @cpp_name@ = adopt_ref(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function())));
     }
     }
 )~~~");
 )~~~");
         } else {
         } else {
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
-    if (!@js_name@@js_suffix@.is_function()) {
-        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Function");
-        @return_statement@
-    }
+    if (!@js_name@@js_suffix@.is_function())
+        return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Function");
+
     auto @cpp_name@ = adopt_ref(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function())));
     auto @cpp_name@ = adopt_ref(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function())));
 )~~~");
 )~~~");
         }
         }
     } else if (is_wrappable_type(*parameter.type)) {
     } else if (is_wrappable_type(*parameter.type)) {
         if (!parameter.type->nullable) {
         if (!parameter.type->nullable) {
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
-    auto @cpp_name@_object_or_error = @js_name@@js_suffix@.to_object(global_object);
-    if (@cpp_name@_object_or_error.is_error())
-        @return_statement@
-    auto @cpp_name@_object = @cpp_name@_object_or_error.release_value();
+    auto @cpp_name@_object = TRY(@js_name@@js_suffix@.to_object(global_object));
 
 
-    if (!is<@wrapper_name@>(@cpp_name@_object)) {
-        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
-        @return_statement@
-    }
+    if (!is<@wrapper_name@>(@cpp_name@_object))
+        return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
 
 
     auto& @cpp_name@ = static_cast<@wrapper_name@*>(@cpp_name@_object)->impl();
     auto& @cpp_name@ = static_cast<@wrapper_name@*>(@cpp_name@_object)->impl();
 )~~~");
 )~~~");
@@ -1080,15 +1037,10 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
     @parameter.type.name@* @cpp_name@ = nullptr;
     @parameter.type.name@* @cpp_name@ = nullptr;
     if (!@js_name@@js_suffix@.is_nullish()) {
     if (!@js_name@@js_suffix@.is_nullish()) {
-        auto @cpp_name@_object_or_error = @js_name@@js_suffix@.to_object(global_object);
-        if (@cpp_name@_object_or_error.is_error())
-            @return_statement@
-        auto @cpp_name@_object = @cpp_name@_object_or_error.release_value();
-
-        if (!is<@wrapper_name@>(@cpp_name@_object)) {
-            vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
-            @return_statement@
-        }
+        auto @cpp_name@_object = TRY(@js_name@@js_suffix@.to_object(global_object));
+
+        if (!is<@wrapper_name@>(@cpp_name@_object))
+            return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
 
 
         @cpp_name@ = &static_cast<@wrapper_name@*>(@cpp_name@_object)->impl();
         @cpp_name@ = &static_cast<@wrapper_name@*>(@cpp_name@_object)->impl();
     }
     }
@@ -1097,7 +1049,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
     } else if (parameter.type->name == "double") {
     } else if (parameter.type->name == "double") {
         if (!optional) {
         if (!optional) {
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
-    double @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_double(global_object));
+    double @cpp_name@ = TRY(@js_name@@js_suffix@.to_double(global_object));
 )~~~");
 )~~~");
         } else {
         } else {
             if (optional_default_value.has_value()) {
             if (optional_default_value.has_value()) {
@@ -1111,7 +1063,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
             }
             }
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
     if (!@js_name@@js_suffix@.is_undefined())
     if (!@js_name@@js_suffix@.is_undefined())
-        @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_double(global_object));
+        @cpp_name@ = TRY(@js_name@@js_suffix@.to_double(global_object));
 )~~~");
 )~~~");
             if (optional_default_value.has_value()) {
             if (optional_default_value.has_value()) {
                 scoped_generator.append(R"~~~(
                 scoped_generator.append(R"~~~(
@@ -1153,15 +1105,15 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
         }
         }
     } else if (parameter.type->name == "unsigned long") {
     } else if (parameter.type->name == "unsigned long") {
         scoped_generator.append(R"~~~(
         scoped_generator.append(R"~~~(
-    auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_u32(global_object));
+    auto @cpp_name@ = TRY(@js_name@@js_suffix@.to_u32(global_object));
 )~~~");
 )~~~");
     } else if (parameter.type->name == "unsigned short") {
     } else if (parameter.type->name == "unsigned short") {
         scoped_generator.append(R"~~~(
         scoped_generator.append(R"~~~(
-    auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_u16(global_object));
+    auto @cpp_name@ = TRY(@js_name@@js_suffix@.to_u16(global_object));
 )~~~");
 )~~~");
     } else if (parameter.type->name == "long") {
     } else if (parameter.type->name == "long") {
         scoped_generator.append(R"~~~(
         scoped_generator.append(R"~~~(
-    auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_i32(global_object));
+    auto @cpp_name@ = TRY(@js_name@@js_suffix@.to_i32(global_object));
 )~~~");
 )~~~");
     } else if (parameter.type->name == "EventHandler") {
     } else if (parameter.type->name == "EventHandler") {
         // x.onfoo = function() { ... }
         // x.onfoo = function() { ... }
@@ -1219,10 +1171,9 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
             TODO();
             TODO();
         auto dictionary_generator = scoped_generator.fork();
         auto dictionary_generator = scoped_generator.fork();
         dictionary_generator.append(R"~~~(
         dictionary_generator.append(R"~~~(
-    if (!@js_name@@js_suffix@.is_nullish() && !@js_name@@js_suffix@.is_object()) {
-        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
-        @return_statement@
-    }
+    if (!@js_name@@js_suffix@.is_nullish() && !@js_name@@js_suffix@.is_object())
+        return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
+
     @parameter.type.name@ @cpp_name@ {};
     @parameter.type.name@ @cpp_name@ {};
 )~~~");
 )~~~");
         auto* current_dictionary = &dictionaries.find(parameter.type->name)->value;
         auto* current_dictionary = &dictionaries.find(parameter.type->name)->value;
@@ -1236,24 +1187,19 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
     if (@js_name@@js_suffix@.is_nullish()) {
     if (@js_name@@js_suffix@.is_nullish()) {
         @member_name@ = JS::js_undefined();
         @member_name@ = JS::js_undefined();
     } else {
     } else {
-        auto @member_name@_or_error = @js_name@@js_suffix@.as_object().get("@member_key@");
-        if (@member_name@_or_error.is_error())
-            @return_statement@
-        @member_name@ = @member_name@_or_error.release_value();
+        @member_name@ = TRY(@js_name@@js_suffix@.as_object().get("@member_key@"));
     }
     }
 )~~~");
 )~~~");
                 if (member.required) {
                 if (member.required) {
                     dictionary_generator.append(R"~~~(
                     dictionary_generator.append(R"~~~(
-    if (@member_name@.is_undefined()) {
-        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::MissingRequiredProperty, "@member_key@");
-        @return_statement@
-    }
+    if (@member_name@.is_undefined())
+        return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::MissingRequiredProperty, "@member_key@");
 )~~~");
 )~~~");
                 }
                 }
 
 
                 auto member_value_name = String::formatted("{}_value", member_js_name);
                 auto member_value_name = String::formatted("{}_value", member_js_name);
                 dictionary_generator.set("member_value_name", member_value_name);
                 dictionary_generator.set("member_value_name", member_value_name);
-                generate_to_cpp(dictionary_generator, member, member_js_name, "", member_value_name, dictionaries, return_type, member.extended_attributes.contains("LegacyNullToEmptyString"), !member.required, member.default_value);
+                generate_to_cpp(dictionary_generator, member, member_js_name, "", member_value_name, dictionaries, member.extended_attributes.contains("LegacyNullToEmptyString"), !member.required, member.default_value);
                 dictionary_generator.append(R"~~~(
                 dictionary_generator.append(R"~~~(
     @cpp_name@.@member_name@ = @member_value_name@;
     @cpp_name@.@member_name@ = @member_value_name@;
 )~~~");
 )~~~");
@@ -1270,7 +1216,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
 }
 }
 
 
 template<typename FunctionType>
 template<typename FunctionType>
-static void generate_argument_count_check(SourceGenerator& generator, FunctionType& function, ReturnType return_type)
+static void generate_argument_count_check(SourceGenerator& generator, FunctionType& function)
 {
 {
     auto argument_count_check_generator = generator.fork();
     auto argument_count_check_generator = generator.fork();
     argument_count_check_generator.set("function.name", function.name);
     argument_count_check_generator.set("function.name", function.name);
@@ -1286,27 +1232,13 @@ static void generate_argument_count_check(SourceGenerator& generator, FunctionTy
         argument_count_check_generator.set(".arg_count_suffix", String::formatted(", \"{}\"", function.length()));
         argument_count_check_generator.set(".arg_count_suffix", String::formatted(", \"{}\"", function.length()));
     }
     }
 
 
-    switch (return_type) {
-    case ReturnType::Completion:
-        argument_count_check_generator.set("return_statement", "return JS::throw_completion(vm.exception()->value());");
-        break;
-    case ReturnType::Value:
-        argument_count_check_generator.set("return_statement", "return {};");
-        break;
-    default:
-        // 'Void' not used here.
-        VERIFY_NOT_REACHED();
-    }
-
     argument_count_check_generator.append(R"~~~(
     argument_count_check_generator.append(R"~~~(
-    if (vm.argument_count() < @function.nargs@) {
-        vm.throw_exception<JS::TypeError>(global_object, @.bad_arg_count@, "@function.name@"@.arg_count_suffix@);
-        @return_statement@
-    }
+    if (vm.argument_count() < @function.nargs@)
+        return vm.throw_completion<JS::TypeError>(global_object, @.bad_arg_count@, "@function.name@"@.arg_count_suffix@);
 )~~~");
 )~~~");
 }
 }
 
 
-static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter> const& parameters, StringBuilder& arguments_builder, HashMap<String, IDL::Dictionary> const& dictionaries, ReturnType return_type)
+static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter> const& parameters, StringBuilder& arguments_builder, HashMap<String, IDL::Dictionary> const& dictionaries)
 {
 {
     auto arguments_generator = generator.fork();
     auto arguments_generator = generator.fork();
 
 
@@ -1323,7 +1255,7 @@ static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter
         }
         }
 
 
         bool legacy_null_to_empty_string = parameter.extended_attributes.contains("LegacyNullToEmptyString");
         bool legacy_null_to_empty_string = parameter.extended_attributes.contains("LegacyNullToEmptyString");
-        generate_to_cpp(generator, parameter, "arg", String::number(argument_index), parameter.name.to_snakecase(), dictionaries, return_type, legacy_null_to_empty_string, parameter.optional, parameter.optional_default_value, parameter.variadic);
+        generate_to_cpp(generator, parameter, "arg", String::number(argument_index), parameter.name.to_snakecase(), dictionaries, legacy_null_to_empty_string, parameter.optional, parameter.optional_default_value, parameter.variadic);
         ++argument_index;
         ++argument_index;
     }
     }
 
 
@@ -1464,22 +1396,20 @@ static void generate_function(SourceGenerator& generator, IDL::Function const& f
     }
     }
 
 
     function_generator.append(R"~~~(
     function_generator.append(R"~~~(
-JS_DEFINE_OLD_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@)
+JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@)
 {
 {
 )~~~");
 )~~~");
 
 
     if (is_static_function == StaticFunction::No) {
     if (is_static_function == StaticFunction::No) {
         function_generator.append(R"~~~(
         function_generator.append(R"~~~(
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 )~~~");
 )~~~");
     }
     }
 
 
-    generate_argument_count_check(generator, function, ReturnType::Value);
+    generate_argument_count_check(generator, function);
 
 
     StringBuilder arguments_builder;
     StringBuilder arguments_builder;
-    generate_arguments(generator, function.parameters, arguments_builder, dictionaries, ReturnType::Value);
+    generate_arguments(generator, function.parameters, arguments_builder, dictionaries);
     function_generator.set(".arguments", arguments_builder.string_view());
     function_generator.set(".arguments", arguments_builder.string_view());
 
 
     if (is_static_function == StaticFunction::No) {
     if (is_static_function == StaticFunction::No) {
@@ -1494,7 +1424,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@)
 
 
     function_generator.append(R"~~~(
     function_generator.append(R"~~~(
     if (should_return_empty(result))
     if (should_return_empty(result))
-        return JS::Value();
+        return JS::throw_completion(vm.exception()->value());
 
 
     [[maybe_unused]] auto retval = result.release_value();
     [[maybe_unused]] auto retval = result.release_value();
 )~~~");
 )~~~");
@@ -2053,7 +1983,7 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
             // FIXME: It's not necessary to determine "creating" if the named property setter specifies an identifier.
             // FIXME: It's not necessary to determine "creating" if the named property setter specifies an identifier.
             //        Try avoiding it somehow, e.g. by enforcing supported_property_names doesn't have side effects so it can be skipped.
             //        Try avoiding it somehow, e.g. by enforcing supported_property_names doesn't have side effects so it can be skipped.
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
-static void invoke_named_property_setter(JS::GlobalObject& global_object, @fully_qualified_name@& impl, String const& property_name, JS::Value value)
+static JS::ThrowCompletionOr<void> invoke_named_property_setter(JS::GlobalObject& global_object, @fully_qualified_name@& impl, String const& property_name, JS::Value value)
 {
 {
     auto& vm = global_object.vm();
     auto& vm = global_object.vm();
 
 
@@ -2068,7 +1998,7 @@ static void invoke_named_property_setter(JS::GlobalObject& global_object, @fully
 
 
             // 4. Let value be the result of converting V to an IDL value of type T.
             // 4. Let value be the result of converting V to an IDL value of type T.
             // NOTE: This takes the last parameter as it's enforced that there's only two parameters.
             // NOTE: This takes the last parameter as it's enforced that there's only two parameters.
-            generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, ReturnType::Void);
+            generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries);
 
 
             // 5. If operation was defined without an identifier, then:
             // 5. If operation was defined without an identifier, then:
             if (interface.named_property_setter->name.is_empty()) {
             if (interface.named_property_setter->name.is_empty()) {
@@ -2077,12 +2007,12 @@ static void invoke_named_property_setter(JS::GlobalObject& global_object, @fully
         // 5.1. If creating is true, then perform the steps listed in the interface description to set the value of a new named property with P as the name and value as the value.
         // 5.1. If creating is true, then perform the steps listed in the interface description to set the value of a new named property with P as the name and value as the value.
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_new_named_property(property_name, converted_value); });
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_new_named_property(property_name, converted_value); });
         if (should_return_empty(result))
         if (should_return_empty(result))
-            return;
+            return JS::throw_completion(vm.exception()->value());
     } else {
     } else {
         // 5.2 Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing named property with P as the name and value as the value.
         // 5.2 Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing named property with P as the name and value as the value.
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_existing_named_property(property_name, converted_value); });
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_existing_named_property(property_name, converted_value); });
         if (should_return_empty(result))
         if (should_return_empty(result))
-            return;
+            return JS::throw_completion(vm.exception()->value());
     }
     }
 )~~~");
 )~~~");
             } else {
             } else {
@@ -2094,11 +2024,12 @@ static void invoke_named_property_setter(JS::GlobalObject& global_object, @fully
                 function_scoped_generator.append(R"~~~(
                 function_scoped_generator.append(R"~~~(
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.@function.cpp_name@(property_name, converted_value); });
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.@function.cpp_name@(property_name, converted_value); });
     if (should_return_empty(result))
     if (should_return_empty(result))
-        return;
+        return JS::throw_completion(vm.exception()->value());
 )~~~");
 )~~~");
             }
             }
 
 
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
+    return {};
 }
 }
 )~~~");
 )~~~");
         }
         }
@@ -2109,7 +2040,7 @@ static void invoke_named_property_setter(JS::GlobalObject& global_object, @fully
             // FIXME: It's not necessary to determine "creating" if the indexed property setter specifies an identifier.
             // FIXME: It's not necessary to determine "creating" if the indexed property setter specifies an identifier.
             //        Try avoiding it somehow, e.g. by enforcing supported_property_indices doesn't have side effects so it can be skipped.
             //        Try avoiding it somehow, e.g. by enforcing supported_property_indices doesn't have side effects so it can be skipped.
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
-static void invoke_indexed_property_setter(JS::GlobalObject& global_object, @fully_qualified_name@& impl, JS::PropertyKey const& property_name, JS::Value value)
+static JS::ThrowCompletionOr<void> invoke_indexed_property_setter(JS::GlobalObject& global_object, @fully_qualified_name@& impl, JS::PropertyKey const& property_name, JS::Value value)
 {
 {
     auto& vm = global_object.vm();
     auto& vm = global_object.vm();
 
 
@@ -2126,7 +2057,7 @@ static void invoke_indexed_property_setter(JS::GlobalObject& global_object, @ful
 
 
             // 5. Let value be the result of converting V to an IDL value of type T.
             // 5. Let value be the result of converting V to an IDL value of type T.
             // NOTE: This takes the last parameter as it's enforced that there's only two parameters.
             // NOTE: This takes the last parameter as it's enforced that there's only two parameters.
-            generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, ReturnType::Void);
+            generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries);
 
 
             // 6. If operation was defined without an identifier, then:
             // 6. If operation was defined without an identifier, then:
             if (interface.indexed_property_setter->name.is_empty()) {
             if (interface.indexed_property_setter->name.is_empty()) {
@@ -2135,12 +2066,12 @@ static void invoke_indexed_property_setter(JS::GlobalObject& global_object, @ful
         // 6.1 If creating is true, then perform the steps listed in the interface description to set the value of a new indexed property with index as the index and value as the value.
         // 6.1 If creating is true, then perform the steps listed in the interface description to set the value of a new indexed property with index as the index and value as the value.
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_new_indexed_property(index, converted_value); });
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_new_indexed_property(index, converted_value); });
         if (should_return_empty(result))
         if (should_return_empty(result))
-            return;
+            return JS::throw_completion(vm.exception()->value());
     } else {
     } else {
         // 6.2 Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing indexed property with index as the index and value as the value.
         // 6.2 Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing indexed property with index as the index and value as the value.
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_existing_indexed_property(index, converted_value); });
         auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.set_value_of_existing_indexed_property(index, converted_value); });
         if (should_return_empty(result))
         if (should_return_empty(result))
-            return;
+            return JS::throw_completion(vm.exception()->value());
     }
     }
 )~~~");
 )~~~");
             } else {
             } else {
@@ -2152,7 +2083,7 @@ static void invoke_indexed_property_setter(JS::GlobalObject& global_object, @ful
                 function_scoped_generator.append(R"~~~(
                 function_scoped_generator.append(R"~~~(
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.@function.cpp_name@(index, converted_value); });
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { impl.@function.cpp_name@(index, converted_value); });
     if (should_return_empty(result))
     if (should_return_empty(result))
-        return;
+        return JS::throw_completion(vm.exception()->value());
 )~~~");
 )~~~");
             }
             }
 
 
@@ -2193,9 +2124,7 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_set(JS::PropertyKey const& pr
                 scoped_generator.append(R"~~~(
                 scoped_generator.append(R"~~~(
         if (IDL::is_an_array_index(global_object, property_name)) {
         if (IDL::is_an_array_index(global_object, property_name)) {
             // 1. Invoke the indexed property setter on O with P and V.
             // 1. Invoke the indexed property setter on O with P and V.
-            invoke_indexed_property_setter(global_object, impl(), property_name, value);
-            if (auto* exception = vm.exception())
-                return JS::throw_completion(exception->value());
+            TRY(invoke_indexed_property_setter(global_object, impl(), property_name, value));
 
 
             // 2. Return true.
             // 2. Return true.
             return true;
             return true;
@@ -2209,9 +2138,7 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_set(JS::PropertyKey const& pr
                 scoped_generator.append(R"~~~(
                 scoped_generator.append(R"~~~(
         if (property_name.is_string()) {
         if (property_name.is_string()) {
             // 1. Invoke the named property setter on O with P and V.
             // 1. Invoke the named property setter on O with P and V.
-            invoke_named_property_setter(global_object, impl(), property_name.as_string(), value);
-            if (auto* exception = vm.exception())
-                return JS::throw_completion(exception->value());
+            TRY(invoke_named_property_setter(global_object, impl(), property_name.as_string(), value));
 
 
             // 2. Return true.
             // 2. Return true.
             return true;
             return true;
@@ -2263,9 +2190,7 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_define_own_property(JS::Prope
             } else {
             } else {
                 scoped_generator.append(R"~~~(
                 scoped_generator.append(R"~~~(
         // 3. Invoke the indexed property setter on O with P and Desc.[[Value]].
         // 3. Invoke the indexed property setter on O with P and Desc.[[Value]].
-        invoke_indexed_property_setter(global_object, impl(), property_name, *property_descriptor.value);
-        if (auto* exception = vm.exception())
-            return JS::throw_completion(exception->value());
+        TRY(invoke_indexed_property_setter(global_object, impl(), property_name, *property_descriptor.value));
 
 
         // 4. Return true.
         // 4. Return true.
         return true;
         return true;
@@ -2322,9 +2247,7 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_define_own_property(JS::Prope
                 return false;
                 return false;
 
 
             // 2. Invoke the named property setter on O with P and Desc.[[Value]].
             // 2. Invoke the named property setter on O with P and Desc.[[Value]].
-            invoke_named_property_setter(global_object, impl(), property_name_as_string, *property_descriptor.value);
-            if (auto* exception = vm.exception())
-                return JS::throw_completion(exception->value());
+            TRY(invoke_named_property_setter(global_object, impl(), property_name_as_string, *property_descriptor.value));
 
 
             // 3. Return true.
             // 3. Return true.
             return true;
             return true;
@@ -2580,7 +2503,7 @@ private:
         auto function_generator = generator.fork();
         auto function_generator = generator.fork();
         function_generator.set("function.name:snakecase", make_input_acceptable_cpp(function.name.to_snakecase()));
         function_generator.set("function.name:snakecase", make_input_acceptable_cpp(function.name.to_snakecase()));
         function_generator.append(R"~~~(
         function_generator.append(R"~~~(
-    JS_DECLARE_OLD_NATIVE_FUNCTION(@function.name:snakecase@);
+    JS_DECLARE_NATIVE_FUNCTION(@function.name:snakecase@);
 )~~~");
 )~~~");
     }
     }
 
 
@@ -2702,10 +2625,10 @@ JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject
 )~~~");
 )~~~");
 
 
         if (!constructor.parameters.is_empty()) {
         if (!constructor.parameters.is_empty()) {
-            generate_argument_count_check(generator, constructor, ReturnType::Completion);
+            generate_argument_count_check(generator, constructor);
 
 
             StringBuilder arguments_builder;
             StringBuilder arguments_builder;
-            generate_arguments(generator, constructor.parameters, arguments_builder, interface.dictionaries, ReturnType::Completion);
+            generate_arguments(generator, constructor.parameters, arguments_builder, interface.dictionaries);
             generator.set(".constructor_arguments", arguments_builder.string_view());
             generator.set(".constructor_arguments", arguments_builder.string_view());
 
 
             generator.append(R"~~~(
             generator.append(R"~~~(
@@ -2759,7 +2682,7 @@ define_direct_property("@constant.name@", JS::Value((i32)@constant.value@), JS::
         function_generator.set("function.length", String::number(function.length()));
         function_generator.set("function.length", String::number(function.length()));
 
 
         function_generator.append(R"~~~(
         function_generator.append(R"~~~(
-    define_old_native_function("@function.name@", @function.name:snakecase@, @function.length@, default_attributes);
+    define_native_function("@function.name@", @function.name:snakecase@, @function.length@, default_attributes);
 )~~~");
 )~~~");
     }
     }
 
 
@@ -2809,24 +2732,24 @@ private:
         auto function_generator = generator.fork();
         auto function_generator = generator.fork();
         function_generator.set("function.name:snakecase", make_input_acceptable_cpp(function.name.to_snakecase()));
         function_generator.set("function.name:snakecase", make_input_acceptable_cpp(function.name.to_snakecase()));
         function_generator.append(R"~~~(
         function_generator.append(R"~~~(
-    JS_DECLARE_OLD_NATIVE_FUNCTION(@function.name:snakecase@);
+    JS_DECLARE_NATIVE_FUNCTION(@function.name:snakecase@);
         )~~~");
         )~~~");
     }
     }
 
 
     if (interface.has_stringifier) {
     if (interface.has_stringifier) {
         auto stringifier_generator = generator.fork();
         auto stringifier_generator = generator.fork();
         stringifier_generator.append(R"~~~(
         stringifier_generator.append(R"~~~(
-    JS_DECLARE_OLD_NATIVE_FUNCTION(to_string);
+    JS_DECLARE_NATIVE_FUNCTION(to_string);
         )~~~");
         )~~~");
     }
     }
 
 
     if (interface.pair_iterator_types.has_value()) {
     if (interface.pair_iterator_types.has_value()) {
         auto iterator_generator = generator.fork();
         auto iterator_generator = generator.fork();
         iterator_generator.append(R"~~~(
         iterator_generator.append(R"~~~(
-    JS_DECLARE_OLD_NATIVE_FUNCTION(entries);
-    JS_DECLARE_OLD_NATIVE_FUNCTION(for_each);
-    JS_DECLARE_OLD_NATIVE_FUNCTION(keys);
-    JS_DECLARE_OLD_NATIVE_FUNCTION(values);
+    JS_DECLARE_NATIVE_FUNCTION(entries);
+    JS_DECLARE_NATIVE_FUNCTION(for_each);
+    JS_DECLARE_NATIVE_FUNCTION(keys);
+    JS_DECLARE_NATIVE_FUNCTION(values);
         )~~~");
         )~~~");
     }
     }
 
 
@@ -2834,12 +2757,12 @@ private:
         auto attribute_generator = generator.fork();
         auto attribute_generator = generator.fork();
         attribute_generator.set("attribute.name:snakecase", attribute.name.to_snakecase());
         attribute_generator.set("attribute.name:snakecase", attribute.name.to_snakecase());
         attribute_generator.append(R"~~~(
         attribute_generator.append(R"~~~(
-    JS_DECLARE_OLD_NATIVE_FUNCTION(@attribute.name:snakecase@_getter);
+    JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_getter);
 )~~~");
 )~~~");
 
 
         if (!attribute.readonly) {
         if (!attribute.readonly) {
             attribute_generator.append(R"~~~(
             attribute_generator.append(R"~~~(
-    JS_DECLARE_OLD_NATIVE_FUNCTION(@attribute.name:snakecase@_setter);
+    JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_setter);
 )~~~");
 )~~~");
         }
         }
     }
     }
@@ -3078,7 +3001,7 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
         }
         }
 
 
         attribute_generator.append(R"~~~(
         attribute_generator.append(R"~~~(
-    define_old_native_accessor("@attribute.name@", @attribute.getter_callback@, @attribute.setter_callback@, default_attributes);
+    define_native_accessor("@attribute.name@", @attribute.getter_callback@, @attribute.setter_callback@, default_attributes);
 )~~~");
 )~~~");
     }
     }
 
 
@@ -3109,7 +3032,7 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
         }
         }
 
 
         function_generator.append(R"~~~(
         function_generator.append(R"~~~(
-    define_old_native_function("@function.name@", @function.name:snakecase@, @function.length@, default_attributes);
+    define_native_function("@function.name@", @function.name:snakecase@, @function.length@, default_attributes);
 )~~~");
 )~~~");
     }
     }
 
 
@@ -3118,7 +3041,7 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
 
 
         auto stringifier_generator = generator.fork();
         auto stringifier_generator = generator.fork();
         stringifier_generator.append(R"~~~(
         stringifier_generator.append(R"~~~(
-    define_old_native_function("toString", to_string, 0, default_attributes);
+    define_native_function("toString", to_string, 0, default_attributes);
 )~~~");
 )~~~");
     }
     }
 
 
@@ -3145,10 +3068,10 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
 
 
         auto iterator_generator = generator.fork();
         auto iterator_generator = generator.fork();
         iterator_generator.append(R"~~~(
         iterator_generator.append(R"~~~(
-    define_old_native_function(vm.names.entries, entries, 0, default_attributes);
-    define_old_native_function(vm.names.forEach, for_each, 1, default_attributes);
-    define_old_native_function(vm.names.keys, keys, 0, default_attributes);
-    define_old_native_function(vm.names.values, values, 0, default_attributes);
+    define_native_function(vm.names.entries, entries, 0, default_attributes);
+    define_native_function(vm.names.forEach, for_each, 1, default_attributes);
+    define_native_function(vm.names.keys, keys, 0, default_attributes);
+    define_native_function(vm.names.values, values, 0, default_attributes);
 
 
     define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.entries), JS::Attribute::Configurable | JS::Attribute::Writable);
     define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.entries), JS::Attribute::Configurable | JS::Attribute::Writable);
 )~~~");
 )~~~");
@@ -3167,9 +3090,9 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
 
 
     if (!interface.attributes.is_empty() || !interface.functions.is_empty() || interface.has_stringifier) {
     if (!interface.attributes.is_empty() || !interface.functions.is_empty() || interface.has_stringifier) {
         generator.append(R"~~~(
         generator.append(R"~~~(
-static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_object)
+static JS::ThrowCompletionOr<@fully_qualified_name@*> impl_from(JS::VM& vm, JS::GlobalObject& global_object)
 {
 {
-    auto* this_object = TRY_OR_DISCARD(vm.this_value(global_object).to_object(global_object));
+    auto* this_object = TRY(vm.this_value(global_object).to_object(global_object));
 )~~~");
 )~~~");
 
 
         if (interface.name == "EventTarget") {
         if (interface.name == "EventTarget") {
@@ -3181,10 +3104,8 @@ static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_ob
         }
         }
 
 
         generator.append(R"~~~(
         generator.append(R"~~~(
-    if (!is<@wrapper_class@>(this_object)) {
-        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@fully_qualified_name@");
-        return nullptr;
-    }
+    if (!is<@wrapper_class@>(this_object))
+        return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@fully_qualified_name@");
 
 
     return &static_cast<@wrapper_class@*>(this_object)->impl();
     return &static_cast<@wrapper_class@*>(this_object)->impl();
 }
 }
@@ -3216,11 +3137,9 @@ static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_ob
         }
         }
 
 
         attribute_generator.append(R"~~~(
         attribute_generator.append(R"~~~(
-JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.getter_callback@)
+JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@attribute.getter_callback@)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 )~~~");
 )~~~");
 
 
         if (attribute.extended_attributes.contains("ReturnNullIfCrossOrigin")) {
         if (attribute.extended_attributes.contains("ReturnNullIfCrossOrigin")) {
@@ -3254,16 +3173,14 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.getter_callback@)
 
 
         if (!attribute.readonly) {
         if (!attribute.readonly) {
             attribute_generator.append(R"~~~(
             attribute_generator.append(R"~~~(
-JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
+JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 
 
     auto value = vm.argument(0);
     auto value = vm.argument(0);
 )~~~");
 )~~~");
 
 
-            generate_to_cpp(generator, attribute, "value", "", "cpp_value", interface.dictionaries, ReturnType::Value, attribute.extended_attributes.contains("LegacyNullToEmptyString"));
+            generate_to_cpp(generator, attribute, "value", "", "cpp_value", interface.dictionaries, attribute.extended_attributes.contains("LegacyNullToEmptyString"));
 
 
             if (attribute.extended_attributes.contains("Reflect")) {
             if (attribute.extended_attributes.contains("Reflect")) {
                 if (attribute.type->name != "boolean") {
                 if (attribute.type->name != "boolean") {
@@ -3283,7 +3200,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->set_@attribute.name:snakecase@(cpp_value); });
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->set_@attribute.name:snakecase@(cpp_value); });
 
 
     if (should_return_empty(result))
     if (should_return_empty(result))
-        return JS::Value();
+        return JS::throw_completion(vm.exception()->value());
 )~~~");
 )~~~");
             }
             }
 
 
@@ -3306,11 +3223,9 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
             stringifier_generator.set("attribute.cpp_getter_name", interface.stringifier_attribute->to_snakecase());
             stringifier_generator.set("attribute.cpp_getter_name", interface.stringifier_attribute->to_snakecase());
 
 
         stringifier_generator.append(R"~~~(
         stringifier_generator.append(R"~~~(
-JS_DEFINE_OLD_NATIVE_FUNCTION(@class_name@::to_string)
+JS_DEFINE_NATIVE_FUNCTION(@class_name@::to_string)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 
 
 )~~~");
 )~~~");
         if (interface.stringifier_attribute.has_value()) {
         if (interface.stringifier_attribute.has_value()) {
@@ -3322,7 +3237,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@class_name@::to_string)
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->to_string(); });
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->to_string(); });
 
 
     if (should_return_empty(result))
     if (should_return_empty(result))
-        return JS::Value();
+        return JS::throw_completion(vm.exception()->value());
 
 
     auto retval = result.release_value();
     auto retval = result.release_value();
 )~~~");
 )~~~");
@@ -3337,56 +3252,44 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@class_name@::to_string)
     if (interface.pair_iterator_types.has_value()) {
     if (interface.pair_iterator_types.has_value()) {
         auto iterator_generator = generator.fork();
         auto iterator_generator = generator.fork();
         iterator_generator.append(R"~~~(
         iterator_generator.append(R"~~~(
-JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::entries)
+JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::entries)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 
 
     return wrap(global_object, @iterator_name@::create(*impl, Object::PropertyKind::KeyAndValue));
     return wrap(global_object, @iterator_name@::create(*impl, Object::PropertyKind::KeyAndValue));
 }
 }
 
 
-JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::for_each)
+JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::for_each)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 
 
     auto callback = vm.argument(0);
     auto callback = vm.argument(0);
-    if (!callback.is_function()) {
-        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunction, callback.to_string_without_side_effects());
-        return {};
-    }
+    if (!callback.is_function())
+        return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAFunction, callback.to_string_without_side_effects());
 
 
     auto this_value = vm.this_value(global_object);
     auto this_value = vm.this_value(global_object);
-    impl->for_each([&](auto key, auto value) {
+    TRY(impl->for_each([&](auto key, auto value) -> JS::ThrowCompletionOr<void> {
 )~~~");
 )~~~");
         generate_variable_statement(iterator_generator, "wrapped_key", interface.pair_iterator_types->get<0>(), "key");
         generate_variable_statement(iterator_generator, "wrapped_key", interface.pair_iterator_types->get<0>(), "key");
         generate_variable_statement(iterator_generator, "wrapped_value", interface.pair_iterator_types->get<1>(), "value");
         generate_variable_statement(iterator_generator, "wrapped_value", interface.pair_iterator_types->get<1>(), "value");
         iterator_generator.append(R"~~~(
         iterator_generator.append(R"~~~(
-        auto result = vm.call(callback.as_function(), vm.argument(1), wrapped_value, wrapped_key, this_value);
-        return result.is_error() ? IterationDecision::Break : IterationDecision::Continue;
-    });
-    if (vm.exception())
+        TRY(vm.call(callback.as_function(), vm.argument(1), wrapped_value, wrapped_key, this_value));
         return {};
         return {};
+    }));
 
 
     return JS::js_undefined();
     return JS::js_undefined();
 }
 }
 
 
-JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::keys)
+JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::keys)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 
 
     return wrap(global_object, @iterator_name@::create(*impl, Object::PropertyKind::Key));
     return wrap(global_object, @iterator_name@::create(*impl, Object::PropertyKind::Key));
 }
 }
 
 
-JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::values)
+JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::values)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
+    auto* impl = TRY(impl_from(vm, global_object));
 
 
     return wrap(global_object, @iterator_name@::create(*impl, Object::PropertyKind::Value));
     return wrap(global_object, @iterator_name@::create(*impl, Object::PropertyKind::Value));
 }
 }
@@ -3572,7 +3475,7 @@ public:
     virtual ~@prototype_class@() override;
     virtual ~@prototype_class@() override;
 
 
 private:
 private:
-    JS_DECLARE_OLD_NATIVE_FUNCTION(next);
+    JS_DECLARE_NATIVE_FUNCTION(next);
 };
 };
 
 
 } // namespace Web::Bindings
 } // namespace Web::Bindings
@@ -3665,30 +3568,25 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
     auto& vm = this->vm();
     auto& vm = this->vm();
     Object::initialize(global_object);
     Object::initialize(global_object);
 
 
-    define_old_native_function(vm.names.next, next, 0, JS::Attribute::Configurable | JS::Attribute::Writable);
+    define_native_function(vm.names.next, next, 0, JS::Attribute::Configurable | JS::Attribute::Writable);
     define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, "Iterator"), JS::Attribute::Configurable);
     define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, "Iterator"), JS::Attribute::Configurable);
 }
 }
 
 
-static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_object)
+static JS::ThrowCompletionOr<@fully_qualified_name@*> impl_from(JS::VM& vm, JS::GlobalObject& global_object)
 {
 {
-    auto* this_object = TRY_OR_DISCARD(vm.this_value(global_object).to_object(global_object));
-    if (!is<@wrapper_class@>(this_object)) {
-        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@fully_qualified_name@");
-        return nullptr;
-    }
+    auto* this_object = TRY(vm.this_value(global_object).to_object(global_object));
+    if (!is<@wrapper_class@>(this_object))
+        return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "@fully_qualified_name@");
     return &static_cast<@wrapper_class@*>(this_object)->impl();
     return &static_cast<@wrapper_class@*>(this_object)->impl();
 }
 }
 
 
-JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::next)
+JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::next)
 {
 {
-    auto* impl = impl_from(vm, global_object);
-    if (!impl)
-        return {};
-
+    auto* impl = TRY(impl_from(vm, global_object));
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->next(); });
     auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->next(); });
 
 
     if (should_return_empty(result))
     if (should_return_empty(result))
-        return JS::Value();
+        return JS::throw_completion(vm.exception()->value());
 
 
     return result.release_value();
     return result.release_value();
 }
 }

+ 4 - 3
Userland/Libraries/LibWeb/URL/URLSearchParams.cpp

@@ -207,13 +207,14 @@ String URLSearchParams::to_string()
     return url_encode(m_list, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded);
     return url_encode(m_list, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded);
 }
 }
 
 
-void URLSearchParams::for_each(Function<IterationDecision(String const&, String const&)> callback)
+JS::ThrowCompletionOr<void> URLSearchParams::for_each(ForEachCallback callback)
 {
 {
     for (auto i = 0u; i < m_list.size(); ++i) {
     for (auto i = 0u; i < m_list.size(); ++i) {
         auto& query_param = m_list[i]; // We are explicitly iterating over the indices here as the callback might delete items from the list
         auto& query_param = m_list[i]; // We are explicitly iterating over the indices here as the callback might delete items from the list
-        if (callback(query_param.name, query_param.value) == IterationDecision::Break)
-            break;
+        TRY(callback(query_param.name, query_param.value));
     }
     }
+
+    return {};
 }
 }
 
 
 }
 }

+ 2 - 1
Userland/Libraries/LibWeb/URL/URLSearchParams.h

@@ -43,7 +43,8 @@ public:
 
 
     String to_string();
     String to_string();
 
 
-    void for_each(Function<IterationDecision(String const&, String const&)>);
+    using ForEachCallback = Function<JS::ThrowCompletionOr<void>(String const&, String const&)>;
+    JS::ThrowCompletionOr<void> for_each(ForEachCallback);
 
 
 private:
 private:
     friend class URL;
     friend class URL;