LibWeb: Introduce new construct_impl method for bound classes

In this generator change, we introduce a new factory method for bound
LibWeb objects that takes a JS::Realm instead of Web::HTML::Window.

The two methods are allowed to co-exist at this point, but the option to
take an HTML::Window will be removed once all clases are converted to
the new API.

We also start using the new Bindings::ensure_web_[prototype/constructor]
helpers from the Bindings/Intrinsics class so that we can eventually
remove the helpers from Window.h for the same.
This commit is contained in:
Andrew Kaster 2022-09-25 16:00:23 -06:00 committed by Linus Groh
parent c61a4f35dc
commit 8407bf60c5
Notes: sideshowbarker 2024-07-17 06:28:39 +09:00

View file

@ -2038,6 +2038,7 @@ void generate_constructor_implementation(IDL::Interface const& interface)
#include <LibWeb/Bindings/@constructor_class@.h>
#include <LibWeb/Bindings/@prototype_class@.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/Window.h>
#if __has_include(<LibWeb/Crypto/@name@.h>)
# include <LibWeb/Crypto/@name@.h>
@ -2141,8 +2142,7 @@ JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject
generator.append(R"~~~(
auto& vm = this->vm();
[[maybe_unused]] auto& realm = *vm.current_realm();
auto& window = verify_cast<HTML::Window>(realm.global_object());
[[maybe_unused]] auto& window = verify_cast<HTML::Window>(realm.global_object());
)~~~");
if (!constructor.parameters.is_empty()) {
@ -2153,14 +2153,29 @@ JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject
generator.set(".constructor_arguments", arguments_builder.string_view());
generator.append(R"~~~(
auto impl = TRY(throw_dom_exception_if_needed(vm, [&] { return @fully_qualified_name@::create_with_global_object(window, @.constructor_arguments@); }));
auto construct_impl = [&] <typename T>() {
if constexpr (requires(T) { T::construct_impl(declval<::JS::Realm&>(), @.constructor_arguments@ ); })
return T::construct_impl(realm, @.constructor_arguments@);
else if constexpr (requires(T) { T::create_with_global_object(declval<::Web::HTML::Window&>(), @.constructor_arguments@); })
return T::create_with_global_object(window, @.constructor_arguments@);
else if constexpr (requires(T) { sizeof(T); })
static_assert(DependentFalse<T>, "Bound type is missing constructor factory");
};
)~~~");
} else {
generator.append(R"~~~(
auto impl = TRY(throw_dom_exception_if_needed(vm, [&] { return @fully_qualified_name@::create_with_global_object(window); }));
auto construct_impl = [&] <typename T>() {
if constexpr (requires(T) { T::construct_impl(declval<::JS::Realm&>()); })
return T::construct_impl(realm);
else if constexpr (requires(T) { T::create_with_global_object(declval<::Web::HTML::Window&>()); })
return T::create_with_global_object(window);
else if constexpr (requires(T) { sizeof(T); })
static_assert(DependentFalse<T>, "Bound type is missing constructor factory");
};
)~~~");
}
generator.append(R"~~~(
auto impl = TRY(throw_dom_exception_if_needed(vm, [&] { return construct_impl.operator()<@fully_qualified_name@>(); }));
return &(*impl);
)~~~");
} else {
@ -2174,11 +2189,10 @@ JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject
void @constructor_class@::initialize(JS::Realm& realm)
{
auto& vm = this->vm();
auto& window = verify_cast<HTML::Window>(realm.global_object());
[[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable;
NativeFunction::initialize(realm);
define_direct_property(vm.names.prototype, &window.ensure_web_prototype<@prototype_class@>("@name@"), 0);
define_direct_property(vm.names.prototype, &ensure_web_prototype<@prototype_class@>(realm, "@name@"), 0);
define_direct_property(vm.names.length, JS::Value(@constructor.length@), JS::Attribute::Configurable);
)~~~");
@ -2377,6 +2391,7 @@ void generate_prototype_implementation(IDL::Interface const& interface)
#include <LibWeb/Bindings/@prototype_class@.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/IDLEventListener.h>
@ -2434,7 +2449,7 @@ namespace Web::Bindings {
)~~~");
} else if (!interface.parent_name.is_empty()) {
generator.append(R"~~~(
: Object(verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<@prototype_base_class@>("@parent_name@"))
: Object(ensure_web_prototype<@prototype_base_class@>(realm, "@parent_name@"))
)~~~");
} else {
generator.append(R"~~~(
@ -2836,7 +2851,6 @@ void generate_iterator_prototype_implementation(IDL::Interface const& interface)
#include <LibJS/Runtime/TypedArray.h>
#include <LibWeb/Bindings/@prototype_class@.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/HTML/Window.h>
#if __has_include(<LibWeb/@possible_include_path@.h>)
# include <LibWeb/@possible_include_path@.h>