mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 10:17:35 +00:00
LibWeb: Convert throw_dom_exception_if_needed() to ThrowCompletionOr
This changes Web::Bindings::throw_dom_exception_if_needed() to return a JS::ThrowCompletionOr instead of an Optional. This allows callers to wrap the invocation with a TRY() macro instead of making a follow-up call to should_return_empty(). Further, this removes all invocations to vm.exception() in the generated bindings.
This commit is contained in:
parent
e3b7c305bc
commit
95e492de59
4 changed files with 84 additions and 168 deletions
|
@ -1414,21 +1414,14 @@ 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 result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->@function.cpp_name@(@.arguments@); });
|
[[maybe_unused]] auto retval = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl->@function.cpp_name@(@.arguments@); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
function_generator.append(R"~~~(
|
function_generator.append(R"~~~(
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return @interface_fully_qualified_name@::@function.cpp_name@(@.arguments@); });
|
[[maybe_unused]] auto retval = TRY(throw_dom_exception_if_needed(global_object, [&] { return @interface_fully_qualified_name@::@function.cpp_name@(@.arguments@); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
function_generator.append(R"~~~(
|
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
|
|
||||||
[[maybe_unused]] auto retval = result.release_value();
|
|
||||||
)~~~");
|
|
||||||
|
|
||||||
generate_return_statement(generator, *function.return_type);
|
generate_return_statement(generator, *function.return_type);
|
||||||
|
|
||||||
function_generator.append(R"~~~(
|
function_generator.append(R"~~~(
|
||||||
|
@ -1558,8 +1551,8 @@ private:
|
||||||
if (interface.is_legacy_platform_object()) {
|
if (interface.is_legacy_platform_object()) {
|
||||||
generator.append(R"~~~(
|
generator.append(R"~~~(
|
||||||
bool is_named_property_exposed_on_object(JS::PropertyKey const&) const;
|
bool is_named_property_exposed_on_object(JS::PropertyKey const&) const;
|
||||||
Optional<JS::PropertyDescriptor> legacy_platform_object_get_own_property_for_get_own_property_slot(JS::PropertyKey const&) const;
|
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> legacy_platform_object_get_own_property_for_get_own_property_slot(JS::PropertyKey const&) const;
|
||||||
Optional<JS::PropertyDescriptor> legacy_platform_object_get_own_property_for_set_slot(JS::PropertyKey const&) const;
|
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> legacy_platform_object_get_own_property_for_set_slot(JS::PropertyKey const&) const;
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1807,12 +1800,11 @@ bool @class_name@::is_named_property_exposed_on_object(JS::PropertyKey const& pr
|
||||||
get_own_property_generator.set("internal_method"sv, for_which_internal_method);
|
get_own_property_generator.set("internal_method"sv, for_which_internal_method);
|
||||||
|
|
||||||
get_own_property_generator.append(R"~~~(
|
get_own_property_generator.append(R"~~~(
|
||||||
Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_property_for_@internal_method@_slot(JS::PropertyKey const& property_name) const
|
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> @class_name@::legacy_platform_object_get_own_property_for_@internal_method@_slot(JS::PropertyKey const& property_name) const
|
||||||
{
|
{
|
||||||
)~~~");
|
)~~~");
|
||||||
|
|
||||||
get_own_property_generator.append(R"~~~(
|
get_own_property_generator.append(R"~~~(
|
||||||
[[maybe_unused]] auto& vm = this->vm();
|
|
||||||
[[maybe_unused]] auto& global_object = this->global_object();
|
[[maybe_unused]] auto& global_object = this->global_object();
|
||||||
)~~~");
|
)~~~");
|
||||||
|
|
||||||
|
@ -1834,7 +1826,7 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
|
||||||
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of an indexed property with index as the index.
|
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of an indexed property with index as the index.
|
||||||
if (interface.indexed_property_getter->name.is_empty()) {
|
if (interface.indexed_property_getter->name.is_empty()) {
|
||||||
get_own_property_generator.append(R"~~~(
|
get_own_property_generator.append(R"~~~(
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl().determine_value_of_indexed_property(index); });
|
auto value = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl().determine_value_of_indexed_property(index); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1845,16 +1837,11 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
|
||||||
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.indexed_property_getter->name.to_snakecase()));
|
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.indexed_property_getter->name.to_snakecase()));
|
||||||
|
|
||||||
function_scoped_generator.append(R"~~~(
|
function_scoped_generator.append(R"~~~(
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl().@function.cpp_name@(index); });
|
auto value = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl().@function.cpp_name@(index); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
get_own_property_generator.append(R"~~~(
|
get_own_property_generator.append(R"~~~(
|
||||||
if (should_return_empty(result))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
auto value = result.release_value();
|
|
||||||
|
|
||||||
// 5. Let desc be a newly created Property Descriptor with no fields.
|
// 5. Let desc be a newly created Property Descriptor with no fields.
|
||||||
JS::PropertyDescriptor descriptor;
|
JS::PropertyDescriptor descriptor;
|
||||||
|
|
||||||
|
@ -1885,7 +1872,7 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
|
||||||
|
|
||||||
// 3. Set ignoreNamedProps to true.
|
// 3. Set ignoreNamedProps to true.
|
||||||
// NOTE: To reduce complexity of WrapperGenerator, this just returns early instead of keeping track of another variable.
|
// NOTE: To reduce complexity of WrapperGenerator, this just returns early instead of keeping track of another variable.
|
||||||
return TRY_OR_DISCARD(Object::internal_get_own_property(property_name));
|
return TRY(Object::internal_get_own_property(property_name));
|
||||||
}
|
}
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
@ -1905,7 +1892,7 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
|
||||||
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of a named property with P as the name.
|
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of a named property with P as the name.
|
||||||
if (interface.named_property_getter->name.is_empty()) {
|
if (interface.named_property_getter->name.is_empty()) {
|
||||||
get_own_property_generator.append(R"~~~(
|
get_own_property_generator.append(R"~~~(
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl().determine_value_of_named_property(property_name_string); });
|
auto value = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl().determine_value_of_named_property(property_name_string); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1915,16 +1902,11 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
|
||||||
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.named_property_getter->name.to_snakecase()));
|
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.named_property_getter->name.to_snakecase()));
|
||||||
|
|
||||||
function_scoped_generator.append(R"~~~(
|
function_scoped_generator.append(R"~~~(
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl().@function.cpp_name@(property_name_string); });
|
auto value = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl().@function.cpp_name@(property_name_string); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
get_own_property_generator.append(R"~~~(
|
get_own_property_generator.append(R"~~~(
|
||||||
if (should_return_empty(result))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
auto value = result.release_value();
|
|
||||||
|
|
||||||
// 5. Let desc be a newly created Property Descriptor with no fields.
|
// 5. Let desc be a newly created Property Descriptor with no fields.
|
||||||
JS::PropertyDescriptor descriptor;
|
JS::PropertyDescriptor descriptor;
|
||||||
|
|
||||||
|
@ -1966,7 +1948,7 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
|
||||||
|
|
||||||
// 3. Return OrdinaryGetOwnProperty(O, P).
|
// 3. Return OrdinaryGetOwnProperty(O, P).
|
||||||
get_own_property_generator.append(R"~~~(
|
get_own_property_generator.append(R"~~~(
|
||||||
return TRY_OR_DISCARD(Object::internal_get_own_property(property_name));
|
return TRY(Object::internal_get_own_property(property_name));
|
||||||
}
|
}
|
||||||
)~~~");
|
)~~~");
|
||||||
};
|
};
|
||||||
|
@ -1985,8 +1967,6 @@ Optional<JS::PropertyDescriptor> @class_name@::legacy_platform_object_get_own_pr
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
static JS::ThrowCompletionOr<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();
|
|
||||||
|
|
||||||
// 1. Let creating be true if P is not a supported property name, and false otherwise.
|
// 1. Let creating be true if P is not a supported property name, and false otherwise.
|
||||||
// NOTE: This is in it's own variable to enforce the type.
|
// NOTE: This is in it's own variable to enforce the type.
|
||||||
// FIXME: Can this throw?
|
// FIXME: Can this throw?
|
||||||
|
@ -2005,14 +1985,10 @@ static JS::ThrowCompletionOr<void> invoke_named_property_setter(JS::GlobalObject
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
if (creating) {
|
if (creating) {
|
||||||
// 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); });
|
TRY(throw_dom_exception_if_needed(global_object, [&] { impl.set_value_of_new_named_property(property_name, converted_value); }));
|
||||||
if (should_return_empty(result))
|
|
||||||
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); });
|
TRY(throw_dom_exception_if_needed(global_object, [&] { impl.set_value_of_existing_named_property(property_name, converted_value); }));
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
}
|
}
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
|
@ -2022,9 +1998,7 @@ static JS::ThrowCompletionOr<void> invoke_named_property_setter(JS::GlobalObject
|
||||||
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.named_property_setter->name.to_snakecase()));
|
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.named_property_setter->name.to_snakecase()));
|
||||||
|
|
||||||
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); });
|
TRY(throw_dom_exception_if_needed(global_object, [&] { impl.@function.cpp_name@(property_name, converted_value); }));
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2042,8 +2016,6 @@ static JS::ThrowCompletionOr<void> invoke_named_property_setter(JS::GlobalObject
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
static JS::ThrowCompletionOr<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();
|
|
||||||
|
|
||||||
// 1. Let index be the result of calling ToUint32(P).
|
// 1. Let index be the result of calling ToUint32(P).
|
||||||
u32 index = property_name.as_number();
|
u32 index = property_name.as_number();
|
||||||
|
|
||||||
|
@ -2064,14 +2036,10 @@ static JS::ThrowCompletionOr<void> invoke_indexed_property_setter(JS::GlobalObje
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
if (creating) {
|
if (creating) {
|
||||||
// 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); });
|
TRY(throw_dom_exception_if_needed(global_object, [&] { impl.set_value_of_new_indexed_property(index, converted_value); }));
|
||||||
if (should_return_empty(result))
|
|
||||||
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); });
|
TRY(throw_dom_exception_if_needed(global_object, [&] { impl.set_value_of_existing_indexed_property(index, converted_value); }));
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
}
|
}
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
|
@ -2081,9 +2049,7 @@ static JS::ThrowCompletionOr<void> invoke_indexed_property_setter(JS::GlobalObje
|
||||||
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.indexed_property_setter->name.to_snakecase()));
|
function_scoped_generator.set("function.cpp_name", make_input_acceptable_cpp(interface.indexed_property_setter->name.to_snakecase()));
|
||||||
|
|
||||||
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); });
|
TRY(throw_dom_exception_if_needed(global_object, [&] { impl.@function.cpp_name@(index, converted_value); }));
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2099,7 +2065,7 @@ static JS::ThrowCompletionOr<void> invoke_indexed_property_setter(JS::GlobalObje
|
||||||
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> @class_name@::internal_get_own_property(JS::PropertyKey const& property_name) const
|
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> @class_name@::internal_get_own_property(JS::PropertyKey const& property_name) const
|
||||||
{
|
{
|
||||||
// 1. Return LegacyPlatformObjectGetOwnProperty(O, P, false).
|
// 1. Return LegacyPlatformObjectGetOwnProperty(O, P, false).
|
||||||
return legacy_platform_object_get_own_property_for_get_own_property_slot(property_name);
|
return TRY(legacy_platform_object_get_own_property_for_get_own_property_slot(property_name));
|
||||||
}
|
}
|
||||||
)~~~");
|
)~~~");
|
||||||
|
|
||||||
|
@ -2107,7 +2073,6 @@ JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> @class_name@::internal_g
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
JS::ThrowCompletionOr<bool> @class_name@::internal_set(JS::PropertyKey const& property_name, JS::Value value, JS::Value receiver)
|
JS::ThrowCompletionOr<bool> @class_name@::internal_set(JS::PropertyKey const& property_name, JS::Value value, JS::Value receiver)
|
||||||
{
|
{
|
||||||
auto& vm = this->vm();
|
|
||||||
[[maybe_unused]] auto& global_object = this->global_object();
|
[[maybe_unused]] auto& global_object = this->global_object();
|
||||||
)~~~");
|
)~~~");
|
||||||
|
|
||||||
|
@ -2153,9 +2118,7 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_set(JS::PropertyKey const& pr
|
||||||
|
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
// 2. Let ownDesc be LegacyPlatformObjectGetOwnProperty(O, P, true).
|
// 2. Let ownDesc be LegacyPlatformObjectGetOwnProperty(O, P, true).
|
||||||
auto own_descriptor = legacy_platform_object_get_own_property_for_set_slot(property_name);
|
auto own_descriptor = TRY(legacy_platform_object_get_own_property_for_set_slot(property_name));
|
||||||
if (auto* exception = vm.exception())
|
|
||||||
return JS::throw_completion(exception->value());
|
|
||||||
|
|
||||||
// 3. Perform ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
|
// 3. Perform ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
|
||||||
// NOTE: The spec says "perform" instead of "return", meaning nothing will be returned on this path according to the spec, which isn't possible to do.
|
// NOTE: The spec says "perform" instead of "return", meaning nothing will be returned on this path according to the spec, which isn't possible to do.
|
||||||
|
@ -2288,7 +2251,6 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_define_own_property(JS::Prope
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
JS::ThrowCompletionOr<bool> @class_name@::internal_delete(JS::PropertyKey const& property_name)
|
JS::ThrowCompletionOr<bool> @class_name@::internal_delete(JS::PropertyKey const& property_name)
|
||||||
{
|
{
|
||||||
[[maybe_unused]] auto& vm = this->vm();
|
|
||||||
auto& global_object = this->global_object();
|
auto& global_object = this->global_object();
|
||||||
)~~~");
|
)~~~");
|
||||||
|
|
||||||
|
@ -2335,12 +2297,7 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_delete(JS::PropertyKey const&
|
||||||
if (interface.named_property_deleter->name.is_empty()) {
|
if (interface.named_property_deleter->name.is_empty()) {
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
// 1. Perform the steps listed in the interface description to delete an existing named property with P as the name.
|
// 1. Perform the steps listed in the interface description to delete an existing named property with P as the name.
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl().delete_existing_named_property(property_name_string); });
|
bool succeeded = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl().delete_existing_named_property(property_name_string); }));
|
||||||
// FIXME: Make this nicer for ThrowCompletionOr.
|
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
|
|
||||||
bool succeeded = result.release_value();
|
|
||||||
|
|
||||||
// 2. If the steps indicated that the deletion failed, then return false.
|
// 2. If the steps indicated that the deletion failed, then return false.
|
||||||
if (!succeeded)
|
if (!succeeded)
|
||||||
|
@ -2353,17 +2310,13 @@ JS::ThrowCompletionOr<bool> @class_name@::internal_delete(JS::PropertyKey const&
|
||||||
|
|
||||||
function_scoped_generator.append(R"~~~(
|
function_scoped_generator.append(R"~~~(
|
||||||
// 1. Perform method steps of operation with O as this and « P » as the argument values.
|
// 1. Perform method steps of operation with O as this and « P » as the argument values.
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl().@function.cpp_name@(property_name_string); });
|
[[maybe_unused]] auto result = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl().@function.cpp_name@(property_name_string); }));
|
||||||
// FIXME: Make this nicer for ThrowCompletionOr.
|
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
)~~~");
|
)~~~");
|
||||||
|
|
||||||
// 2. If operation was declared with a return type of boolean and the steps returned false, then return false.
|
// 2. If operation was declared with a return type of boolean and the steps returned false, then return false.
|
||||||
if (interface.named_property_deleter->return_type->name == "boolean") {
|
if (interface.named_property_deleter->return_type->name == "boolean") {
|
||||||
function_scoped_generator.append(R"~~~(
|
function_scoped_generator.append(R"~~~(
|
||||||
bool succeeded = result.release_value();
|
if (!result)
|
||||||
if (!succeeded)
|
|
||||||
return false;
|
return false;
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
@ -2632,17 +2585,15 @@ JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject
|
||||||
generator.set(".constructor_arguments", arguments_builder.string_view());
|
generator.set(".constructor_arguments", arguments_builder.string_view());
|
||||||
|
|
||||||
generator.append(R"~~~(
|
generator.append(R"~~~(
|
||||||
auto impl = throw_dom_exception_if_needed(vm, global_object, [&] { return @fully_qualified_name@::create_with_global_object(window, @.constructor_arguments@); });
|
auto impl = TRY(throw_dom_exception_if_needed(global_object, [&] { return @fully_qualified_name@::create_with_global_object(window, @.constructor_arguments@); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
generator.append(R"~~~(
|
generator.append(R"~~~(
|
||||||
auto impl = throw_dom_exception_if_needed(vm, global_object, [&] { return @fully_qualified_name@::create_with_global_object(window); });
|
auto impl = TRY(throw_dom_exception_if_needed(global_object, [&] { return @fully_qualified_name@::create_with_global_object(window); }));
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
generator.append(R"~~~(
|
generator.append(R"~~~(
|
||||||
if (should_return_empty(impl))
|
return wrap(global_object, *impl);
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
return wrap(global_object, *impl.release_value());
|
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
// Multiple constructor overloads - can't do that yet.
|
// Multiple constructor overloads - can't do that yet.
|
||||||
|
@ -3197,10 +3148,7 @@ JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attribute_generator.append(R"~~~(
|
attribute_generator.append(R"~~~(
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->set_@attribute.name:snakecase@(cpp_value); });
|
TRY(throw_dom_exception_if_needed(global_object, [&] { return impl->set_@attribute.name:snakecase@(cpp_value); }));
|
||||||
|
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3234,12 +3182,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::to_string)
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
stringifier_generator.append(R"~~~(
|
stringifier_generator.append(R"~~~(
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->to_string(); });
|
auto retval = TRY(throw_dom_exception_if_needed(global_object, [&] { return impl->to_string(); }));
|
||||||
|
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
|
|
||||||
auto retval = result.release_value();
|
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
stringifier_generator.append(R"~~~(
|
stringifier_generator.append(R"~~~(
|
||||||
|
@ -3583,12 +3526,7 @@ static JS::ThrowCompletionOr<@fully_qualified_name@*> impl_from(JS::VM& vm, JS::
|
||||||
JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::next)
|
JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::next)
|
||||||
{
|
{
|
||||||
auto* impl = TRY(impl_from(vm, global_object));
|
auto* impl = TRY(impl_from(vm, global_object));
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->next(); });
|
return TRY(throw_dom_exception_if_needed(global_object, [&] { return impl->next(); }));
|
||||||
|
|
||||||
if (should_return_empty(result))
|
|
||||||
return JS::throw_completion(vm.exception()->value());
|
|
||||||
|
|
||||||
return result.release_value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Web::Bindings
|
} // namespace Web::Bindings
|
||||||
|
|
|
@ -20,19 +20,6 @@ constexpr bool IsExceptionOr = false;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool IsExceptionOr<DOM::ExceptionOr<T>> = true;
|
constexpr bool IsExceptionOr<DOM::ExceptionOr<T>> = true;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ALWAYS_INLINE bool throw_dom_exception(JS::VM& vm, JS::GlobalObject& global_object, DOM::ExceptionOr<T>& result)
|
|
||||||
{
|
|
||||||
if (result.is_exception()) {
|
|
||||||
result.materialized_exception(global_object)
|
|
||||||
.visit(
|
|
||||||
[&](NonnullRefPtr<DOM::DOMException> dom_exception) { vm.throw_exception(global_object, DOMExceptionWrapper::create(global_object, move(dom_exception))); },
|
|
||||||
[&](auto* js_exception) { vm.throw_exception(global_object, js_exception); });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -60,22 +47,47 @@ struct ExtractExceptionOrValueType<DOM::ExceptionOr<void>> {
|
||||||
using Type = JS::Value;
|
using Type = JS::Value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ALWAYS_INLINE JS::Completion dom_exception_to_throw_completion(auto&& global_object, auto&& exception)
|
||||||
|
{
|
||||||
|
auto& vm = global_object.vm();
|
||||||
|
|
||||||
|
return exception.visit(
|
||||||
|
[&](DOM::SimpleException const& exception) {
|
||||||
|
switch (exception.type) {
|
||||||
|
#define E(x) \
|
||||||
|
case DOM::SimpleExceptionType::x: \
|
||||||
|
return vm.template throw_completion<JS::x>(global_object, exception.message);
|
||||||
|
|
||||||
|
ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E)
|
||||||
|
|
||||||
|
#undef E
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&](NonnullRefPtr<DOM::DOMException> exception) {
|
||||||
|
return vm.template throw_completion<DOMExceptionWrapper>(global_object, move(exception));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using ExtractExceptionOrValueType = typename Detail::ExtractExceptionOrValueType<T>::Type;
|
using ExtractExceptionOrValueType = typename Detail::ExtractExceptionOrValueType<T>::Type;
|
||||||
|
|
||||||
// Return type depends on the return type of 'fn' (when invoked with no args):
|
// 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()
|
// void or ExceptionOr<void>: JS::ThrowCompletionOr<JS::Value>, always returns JS::js_undefined()
|
||||||
// ExceptionOr<T>: Optional<T>
|
// ExceptionOr<T>: JS::ThrowCompletionOr<T>
|
||||||
// T: Optional<T>
|
// T: JS::ThrowCompletionOr<T>
|
||||||
template<typename F, typename T = decltype(declval<F>()()), typename Ret = Conditional<!IsExceptionOr<T> && !IsVoid<T>, T, ExtractExceptionOrValueType<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)
|
JS::ThrowCompletionOr<Ret> throw_dom_exception_if_needed(auto&& global_object, F&& fn)
|
||||||
{
|
{
|
||||||
if constexpr (IsExceptionOr<T>) {
|
if constexpr (IsExceptionOr<T>) {
|
||||||
auto&& result = fn();
|
auto&& result = fn();
|
||||||
if (throw_dom_exception(vm, global_object, result))
|
|
||||||
return {};
|
if (result.is_exception())
|
||||||
|
return Detail::dom_exception_to_throw_completion(global_object, result.exception());
|
||||||
|
|
||||||
if constexpr (requires(T v) { v.value(); })
|
if constexpr (requires(T v) { v.value(); })
|
||||||
return result.value();
|
return result.value();
|
||||||
else
|
else
|
||||||
|
@ -88,12 +100,4 @@ Optional<Ret> throw_dom_exception_if_needed(auto&& vm, auto&& global_object, F&&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool should_return_empty(const Optional<T>& value)
|
|
||||||
{
|
|
||||||
if constexpr (IsSame<JS::Value, T>)
|
|
||||||
return !value.has_value() || value.value().is_empty();
|
|
||||||
return !value.has_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -636,33 +636,31 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::screen_y_getter)
|
||||||
return JS::Value(impl->screen_y());
|
return JS::Value(impl->screen_y());
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __ENUMERATE(attribute, event_name) \
|
#define __ENUMERATE(attribute, event_name) \
|
||||||
JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_getter) \
|
JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_getter) \
|
||||||
{ \
|
{ \
|
||||||
auto* impl = TRY(impl_from(vm, global_object)); \
|
auto* impl = TRY(impl_from(vm, global_object)); \
|
||||||
auto retval = impl->attribute(); \
|
auto retval = impl->attribute(); \
|
||||||
if (retval.callback.is_null()) \
|
if (retval.callback.is_null()) \
|
||||||
return JS::js_null(); \
|
return JS::js_null(); \
|
||||||
return retval.callback.cell(); \
|
return retval.callback.cell(); \
|
||||||
} \
|
} \
|
||||||
JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_setter) \
|
JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_setter) \
|
||||||
{ \
|
{ \
|
||||||
auto* impl = TRY(impl_from(vm, global_object)); \
|
auto* impl = TRY(impl_from(vm, global_object)); \
|
||||||
auto value = vm.argument(0); \
|
auto value = vm.argument(0); \
|
||||||
HTML::EventHandler cpp_value; \
|
HTML::EventHandler cpp_value; \
|
||||||
if (value.is_function()) { \
|
if (value.is_function()) { \
|
||||||
cpp_value.callback = JS::make_handle(&value.as_function()); \
|
cpp_value.callback = JS::make_handle(&value.as_function()); \
|
||||||
} else if (value.is_string()) { \
|
} else if (value.is_string()) { \
|
||||||
cpp_value.string = value.as_string().string(); \
|
cpp_value.string = value.as_string().string(); \
|
||||||
} else { \
|
} else { \
|
||||||
return JS::js_undefined(); \
|
return JS::js_undefined(); \
|
||||||
} \
|
} \
|
||||||
auto result = throw_dom_exception_if_needed(vm, global_object, [&] { \
|
TRY(throw_dom_exception_if_needed(global_object, [&] { \
|
||||||
return impl->set_##attribute(cpp_value); \
|
return impl->set_##attribute(cpp_value); \
|
||||||
}); \
|
})); \
|
||||||
if (should_return_empty(result)) \
|
return JS::js_undefined(); \
|
||||||
return JS::throw_completion(vm.exception()->value()); \
|
|
||||||
return JS::js_undefined(); \
|
|
||||||
}
|
}
|
||||||
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
||||||
#undef __ENUMERATE
|
#undef __ENUMERATE
|
||||||
|
|
|
@ -80,30 +80,6 @@ public:
|
||||||
return m_exception.template downcast<SimpleException, NonnullRefPtr<DOMException>>();
|
return m_exception.template downcast<SimpleException, NonnullRefPtr<DOMException>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto materialized_exception(JS::GlobalObject& global_object) const
|
|
||||||
{
|
|
||||||
#define E(x) JS::x*,
|
|
||||||
using ResultType = Variant<ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E) NonnullRefPtr<DOMException>>;
|
|
||||||
#undef E
|
|
||||||
|
|
||||||
return m_exception.visit(
|
|
||||||
[&](SimpleException& exception) -> ResultType {
|
|
||||||
switch (exception.type) {
|
|
||||||
#define E(x) \
|
|
||||||
case SimpleExceptionType::x: \
|
|
||||||
return JS::x::create(global_object, exception.message);
|
|
||||||
|
|
||||||
ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E)
|
|
||||||
|
|
||||||
#undef E
|
|
||||||
default:
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[&](NonnullRefPtr<DOMException> const& exception) -> ResultType { return exception; },
|
|
||||||
[](Empty) -> ResultType { VERIFY_NOT_REACHED(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_exception() const
|
bool is_exception() const
|
||||||
{
|
{
|
||||||
return !m_exception.template has<Empty>();
|
return !m_exception.template has<Empty>();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue