diff --git a/Documentation/Browser/AddNewIDLFile.md b/Documentation/Browser/AddNewIDLFile.md index 3147d361daf264981c4a8d0959f01406e4269a6d..7a59a345005846e608f10bb00f2c74e5f551bae7 100644 --- a/Documentation/Browser/AddNewIDLFile.md +++ b/Documentation/Browser/AddNewIDLFile.md @@ -38,10 +38,5 @@ interface CSSRule { - It must inherit from `public RefCounted` and `public Bindings::Wrappable` - It must have a public `using WrapperType = Bindings::HTMLDetailsElementWrapper;` -7. Depending on what kind of thing your interface is, you may need to add it to the `WrapperFactory` of that kind: - - Elements: [`LibWeb/Bindings/NodeWrapperFactory.cpp`](../../Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp) - - Open the relevant wrapper factory file, and add `#include` directives and an `if` statement for your new type. - 8. If your type isn't an Event or Element, you will need to add it to [`is_wrappable_type()`](../../Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp) so that it can be accepted as an IDL parameter, attribute or return type. diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp index 3cb9904719c1ef2978a89d02f1d3aeb11d895664..fe6edc907c6166b293df85e490f509f20c380e6a 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp @@ -108,6 +108,48 @@ static bool impl_is_wrapper(Type const& type) if (type.name == "CSSImportRule"sv) return true; + if (type.name == "EventTarget"sv) + return true; + + if (type.name == "Node"sv) + return true; + if (type.name == "ShadowRoot"sv) + return true; + if (type.name == "DocumentTemporary"sv) + return true; + if (type.name == "Text"sv) + return true; + if (type.name == "Document"sv) + return true; + if (type.name == "DocumentType"sv) + return true; + if (type.name.ends_with("Element"sv)) + return true; + if (type.name == "XMLHttpRequest"sv) + return true; + if (type.name == "XMLHttpRequestEventTarget"sv) + return true; + if (type.name == "AbortSignal"sv) + return true; + if (type.name == "WebSocket"sv) + return true; + if (type.name == "Worker"sv) + return true; + if (type.name == "NodeIterator"sv) + return true; + if (type.name == "TreeWalker"sv) + return true; + if (type.name == "MediaQueryList"sv) + return true; + if (type.name == "MessagePort"sv) + return true; + if (type.name == "NodeFilter"sv) + return true; + if (type.name == "DOMTokenList"sv) + return true; + if (type.name == "DOMStringMap"sv) + return true; + return false; } @@ -328,9 +370,10 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter scoped_generator.set("legacy_null_to_empty_string", legacy_null_to_empty_string ? "true" : "false"); scoped_generator.set("parameter.type.name", parameter.type->name); if (parameter.type->name == "Window") - scoped_generator.set("wrapper_name", "WindowObject"); - else + scoped_generator.set("wrapper_name", "HTML::Window"); + else { scoped_generator.set("wrapper_name", String::formatted("{}Wrapper", parameter.type->name)); + } if (optional_default_value.has_value()) scoped_generator.set("parameter.optional_default_value", *optional_default_value); @@ -422,7 +465,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter )~~~"); } else { scoped_generator.append(R"~~~( - Optional> @cpp_name@; + Optional> @cpp_name@; if (!@js_name@@js_suffix@.is_undefined()) { if (!@js_name@@js_suffix@.is_object() || !is<@wrapper_name@>(@js_name@@js_suffix@.as_object())) return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@"); @@ -1500,7 +1543,13 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va )~~~"); } - generate_wrap_statement(scoped_generator, String::formatted("element{}", recursion_depth), sequence_generic_type.parameters.first(), interface, String::formatted("auto wrapped_element{} =", recursion_depth), WrappingReference::Yes, recursion_depth + 1); + if (impl_is_wrapper(sequence_generic_type.parameters.first())) { + scoped_generator.append(R"~~~( + auto* wrapped_element@recursion_depth@ = wrap(realm, *element@recursion_depth@); +)~~~"); + } else { + generate_wrap_statement(scoped_generator, String::formatted("element{}", recursion_depth), sequence_generic_type.parameters.first(), interface, String::formatted("auto wrapped_element{} =", recursion_depth), WrappingReference::Yes, recursion_depth + 1); + } scoped_generator.append(R"~~~( auto property_index@recursion_depth@ = JS::PropertyKey { i@recursion_depth@ }; @@ -1950,40 +1999,6 @@ private: }; )~~~"); - for (auto& it : interface.enumerations) { - if (!it.value.is_original_definition) - continue; - auto enum_generator = generator.fork(); - enum_generator.set("enum.type.name", it.key); - enum_generator.append(R"~~~( -enum class @enum.type.name@ { -)~~~"); - for (auto& entry : it.value.translated_cpp_names) { - enum_generator.set("enum.entry", entry.value); - enum_generator.append(R"~~~( - @enum.entry@, -)~~~"); - } - - enum_generator.append(R"~~~( -}; -inline String idl_enum_to_string(@enum.type.name@ value) { - switch(value) { -)~~~"); - for (auto& entry : it.value.translated_cpp_names) { - enum_generator.set("enum.entry", entry.value); - enum_generator.set("enum.string", entry.key); - enum_generator.append(R"~~~( - case @enum.type.name@::@enum.entry@: return "@enum.string@"; -)~~~"); - } - enum_generator.append(R"~~~( - default: return ""; - }; -} -)~~~"); - } - if (should_emit_wrapper_factory(interface)) { generator.append(R"~~~( @wrapper_class@* wrap(JS::Realm&, @fully_qualified_name@&); @@ -2021,8 +2036,7 @@ void generate_implementation(IDL::Interface const& interface) #include #endif #include -#include -#include +#include )~~~"); emit_includes_for_all_imports(interface, generator); @@ -2055,7 +2069,7 @@ namespace Web::Bindings { if (interface.wrapper_base_class == "Wrapper") { generator.append(R"~~~( @wrapper_class@::@wrapper_class@(JS::Realm& realm, @fully_qualified_name@& impl) - : Wrapper(static_cast(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")) + : Wrapper(verify_cast(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")) , m_impl(impl) { } @@ -2065,7 +2079,7 @@ namespace Web::Bindings { @wrapper_class@::@wrapper_class@(JS::Realm& realm, @fully_qualified_name@& impl) : @wrapper_base_class@(realm, impl) { - set_prototype(&static_cast(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")); + set_prototype(&verify_cast(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")); } )~~~"); } @@ -2902,11 +2916,8 @@ void generate_constructor_implementation(IDL::Interface const& interface) #if __has_include() #include #endif -#include #include -#include -#include -#include +#include #if __has_include() # include #elif __has_include() @@ -3007,7 +3018,7 @@ JS::ThrowCompletionOr @constructor_class@::construct(FunctionObject auto& vm = this->vm(); [[maybe_unused]] auto& realm = *vm.current_realm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); )~~~"); if (!constructor.parameters.is_empty()) { @@ -3039,7 +3050,7 @@ JS::ThrowCompletionOr @constructor_class@::construct(FunctionObject void @constructor_class@::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable; NativeFunction::initialize(realm); @@ -3165,8 +3176,46 @@ private: } generator.append(R"~~~( + +}; + +)~~~"); + + for (auto& it : interface.enumerations) { + if (!it.value.is_original_definition) + continue; + auto enum_generator = generator.fork(); + enum_generator.set("enum.type.name", it.key); + enum_generator.append(R"~~~( +enum class @enum.type.name@ { +)~~~"); + for (auto& entry : it.value.translated_cpp_names) { + enum_generator.set("enum.entry", entry.value); + enum_generator.append(R"~~~( + @enum.entry@, +)~~~"); + } + + enum_generator.append(R"~~~( }; +inline String idl_enum_to_string(@enum.type.name@ value) { + switch(value) { +)~~~"); + for (auto& entry : it.value.translated_cpp_names) { + enum_generator.set("enum.entry", entry.value); + enum_generator.set("enum.string", entry.key); + enum_generator.append(R"~~~( + case @enum.type.name@::@enum.entry@: return "@enum.string@"; +)~~~"); + } + enum_generator.append(R"~~~( + default: return ""; + }; +} +)~~~"); + } + generator.append(R"~~~( } // namespace Web::Bindings )~~~"); @@ -3208,10 +3257,8 @@ void generate_prototype_implementation(IDL::Interface const& interface) #endif #include #include -#include #include #include -#include #include #include #include @@ -3266,7 +3313,7 @@ namespace Web::Bindings { )~~~"); } else if (!interface.parent_name.is_empty()) { generator.append(R"~~~( - : Object(static_cast(realm.global_object()).ensure_web_prototype<@prototype_base_class@>("@parent_name@")) + : Object(verify_cast(realm.global_object()).ensure_web_prototype<@prototype_base_class@>("@parent_name@")) )~~~"); } else { generator.append(R"~~~( @@ -3418,8 +3465,8 @@ static JS::ThrowCompletionOr<@fully_qualified_name@*> impl_from(JS::VM& vm) if (interface.name == "EventTarget") { generator.append(R"~~~( - if (is(this_object)) { - return &static_cast(this_object)->impl(); + if (is(this_object)) { + return &static_cast(this_object)->impl(); } )~~~"); } @@ -3686,7 +3733,7 @@ void generate_iterator_implementation(IDL::Interface const& interface) #include #endif #include -#include +#include )~~~"); @@ -3720,7 +3767,7 @@ namespace Web::Bindings { } @wrapper_class@::@wrapper_class@(JS::Realm& realm, @fully_qualified_name@& impl) - : Wrapper(static_cast(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")) + : Wrapper(verify_cast(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")) , m_impl(impl) { } @@ -3804,7 +3851,7 @@ void generate_iterator_prototype_implementation(IDL::Interface const& interface) #include #include #include -#include +#include #if __has_include() # include diff --git a/Userland/Libraries/LibJS/Heap/Heap.h b/Userland/Libraries/LibJS/Heap/Heap.h index 92cbc751eacf124c28dba93c17bba4d224b673af..435d7c6364e12f31785ee2ef2293e7954c4e71ad 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.h +++ b/Userland/Libraries/LibJS/Heap/Heap.h @@ -20,7 +20,6 @@ #include #include #include -#include #include namespace JS { diff --git a/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp index 775ff6d7739d28b74152b47f9842fe9b0f07442f..ea2f9ae745f80f035154152529cf095da811e2c9 100644 --- a/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp @@ -6,9 +6,8 @@ #include #include -#include -#include #include +#include #include #include @@ -22,7 +21,7 @@ AudioConstructor::AudioConstructor(JS::Realm& realm) void AudioConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype("HTMLAudioElement"), 0); @@ -38,10 +37,9 @@ JS::ThrowCompletionOr AudioConstructor::call() JS::ThrowCompletionOr AudioConstructor::construct(FunctionObject&) { auto& vm = this->vm(); - auto& realm = *vm.current_realm(); // 1. Let document be the current global object's associated Document. - auto& window = static_cast(HTML::current_global_object()); + auto& window = verify_cast(HTML::current_global_object()); auto& document = window.impl().associated_document(); // 2. Let audio be the result of creating an element given document, audio, and the HTML namespace. @@ -60,7 +58,7 @@ JS::ThrowCompletionOr AudioConstructor::construct(FunctionObject&) } // 5. Return audio. - return wrap(realm, audio); + return audio.ptr(); } } diff --git a/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.cpp b/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.cpp index b880ba1db5faffa1d56395a98c6cf7a422b7b43d..6a1210a9c59a1d663a2304963391e80e47d3fb4d 100644 --- a/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.cpp @@ -17,14 +17,14 @@ #include #include #include -#include #include #include +#include namespace Web::Bindings { // 7.2.3.1 CrossOriginProperties ( O ), https://html.spec.whatwg.org/multipage/browsers.html#crossoriginproperties-(-o-) -Vector cross_origin_properties(Variant const& object) +Vector cross_origin_properties(Variant const& object) { // 1. Assert: O is a Location or Window object. @@ -37,7 +37,7 @@ Vector cross_origin_properties(Variant Vector { + [](HTML::Window const*) -> Vector { return { { .property = "window"sv, .needs_get = true, .needs_set = false }, { .property = "self"sv, .needs_get = true, .needs_set = false }, @@ -90,11 +90,11 @@ bool is_platform_object_same_origin(JS::Object const& object) } // 7.2.3.4 CrossOriginGetOwnPropertyHelper ( O, P ), https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-) -Optional cross_origin_get_own_property_helper(Variant const& object, JS::PropertyKey const& property_key) +Optional cross_origin_get_own_property_helper(Variant const& object, JS::PropertyKey const& property_key) { auto& realm = *main_thread_vm().current_realm(); auto const* object_ptr = object.visit([](auto* o) { return static_cast(o); }); - auto const object_const_variant = object.visit([](auto* o) { return Variant { o }; }); + auto const object_const_variant = object.visit([](auto* o) { return Variant { o }; }); // 1. Let crossOriginKey be a tuple consisting of the current settings object, O's relevant settings object, and P. auto cross_origin_key = CrossOriginKey { @@ -227,7 +227,7 @@ JS::ThrowCompletionOr cross_origin_set(JS::VM& vm, JS::Object& object, JS: } // 7.2.3.7 CrossOriginOwnPropertyKeys ( O ), https://html.spec.whatwg.org/multipage/browsers.html#crossoriginownpropertykeys-(-o-) -JS::MarkedVector cross_origin_own_property_keys(Variant const& object) +JS::MarkedVector cross_origin_own_property_keys(Variant const& object) { auto& event_loop = HTML::main_thread_event_loop(); auto& vm = event_loop.vm(); diff --git a/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.h b/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.h index 19c962d0e9fe8dbb4b525db943c307610235ce64..a385b74d6cf4ec4a0ffa0b3e784cee1f4366704e 100644 --- a/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.h +++ b/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.h @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace Web::Bindings { @@ -27,14 +28,14 @@ struct CrossOriginKey { using CrossOriginPropertyDescriptorMap = HashMap; -Vector cross_origin_properties(Variant const&); +Vector cross_origin_properties(Variant const&); bool is_cross_origin_accessible_window_property_name(JS::PropertyKey const&); JS::ThrowCompletionOr cross_origin_property_fallback(JS::VM&, JS::PropertyKey const&); bool is_platform_object_same_origin(JS::Object const&); -Optional cross_origin_get_own_property_helper(Variant const&, JS::PropertyKey const&); +Optional cross_origin_get_own_property_helper(Variant const&, JS::PropertyKey const&); JS::ThrowCompletionOr cross_origin_get(JS::VM&, JS::Object const&, JS::PropertyKey const&, JS::Value receiver); JS::ThrowCompletionOr cross_origin_set(JS::VM&, JS::Object&, JS::PropertyKey const&, JS::Value, JS::Value receiver); -JS::MarkedVector cross_origin_own_property_keys(Variant const&); +JS::MarkedVector cross_origin_own_property_keys(Variant const&); } diff --git a/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.cpp deleted file mode 100644 index 1f764e6d2330c7f693dbe773c845a141d7843ca7..0000000000000000000000000000000000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include - -namespace Web::Bindings { - -JS::Object* wrap(JS::Realm& realm, DOM::EventTarget& target) -{ - return target.create_wrapper(realm); -} - -} diff --git a/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.h b/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.h deleted file mode 100644 index 5ebd48575eafc8597dd150e4008e40fa479d0561..0000000000000000000000000000000000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace Web::Bindings { - -JS::Object* wrap(JS::Realm&, DOM::EventTarget&); - -} diff --git a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h index 7ad5afadf1cbbd964f07ea1ba71f536f00838c0c..d4b2b9783c387c50c6f9376f33847047a6a3ec51 100644 --- a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h +++ b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h @@ -128,7 +128,7 @@ JS::Completion invoke_callback(Bindings::CallbackType& callback, Optional arguments_list { function_object->vm().heap() }; + JS::MarkedVector arguments_list { function_object.vm().heap() }; (arguments_list.append(forward(args)), ...); return invoke_callback(callback, move(this_argument), move(arguments_list)); diff --git a/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp index 772daf0f2483527b70981410c8148c69fb15aa00..d7f5be791a8a8c8b89f95dc30e64bdc706caba8f 100644 --- a/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp @@ -5,10 +5,9 @@ */ #include -#include #include -#include #include +#include #include #include @@ -22,7 +21,7 @@ ImageConstructor::ImageConstructor(JS::Realm& realm) void ImageConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype("HTMLImageElement"), 0); @@ -38,11 +37,10 @@ JS::ThrowCompletionOr ImageConstructor::call() JS::ThrowCompletionOr ImageConstructor::construct(FunctionObject&) { auto& vm = this->vm(); - auto& realm = *vm.current_realm(); // 1. Let document be the current global object's associated Document. - auto& window = static_cast(HTML::current_global_object()); - auto& document = window.impl().associated_document(); + auto& window = verify_cast(HTML::current_global_object()); + auto& document = window.associated_document(); // 2. Let img be the result of creating an element given document, img, and the HTML namespace. auto image_element = DOM::create_element(document, HTML::TagNames::img, Namespace::HTML); @@ -60,7 +58,7 @@ JS::ThrowCompletionOr ImageConstructor::construct(FunctionObject&) } // 5. Return img. - return wrap(realm, image_element); + return image_element.ptr(); } } diff --git a/Userland/Libraries/LibWeb/Bindings/LegacyPlatformObject.h b/Userland/Libraries/LibWeb/Bindings/LegacyPlatformObject.h index c8969d438e60c0223e3605ba014de2dca4241705..a8f459bb1b910e377875875aa6b54252d5b69622 100644 --- a/Userland/Libraries/LibWeb/Bindings/LegacyPlatformObject.h +++ b/Userland/Libraries/LibWeb/Bindings/LegacyPlatformObject.h @@ -12,7 +12,7 @@ namespace Web::Bindings { // https://webidl.spec.whatwg.org/#dfn-legacy-platform-object class LegacyPlatformObject : public PlatformObject { - JS_OBJECT(LegacyPlatformObject, PlatformObject); + WEB_PLATFORM_OBJECT(LegacyPlatformObject, PlatformObject); public: virtual ~LegacyPlatformObject() override; diff --git a/Userland/Libraries/LibWeb/Bindings/LocationConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/LocationConstructor.cpp index 774fbfed70ae149c64b44841f29c2c725e55fa90..d625e19dceb50ff247a3f7ee15a3aa98fc5fa9b4 100644 --- a/Userland/Libraries/LibWeb/Bindings/LocationConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/LocationConstructor.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include namespace Web::Bindings { @@ -31,7 +31,7 @@ JS::ThrowCompletionOr LocationConstructor::construct(FunctionObject void LocationConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype("Location"), 0); diff --git a/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp b/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp index c7bb3ef3432f6f3a2dcc456e9a3be70b8be7ec23..f6e27a511a63c077cd1a4f4cf3831c455949826e 100644 --- a/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -24,7 +23,7 @@ namespace Web::Bindings { // https://html.spec.whatwg.org/multipage/history.html#the-location-interface LocationObject::LocationObject(JS::Realm& realm) - : Object(static_cast(realm.global_object()).ensure_web_prototype("Location")) + : Object(verify_cast(realm.global_object()).ensure_web_prototype("Location")) , m_default_properties(heap()) { } @@ -60,7 +59,7 @@ DOM::Document const* LocationObject::relevant_document() const // A Location object has an associated relevant Document, which is this Location object's // relevant global object's browsing context's active document, if this Location object's // relevant global object's browsing context is non-null, and null otherwise. - auto* browsing_context = verify_cast(HTML::relevant_global_object(*this)).impl().browsing_context(); + auto* browsing_context = verify_cast(HTML::relevant_global_object(*this)).browsing_context(); return browsing_context ? browsing_context->active_document() : nullptr; } @@ -95,7 +94,7 @@ JS_DEFINE_NATIVE_FUNCTION(LocationObject::href_getter) // https://html.spec.whatwg.org/multipage/history.html#the-location-interface:dom-location-href-2 JS_DEFINE_NATIVE_FUNCTION(LocationObject::href_setter) { - auto& window = static_cast(HTML::current_global_object()); + auto& window = verify_cast(HTML::current_global_object()); // FIXME: 1. If this's relevant Document is null, then return. @@ -218,7 +217,7 @@ JS_DEFINE_NATIVE_FUNCTION(LocationObject::port_getter) // https://html.spec.whatwg.org/multipage/history.html#dom-location-reload JS_DEFINE_NATIVE_FUNCTION(LocationObject::reload) { - auto& window = static_cast(HTML::current_global_object()); + auto& window = verify_cast(HTML::current_global_object()); window.impl().did_call_location_reload({}); return JS::js_undefined(); } @@ -226,7 +225,7 @@ JS_DEFINE_NATIVE_FUNCTION(LocationObject::reload) // https://html.spec.whatwg.org/multipage/history.html#dom-location-replace JS_DEFINE_NATIVE_FUNCTION(LocationObject::replace) { - auto& window = static_cast(HTML::current_global_object()); + auto& window = verify_cast(HTML::current_global_object()); auto url = TRY(vm.argument(0).to_string(vm)); // FIXME: This needs spec compliance work. window.impl().did_call_location_replace({}, move(url)); diff --git a/Userland/Libraries/LibWeb/Bindings/LocationPrototype.h b/Userland/Libraries/LibWeb/Bindings/LocationPrototype.h index 52ed45fe8dacdb6e73210500da3de16cb980fdb3..f803260011ae4a0d2eb5fb34dac69a34476c418f 100644 --- a/Userland/Libraries/LibWeb/Bindings/LocationPrototype.h +++ b/Userland/Libraries/LibWeb/Bindings/LocationPrototype.h @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include namespace Web::Bindings { diff --git a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp index 03c8954b8af9a8271853919ee9daa6ad57adc06a..a9e230b89aa3fc868e46dc38db9541c75a4e30b7 100644 --- a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp +++ b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp @@ -127,7 +127,7 @@ JS::VM& main_thread_vm() // with the promise attribute initialized to promise, and the reason attribute initialized to the value of promise's [[PromiseResult]] internal slot. HTML::queue_global_task(HTML::Task::Source::DOMManipulation, global, [global = JS::make_handle(&global), promise = JS::make_handle(&promise)]() mutable { // FIXME: This currently assumes that global is a WindowObject. - auto& window = verify_cast(*global.cell()); + auto& window = verify_cast(*global.cell()); HTML::PromiseRejectionEventInit event_init { {}, // Initialize the inherited DOM::EventInit @@ -135,7 +135,7 @@ JS::VM& main_thread_vm() /* .reason = */ promise.cell()->result(), }; auto promise_rejection_event = HTML::PromiseRejectionEvent::create(window, HTML::EventNames::rejectionhandled, event_init); - window.impl().dispatch_event(*promise_rejection_event); + window.dispatch_event(*promise_rejection_event); }); break; } @@ -308,20 +308,18 @@ JS::VM& main_thread_vm() // just to make sure that it's never empty. auto& custom_data = *verify_cast(vm->custom_data()); custom_data.root_execution_context = MUST(JS::Realm::initialize_host_defined_realm( - *vm, [&](JS::Realm& realm) -> JS::GlobalObject* { - auto internal_window = HTML::Window::create(); - custom_data.internal_window_object = JS::make_handle(vm->heap().allocate(realm, realm, internal_window)); - return custom_data.internal_window_object.cell(); }, - [](JS::Realm&) -> JS::GlobalObject* { - return nullptr; - })); + *vm, [&](JS::Realm& realm) -> JS::Object* { + custom_data.internal_window_object = JS::make_handle(*HTML::Window::create(realm)); + return custom_data.internal_window_object.cell(); + }, + nullptr)); vm->push_execution_context(*custom_data.root_execution_context); } return *vm; } -Bindings::WindowObject& main_thread_internal_window_object() +HTML::Window& main_thread_internal_window_object() { auto& vm = main_thread_vm(); auto& custom_data = verify_cast(*vm.custom_data()); @@ -398,7 +396,7 @@ void queue_mutation_observer_microtask(DOM::Document& document) } // https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-new-javascript-realm -NonnullOwnPtr create_a_new_javascript_realm(JS::VM& vm, Function create_global_object, Function create_global_this_value) +NonnullOwnPtr create_a_new_javascript_realm(JS::VM& vm, Function create_global_object, Function create_global_this_value) { // 1. Perform InitializeHostDefinedRealm() with the provided customizations for creating the global object and the global this binding. // 2. Let realm execution context be the running JavaScript execution context. diff --git a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h index 88a473e77135b5cb1e5c4015b10296fadd78fdac..d3825618b6b4fa75a2fbbf2cb27c94981674e37a 100644 --- a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h +++ b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h @@ -11,9 +11,9 @@ #include #include #include -#include #include #include +#include namespace Web::Bindings { @@ -35,7 +35,7 @@ struct WebEngineCustomData final : public JS::VM::CustomData { // This object is used as the global object for GC-allocated objects that don't // belong to a web-facing global object. - JS::Handle internal_window_object; + JS::Handle internal_window_object; }; struct WebEngineCustomJobCallbackData final : public JS::JobCallback::CustomData { @@ -53,8 +53,8 @@ struct WebEngineCustomJobCallbackData final : public JS::JobCallback::CustomData HTML::ClassicScript* active_script(); JS::VM& main_thread_vm(); -Bindings::WindowObject& main_thread_internal_window_object(); +HTML::Window& main_thread_internal_window_object(); void queue_mutation_observer_microtask(DOM::Document&); -NonnullOwnPtr create_a_new_javascript_realm(JS::VM&, Function create_global_object, Function create_global_this_value); +NonnullOwnPtr create_a_new_javascript_realm(JS::VM&, Function create_global_object, Function create_global_this_value); } diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp index 8a1b13e22f3dd912805aad014074b36bf380b4a0..9448536055bcd062584de842e5bbc3f4b954f56d 100644 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include namespace Web::Bindings { @@ -31,7 +31,7 @@ JS::ThrowCompletionOr NavigatorConstructor::construct(FunctionObjec void NavigatorConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype("Navigator"), 0); diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp b/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp index 533ef5b9a39969198faf446c09fb3b899300b255..8db25da83f0c1a7b2fc95f592d04639e9f8c17a8 100644 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp @@ -14,7 +14,7 @@ namespace Web { namespace Bindings { NavigatorObject::NavigatorObject(JS::Realm& realm) - : Object(static_cast(realm.global_object()).ensure_web_prototype("Navigator")) + : Object(verify_cast(realm.global_object()).ensure_web_prototype("Navigator")) { } diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h b/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h index 32eb17d619c596205ae2472a276e2b42ea6d8e57..3f5242ba222d1fa3668620cac43cc0cd96b4518f 100644 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h +++ b/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include namespace Web::Bindings { diff --git a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp deleted file mode 100644 index 62b58e9cb84117ed338148b4c0756a820cacca42..0000000000000000000000000000000000000000 --- a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * Copyright (c) 2020, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Web::Bindings { - -NodeWrapper* wrap(JS::Realm& realm, DOM::Node& node) -{ - if (node.wrapper()) - return static_cast(node.wrapper()); - - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - if (is(node)) - return static_cast(wrap_impl(realm, verify_cast(node))); - return static_cast(wrap_impl(realm, node)); -} - -} diff --git a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.h b/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.h deleted file mode 100644 index 69bad2cc084bc220d2940f38e870fd065862c50b..0000000000000000000000000000000000000000 --- a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace Web { -namespace Bindings { - -NodeWrapper* wrap(JS::Realm&, DOM::Node&); - -} -} diff --git a/Userland/Libraries/LibWeb/Bindings/OptionConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/OptionConstructor.cpp index c4b7930f13f39c074a54a56b96cdfaddbb022016..8c0a9984c29c1999251a8aa9474e98bbec9069eb 100644 --- a/Userland/Libraries/LibWeb/Bindings/OptionConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/OptionConstructor.cpp @@ -5,11 +5,11 @@ */ #include -#include -#include #include #include +#include #include +#include #include #include @@ -23,7 +23,7 @@ OptionConstructor::OptionConstructor(JS::Realm& realm) void OptionConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype("HTMLOptionElement"), 0); @@ -42,18 +42,18 @@ JS::ThrowCompletionOr OptionConstructor::construct(FunctionObject&) auto& realm = *vm.current_realm(); // 1. Let document be the current global object's associated Document. - auto& window = static_cast(HTML::current_global_object()); - auto& document = window.impl().associated_document(); + auto& window = verify_cast(HTML::current_global_object()); + auto& document = window.associated_document(); // 2. Let option be the result of creating an element given document, option, and the HTML namespace. - auto option_element = static_ptr_cast(DOM::create_element(document, HTML::TagNames::option, Namespace::HTML)); + JS::NonnullGCPtr option_element = verify_cast(*DOM::create_element(document, HTML::TagNames::option, Namespace::HTML)); // 3. If text is not the empty string, then append to option a new Text node whose data is text. if (vm.argument_count() > 0) { auto text = TRY(vm.argument(0).to_string(vm)); if (!text.is_empty()) { - auto new_text_node = adopt_ref(*new DOM::Text(document, text)); - option_element->append_child(new_text_node); + auto new_text_node = vm.heap().allocate(realm, document, text); + option_element->append_child(*new_text_node); } } @@ -75,7 +75,7 @@ JS::ThrowCompletionOr OptionConstructor::construct(FunctionObject&) option_element->m_selected = vm.argument(3).to_boolean(); // 7. Return option. - return wrap(realm, option_element); + return option_element.ptr(); } } diff --git a/Userland/Libraries/LibWeb/Bindings/PlatformObject.cpp b/Userland/Libraries/LibWeb/Bindings/PlatformObject.cpp index b334f152657bdacaf985c4ce30a0d7ede43a4d65..8c65fa9388cc1dcd42c5ea4544d5a6f8b3116b8d 100644 --- a/Userland/Libraries/LibWeb/Bindings/PlatformObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/PlatformObject.cpp @@ -4,10 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include +#include namespace Web::Bindings { +PlatformObject::PlatformObject(JS::Realm& realm) + : JS::Object(realm, nullptr) +{ +} + PlatformObject::PlatformObject(JS::Object& prototype) : JS::Object(prototype) { @@ -15,4 +23,14 @@ PlatformObject::PlatformObject(JS::Object& prototype) PlatformObject::~PlatformObject() = default; +JS::Realm& PlatformObject::realm() const +{ + return shape().realm(); +} + +HTML::Window& PlatformObject::global_object() const +{ + return verify_cast(realm().global_object()); +} + } diff --git a/Userland/Libraries/LibWeb/Bindings/PlatformObject.h b/Userland/Libraries/LibWeb/Bindings/PlatformObject.h index dc4b4ff81c3f56cd19efad166dbfc057e085a706..a866933dd4bcd61630ce1a2d37835673ca8bfd79 100644 --- a/Userland/Libraries/LibWeb/Bindings/PlatformObject.h +++ b/Userland/Libraries/LibWeb/Bindings/PlatformObject.h @@ -6,19 +6,49 @@ #pragma once +#include #include #include +#include namespace Web::Bindings { +#define WEB_PLATFORM_OBJECT(class_, base_class) \ + JS_OBJECT(class_, base_class) \ + auto& impl() \ + { \ + return *this; \ + } \ + auto const& impl() const \ + { \ + return *this; \ + } + +#define WRAPPER_HACK(class_, namespace_) \ + namespace Web::Bindings { \ + inline JS::Object* wrap(JS::Realm&, namespace_::class_& object) \ + { \ + return &object; \ + } \ + using class_##Wrapper = namespace_::class_; \ + } + // https://webidl.spec.whatwg.org/#dfn-platform-object -class PlatformObject : public JS::Object { +class PlatformObject + : public JS::Object + , public Weakable { JS_OBJECT(PlatformObject, JS::Object); public: virtual ~PlatformObject() override; + JS::Realm& realm() const; + + // FIXME: This should return a type that works in both window and worker contexts. + HTML::Window& global_object() const; + protected: + PlatformObject(JS::Realm&); explicit PlatformObject(JS::Object& prototype); }; diff --git a/Userland/Libraries/LibWeb/Bindings/WindowConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/WindowConstructor.cpp index ef33827f17130f2cf62b808be7bcca887453cdb0..909bd5e93b98ad8f4ecec8c78e41026e10ed9f6e 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowConstructor.cpp @@ -6,8 +6,8 @@ #include #include -#include #include +#include namespace Web::Bindings { @@ -31,7 +31,7 @@ JS::ThrowCompletionOr WindowConstructor::construct(FunctionObject&) void WindowConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast(realm.global_object()); + auto& window = verify_cast(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype("Window"), 0); diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp deleted file mode 100644 index c9b530b425e861f8b6cfae11262bf3bbe0956894..0000000000000000000000000000000000000000 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp +++ /dev/null @@ -1,774 +0,0 @@ -/* - * Copyright (c) 2020-2022, Andreas Kling - * Copyright (c) 2021, Sam Atkins - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Web::Bindings { - -WindowObject::WindowObject(JS::Realm& realm, HTML::Window& impl) - : GlobalObject(realm) - , m_impl(impl) -{ - impl.set_wrapper({}, *this); -} - -void WindowObject::initialize(JS::Realm& realm) -{ - Base::initialize(realm); - - Object::set_prototype(&ensure_web_prototype("Window")); - - // FIXME: These should be native accessors, not properties - define_direct_property("window", this, JS::Attribute::Enumerable); - define_direct_property("frames", this, JS::Attribute::Enumerable); - define_direct_property("self", this, JS::Attribute::Enumerable); - define_native_accessor(realm, "top", top_getter, nullptr, JS::Attribute::Enumerable); - define_native_accessor(realm, "parent", parent_getter, {}, JS::Attribute::Enumerable); - define_native_accessor(realm, "document", document_getter, {}, JS::Attribute::Enumerable); - define_native_accessor(realm, "name", name_getter, name_setter, JS::Attribute::Enumerable); - define_native_accessor(realm, "history", history_getter, {}, JS::Attribute::Enumerable); - define_native_accessor(realm, "performance", performance_getter, performance_setter, JS::Attribute::Enumerable | JS::Attribute::Configurable); - define_native_accessor(realm, "crypto", crypto_getter, {}, JS::Attribute::Enumerable); - define_native_accessor(realm, "screen", screen_getter, {}, JS::Attribute::Enumerable); - define_native_accessor(realm, "innerWidth", inner_width_getter, {}, JS::Attribute::Enumerable); - define_native_accessor(realm, "innerHeight", inner_height_getter, {}, JS::Attribute::Enumerable); - define_native_accessor(realm, "devicePixelRatio", device_pixel_ratio_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable); - u8 attr = JS::Attribute::Writable | JS::Attribute::Enumerable | JS::Attribute::Configurable; - define_native_function(realm, "alert", alert, 0, attr); - define_native_function(realm, "confirm", confirm, 0, attr); - define_native_function(realm, "prompt", prompt, 0, attr); - define_native_function(realm, "setInterval", set_interval, 1, attr); - define_native_function(realm, "setTimeout", set_timeout, 1, attr); - define_native_function(realm, "clearInterval", clear_interval, 1, attr); - define_native_function(realm, "clearTimeout", clear_timeout, 1, attr); - define_native_function(realm, "requestAnimationFrame", request_animation_frame, 1, attr); - define_native_function(realm, "cancelAnimationFrame", cancel_animation_frame, 1, attr); - define_native_function(realm, "atob", atob, 1, attr); - define_native_function(realm, "btoa", btoa, 1, attr); - - define_native_function(realm, "queueMicrotask", queue_microtask, 1, attr); - - define_native_function(realm, "requestIdleCallback", request_idle_callback, 1, attr); - define_native_function(realm, "cancelIdleCallback", cancel_idle_callback, 1, attr); - - define_native_function(realm, "getComputedStyle", get_computed_style, 1, attr); - define_native_function(realm, "matchMedia", match_media, 1, attr); - define_native_function(realm, "getSelection", get_selection, 0, attr); - - define_native_function(realm, "postMessage", post_message, 1, attr); - - // FIXME: These properties should be [Replaceable] according to the spec, but [Writable+Configurable] is the closest we have. - define_native_accessor(realm, "scrollX", scroll_x_getter, {}, attr); - define_native_accessor(realm, "pageXOffset", scroll_x_getter, {}, attr); - define_native_accessor(realm, "scrollY", scroll_y_getter, {}, attr); - define_native_accessor(realm, "pageYOffset", scroll_y_getter, {}, attr); - - define_native_function(realm, "scroll", scroll, 2, attr); - define_native_function(realm, "scrollTo", scroll, 2, attr); - define_native_function(realm, "scrollBy", scroll_by, 2, attr); - - define_native_accessor(realm, "screenX", screen_x_getter, {}, attr); - define_native_accessor(realm, "screenY", screen_y_getter, {}, attr); - define_native_accessor(realm, "screenLeft", screen_left_getter, {}, attr); - define_native_accessor(realm, "screenTop", screen_top_getter, {}, attr); - - define_direct_property("CSS", heap().allocate(realm, realm), 0); - - define_native_accessor(realm, "localStorage", local_storage_getter, {}, attr); - define_native_accessor(realm, "sessionStorage", session_storage_getter, {}, attr); - define_native_accessor(realm, "origin", origin_getter, {}, attr); - - // Legacy - define_native_accessor(realm, "event", event_getter, event_setter, JS::Attribute::Enumerable); - - m_location_object = heap().allocate(realm, realm); - - auto* m_navigator_object = heap().allocate(realm, realm); - define_direct_property("navigator", m_navigator_object, JS::Attribute::Enumerable | JS::Attribute::Configurable); - define_direct_property("clientInformation", m_navigator_object, JS::Attribute::Enumerable | JS::Attribute::Configurable); - - // NOTE: location is marked as [LegacyUnforgeable], meaning it isn't configurable. - define_native_accessor(realm, "location", location_getter, location_setter, JS::Attribute::Enumerable); - - // WebAssembly "namespace" - define_direct_property("WebAssembly", heap().allocate(realm, realm), JS::Attribute::Enumerable | JS::Attribute::Configurable); - - // HTML::GlobalEventHandlers and HTML::WindowEventHandlers -#define __ENUMERATE(attribute, event_name) \ - define_native_accessor(realm, #attribute, attribute##_getter, attribute##_setter, attr); - ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE); - ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE); -#undef __ENUMERATE - - ADD_WINDOW_OBJECT_INTERFACES; -} - -void WindowObject::visit_edges(Visitor& visitor) -{ - GlobalObject::visit_edges(visitor); - visitor.visit(m_location_object); - for (auto& it : m_prototypes) - visitor.visit(it.value); - for (auto& it : m_constructors) - visitor.visit(it.value); -} - -HTML::Origin WindowObject::origin() const -{ - return impl().associated_document().origin(); -} - -// https://webidl.spec.whatwg.org/#platform-object-setprototypeof -JS::ThrowCompletionOr WindowObject::internal_set_prototype_of(JS::Object* prototype) -{ - // 1. Return ? SetImmutablePrototype(O, V). - return set_immutable_prototype(prototype); -} - -static JS::ThrowCompletionOr impl_from(JS::VM& vm) -{ - // Since this is a non built-in function we must treat it as non-strict mode - // this means that a nullish this_value should be converted to the - // global_object. Generally this does not matter as we try to convert the - // this_value to a specific object type in the bindings. But since window is - // the global object we make an exception here. - // This allows calls like `setTimeout(f, 10)` to work. - auto this_value = vm.this_value(); - if (this_value.is_nullish()) - this_value = &vm.current_realm()->global_object(); - - auto* this_object = MUST(this_value.to_object(vm)); - - if (!is(*this_object)) - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "WindowObject"); - return &static_cast(this_object)->impl(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert) -{ - // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#simple-dialogs - // Note: This method is defined using two overloads, instead of using an optional argument, - // for historical reasons. The practical impact of this is that alert(undefined) is - // treated as alert("undefined"), but alert() is treated as alert(""). - auto* impl = TRY(impl_from(vm)); - String message = ""; - if (vm.argument_count()) - message = TRY(vm.argument(0).to_string(vm)); - impl->alert(message); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm) -{ - auto* impl = TRY(impl_from(vm)); - String message = ""; - if (!vm.argument(0).is_undefined()) - message = TRY(vm.argument(0).to_string(vm)); - return JS::Value(impl->confirm(message)); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::prompt) -{ - auto* impl = TRY(impl_from(vm)); - String message = ""; - String default_ = ""; - if (!vm.argument(0).is_undefined()) - message = TRY(vm.argument(0).to_string(vm)); - if (!vm.argument(1).is_undefined()) - default_ = TRY(vm.argument(1).to_string(vm)); - auto response = impl->prompt(message, default_); - if (response.is_null()) - return JS::js_null(); - return JS::js_string(vm, response); -} - -static JS::ThrowCompletionOr make_timer_handler(JS::VM& vm, JS::Value handler) -{ - if (handler.is_function()) - return JS::make_handle(vm.heap().allocate_without_realm(handler.as_function(), HTML::incumbent_settings_object())); - return TRY(handler.to_string(vm)); -} - -// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout -JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout) -{ - auto* impl = TRY(impl_from(vm)); - - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "setTimeout"); - - auto handler = TRY(make_timer_handler(vm, vm.argument(0))); - - i32 timeout = 0; - if (vm.argument_count() >= 2) - timeout = TRY(vm.argument(1).to_i32(vm)); - - JS::MarkedVector arguments { vm.heap() }; - for (size_t i = 2; i < vm.argument_count(); ++i) - arguments.append(vm.argument(i)); - - auto id = impl->set_timeout(move(handler), timeout, move(arguments)); - return JS::Value(id); -} - -// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval -JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval) -{ - auto* impl = TRY(impl_from(vm)); - - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "setInterval"); - - auto handler = TRY(make_timer_handler(vm, vm.argument(0))); - - i32 timeout = 0; - if (vm.argument_count() >= 2) - timeout = TRY(vm.argument(1).to_i32(vm)); - - JS::MarkedVector arguments { vm.heap() }; - for (size_t i = 2; i < vm.argument_count(); ++i) - arguments.append(vm.argument(i)); - - auto id = impl->set_interval(move(handler), timeout, move(arguments)); - return JS::Value(id); -} - -// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-cleartimeout -JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_timeout) -{ - auto* impl = TRY(impl_from(vm)); - - i32 id = 0; - if (vm.argument_count()) - id = TRY(vm.argument(0).to_i32(vm)); - - impl->clear_timeout(id); - return JS::js_undefined(); -} - -// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-clearinterval -JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_interval) -{ - auto* impl = TRY(impl_from(vm)); - - i32 id = 0; - if (vm.argument_count()) - id = TRY(vm.argument(0).to_i32(vm)); - - impl->clear_interval(id); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_animation_frame) -{ - auto* impl = TRY(impl_from(vm)); - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountOne, "requestAnimationFrame"); - auto* callback_object = TRY(vm.argument(0).to_object(vm)); - if (!callback_object->is_function()) - return vm.throw_completion(JS::ErrorType::NotAFunctionNoParam); - auto* callback = vm.heap().allocate_without_realm(*callback_object, HTML::incumbent_settings_object()); - return JS::Value(impl->request_animation_frame(*callback)); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_animation_frame) -{ - auto* impl = TRY(impl_from(vm)); - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountOne, "cancelAnimationFrame"); - auto id = TRY(vm.argument(0).to_i32(vm)); - impl->cancel_animation_frame(id); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::queue_microtask) -{ - auto* impl = TRY(impl_from(vm)); - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "queueMicrotask"); - auto* callback_object = TRY(vm.argument(0).to_object(vm)); - if (!callback_object->is_function()) - return vm.throw_completion(JS::ErrorType::NotAFunctionNoParam); - - auto* callback = vm.heap().allocate_without_realm(*callback_object, HTML::incumbent_settings_object()); - - impl->queue_microtask(*callback); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_idle_callback) -{ - auto* impl = TRY(impl_from(vm)); - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "requestIdleCallback"); - auto* callback_object = TRY(vm.argument(0).to_object(vm)); - if (!callback_object->is_function()) - return vm.throw_completion(JS::ErrorType::NotAFunctionNoParam); - // FIXME: accept options object - - auto* callback = vm.heap().allocate_without_realm(*callback_object, HTML::incumbent_settings_object()); - - return JS::Value(impl->request_idle_callback(*callback)); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_idle_callback) -{ - auto* impl = TRY(impl_from(vm)); - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountOne, "cancelIdleCallback"); - auto id = TRY(vm.argument(0).to_u32(vm)); - impl->cancel_idle_callback(id); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob) -{ - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountOne, "atob"); - auto string = TRY(vm.argument(0).to_string(vm)); - auto decoded = decode_base64(StringView(string)); - if (decoded.is_error()) - return vm.throw_completion(JS::ErrorType::InvalidFormat, "Base64"); - - // decode_base64() returns a byte string. LibJS uses UTF-8 for strings. Use Latin1Decoder to convert bytes 128-255 to UTF-8. - auto decoder = TextCodec::decoder_for("windows-1252"); - VERIFY(decoder); - return JS::js_string(vm, decoder->to_utf8(decoded.value())); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa) -{ - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountOne, "btoa"); - auto string = TRY(vm.argument(0).to_string(vm)); - - Vector byte_string; - byte_string.ensure_capacity(string.length()); - for (u32 code_point : Utf8View(string)) { - if (code_point > 0xff) { - return Bindings::throw_dom_exception_if_needed(vm, [] { - return DOM::InvalidCharacterError::create("Data contains characters outside the range U+0000 and U+00FF"); - }).release_error(); - } - byte_string.append(code_point); - } - - auto encoded = encode_base64(byte_string.span()); - return JS::js_string(vm, move(encoded)); -} - -// https://html.spec.whatwg.org/multipage/browsers.html#dom-top -JS_DEFINE_NATIVE_FUNCTION(WindowObject::top_getter) -{ - auto* impl = TRY(impl_from(vm)); - - auto* this_browsing_context = impl->associated_document().browsing_context(); - if (!this_browsing_context) - return JS::js_null(); - - VERIFY(this_browsing_context->top_level_browsing_context().active_document()); - auto& top_window = this_browsing_context->top_level_browsing_context().active_document()->window(); - return top_window.wrapper(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::parent_getter) -{ - auto* impl = TRY(impl_from(vm)); - auto* parent = impl->parent(); - if (!parent) - return JS::js_null(); - return parent->wrapper(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::document_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - return wrap(realm, impl->associated_document()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::performance_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - return wrap(realm, impl->performance()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::performance_setter) -{ - // https://webidl.spec.whatwg.org/#dfn-attribute-setter - // 4.1. If no arguments were passed, then throw a TypeError. - if (vm.argument_count() == 0) - return vm.throw_completion(JS::ErrorType::BadArgCountOne, "set performance"); - - auto* impl = TRY(impl_from(vm)); - - // 5. If attribute is declared with the [Replaceable] extended attribute, then: - // 1. Perform ? CreateDataProperty(esValue, id, V). - VERIFY(impl->wrapper()); - TRY(impl->wrapper()->create_data_property("performance", vm.argument(0))); - - // 2. Return undefined. - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::screen_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - return wrap(realm, impl->screen()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::event_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - if (!impl->current_event()) - return JS::js_undefined(); - return wrap(realm, const_cast(*impl->current_event())); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::event_setter) -{ - REPLACEABLE_PROPERTY_SETTER(WindowObject, event); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::location_getter) -{ - auto* impl = TRY(impl_from(vm)); - VERIFY(impl->wrapper()); - return impl->wrapper()->m_location_object; -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::location_setter) -{ - auto* impl = TRY(impl_from(vm)); - VERIFY(impl->wrapper()); - TRY(impl->wrapper()->m_location_object->set(JS::PropertyKey("href"), vm.argument(0), JS::Object::ShouldThrowExceptions::Yes)); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::crypto_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - return wrap(realm, impl->crypto()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::inner_width_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->inner_width()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::inner_height_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->inner_height()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::device_pixel_ratio_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->device_pixel_ratio()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::get_computed_style) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - auto* object = TRY(vm.argument(0).to_object(vm)); - if (!is(object)) - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "DOM element"); - - return wrap(realm, *impl->get_computed_style(static_cast(object)->impl())); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::get_selection) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - auto* selection = impl->get_selection(); - if (!selection) - return JS::js_null(); - return wrap(realm, *selection); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::match_media) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - auto media = TRY(vm.argument(0).to_string(vm)); - return wrap(realm, impl->match_media(move(media))); -} - -// https://www.w3.org/TR/cssom-view/#dom-window-scrollx -JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_x_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->scroll_x()); -} - -// https://www.w3.org/TR/cssom-view/#dom-window-scrolly -JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_y_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->scroll_y()); -} - -enum class ScrollBehavior { - Auto, - Smooth -}; - -// https://www.w3.org/TR/cssom-view/#perform-a-scroll -static void perform_a_scroll(Page& page, double x, double y, ScrollBehavior) -{ - // FIXME: Stop any existing smooth-scrolls - // FIXME: Implement smooth-scroll - page.client().page_did_request_scroll_to({ x, y }); -} - -// https://www.w3.org/TR/cssom-view/#dom-window-scroll -JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll) -{ - auto* impl = TRY(impl_from(vm)); - if (!impl->page()) - return JS::js_undefined(); - auto& page = *impl->page(); - - auto viewport_rect = page.top_level_browsing_context().viewport_rect(); - auto x_value = JS::Value(viewport_rect.x()); - auto y_value = JS::Value(viewport_rect.y()); - String behavior_string = "auto"; - - if (vm.argument_count() == 1) { - auto* options = TRY(vm.argument(0).to_object(vm)); - auto left = TRY(options->get("left")); - if (!left.is_undefined()) - x_value = left; - - auto top = TRY(options->get("top")); - if (!top.is_undefined()) - y_value = top; - - auto behavior_string_value = TRY(options->get("behavior")); - if (!behavior_string_value.is_undefined()) - behavior_string = TRY(behavior_string_value.to_string(vm)); - if (behavior_string != "smooth" && behavior_string != "auto") - return vm.throw_completion("Behavior is not one of 'smooth' or 'auto'"); - - } else if (vm.argument_count() >= 2) { - // We ignore arguments 2+ in line with behavior of Chrome and Firefox - x_value = vm.argument(0); - y_value = vm.argument(1); - } - - ScrollBehavior behavior = (behavior_string == "smooth") ? ScrollBehavior::Smooth : ScrollBehavior::Auto; - - double x = TRY(x_value.to_double(vm)); - x = JS::Value(x).is_finite_number() ? x : 0.0; - - double y = TRY(y_value.to_double(vm)); - y = JS::Value(y).is_finite_number() ? y : 0.0; - - // FIXME: Are we calculating the viewport in the way this function expects? - // FIXME: Handle overflow-directions other than top-left to bottom-right - - perform_a_scroll(page, x, y, behavior); - return JS::js_undefined(); -} - -// https://www.w3.org/TR/cssom-view/#dom-window-scrollby -JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_by) -{ - auto& realm = *vm.current_realm(); - - auto* impl = TRY(impl_from(vm)); - if (!impl->page()) - return JS::js_undefined(); - auto& page = *impl->page(); - - JS::Object* options = nullptr; - - if (vm.argument_count() == 0) { - options = JS::Object::create(realm, nullptr); - } else if (vm.argument_count() == 1) { - options = TRY(vm.argument(0).to_object(vm)); - } else if (vm.argument_count() >= 2) { - // We ignore arguments 2+ in line with behavior of Chrome and Firefox - options = JS::Object::create(realm, nullptr); - MUST(options->set("left", vm.argument(0), ShouldThrowExceptions::No)); - MUST(options->set("top", vm.argument(1), ShouldThrowExceptions::No)); - MUST(options->set("behavior", JS::js_string(vm, "auto"), ShouldThrowExceptions::No)); - } - - auto left_value = TRY(options->get("left")); - auto left = TRY(left_value.to_double(vm)); - - auto top_value = TRY(options->get("top")); - auto top = TRY(top_value.to_double(vm)); - - left = JS::Value(left).is_finite_number() ? left : 0.0; - top = JS::Value(top).is_finite_number() ? top : 0.0; - - auto current_scroll_position = page.top_level_browsing_context().viewport_scroll_offset(); - left = left + current_scroll_position.x(); - top = top + current_scroll_position.y(); - - auto behavior_string_value = TRY(options->get("behavior")); - auto behavior_string = behavior_string_value.is_undefined() ? "auto" : TRY(behavior_string_value.to_string(vm)); - if (behavior_string != "smooth" && behavior_string != "auto") - return vm.throw_completion("Behavior is not one of 'smooth' or 'auto'"); - ScrollBehavior behavior = (behavior_string == "smooth") ? ScrollBehavior::Smooth : ScrollBehavior::Auto; - - // FIXME: Spec wants us to call scroll(options) here. - // The only difference is that would invoke the viewport calculations that scroll() - // is not actually doing yet, so this is the same for now. - perform_a_scroll(page, left, top, behavior); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::history_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - return wrap(realm, impl->associated_document().history()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::screen_left_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->screen_x()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::screen_top_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->screen_y()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::screen_x_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->screen_x()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::screen_y_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::Value(impl->screen_y()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::post_message) -{ - auto* impl = TRY(impl_from(vm)); - auto target_origin = TRY(vm.argument(1).to_string(vm)); - impl->post_message(vm.argument(0), target_origin); - return JS::js_undefined(); -} - -// https://html.spec.whatwg.org/multipage/webappapis.html#dom-origin -JS_DEFINE_NATIVE_FUNCTION(WindowObject::origin_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::js_string(vm, impl->associated_document().origin().serialize()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::local_storage_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - // FIXME: localStorage may throw. We have to deal with that here. - return wrap(realm, *impl->local_storage()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::session_storage_getter) -{ - auto& realm = *vm.current_realm(); - auto* impl = TRY(impl_from(vm)); - // FIXME: sessionStorage may throw. We have to deal with that here. - return wrap(realm, *impl->session_storage()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::name_getter) -{ - auto* impl = TRY(impl_from(vm)); - return JS::js_string(vm, impl->name()); -} - -JS_DEFINE_NATIVE_FUNCTION(WindowObject::name_setter) -{ - auto* impl = TRY(impl_from(vm)); - impl->set_name(TRY(vm.argument(0).to_string(vm))); - return JS::js_undefined(); -} - -#define __ENUMERATE(attribute, event_name) \ - JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_getter) \ - { \ - auto* impl = TRY(impl_from(vm)); \ - auto retval = impl->attribute(); \ - if (!retval) \ - return JS::js_null(); \ - return &retval->callback; \ - } \ - JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_setter) \ - { \ - auto* impl = TRY(impl_from(vm)); \ - auto value = vm.argument(0); \ - Bindings::CallbackType* cpp_value; \ - if (value.is_object()) { \ - cpp_value = vm.heap().allocate_without_realm( \ - value.as_object(), HTML::incumbent_settings_object()); \ - } \ - impl->set_##attribute(cpp_value); \ - return JS::js_undefined(); \ - } -ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE) -ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE) -#undef __ENUMERATE - -} diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.h b/Userland/Libraries/LibWeb/Bindings/WindowObject.h index 86cc00a6d44c7485f5d2963a3e1cbce24857b12d..ac4013b6d31867143650a50a19786da66dea4992 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.h @@ -23,9 +23,6 @@ namespace Web { namespace Bindings { -// https://html.spec.whatwg.org/#timerhandler -using TimerHandler = Variant, String>; - class WindowObject : public JS::GlobalObject , public Weakable { @@ -35,134 +32,6 @@ public: explicit WindowObject(JS::Realm&, HTML::Window&); virtual void initialize(JS::Realm&) override; virtual ~WindowObject() override = default; - - JS::Realm& realm() const { return shape().realm(); } - - HTML::Window& impl() { return *m_impl; } - const HTML::Window& impl() const { return *m_impl; } - - HTML::Origin origin() const; - - LocationObject* location_object() { return m_location_object; } - LocationObject const* location_object() const { return m_location_object; } - - JS::Object* web_prototype(String const& class_name) { return m_prototypes.get(class_name).value_or(nullptr); } - JS::NativeFunction* web_constructor(String const& class_name) { return m_constructors.get(class_name).value_or(nullptr); } - - template - JS::Object& ensure_web_prototype(String const& class_name) - { - auto it = m_prototypes.find(class_name); - if (it != m_prototypes.end()) - return *it->value; - auto& realm = shape().realm(); - auto* prototype = heap().allocate(realm, realm); - m_prototypes.set(class_name, prototype); - return *prototype; - } - - template - JS::NativeFunction& ensure_web_constructor(String const& class_name) - { - auto it = m_constructors.find(class_name); - if (it != m_constructors.end()) - return *it->value; - auto& realm = shape().realm(); - auto* constructor = heap().allocate(realm, realm); - m_constructors.set(class_name, constructor); - define_direct_property(class_name, JS::Value(constructor), JS::Attribute::Writable | JS::Attribute::Configurable); - return *constructor; - } - - virtual JS::ThrowCompletionOr internal_set_prototype_of(JS::Object* prototype) override; - - CrossOriginPropertyDescriptorMap const& cross_origin_property_descriptor_map() const { return m_cross_origin_property_descriptor_map; } - CrossOriginPropertyDescriptorMap& cross_origin_property_descriptor_map() { return m_cross_origin_property_descriptor_map; } - -private: - virtual void visit_edges(Visitor&) override; - - JS_DECLARE_NATIVE_FUNCTION(top_getter); - - JS_DECLARE_NATIVE_FUNCTION(document_getter); - - JS_DECLARE_NATIVE_FUNCTION(location_getter); - JS_DECLARE_NATIVE_FUNCTION(location_setter); - - JS_DECLARE_NATIVE_FUNCTION(name_getter); - JS_DECLARE_NATIVE_FUNCTION(name_setter); - - JS_DECLARE_NATIVE_FUNCTION(performance_getter); - JS_DECLARE_NATIVE_FUNCTION(performance_setter); - - JS_DECLARE_NATIVE_FUNCTION(history_getter); - JS_DECLARE_NATIVE_FUNCTION(screen_getter); - - JS_DECLARE_NATIVE_FUNCTION(event_getter); - JS_DECLARE_NATIVE_FUNCTION(event_setter); - - JS_DECLARE_NATIVE_FUNCTION(inner_width_getter); - JS_DECLARE_NATIVE_FUNCTION(inner_height_getter); - - JS_DECLARE_NATIVE_FUNCTION(parent_getter); - - JS_DECLARE_NATIVE_FUNCTION(device_pixel_ratio_getter); - - JS_DECLARE_NATIVE_FUNCTION(scroll_x_getter); - JS_DECLARE_NATIVE_FUNCTION(scroll_y_getter); - JS_DECLARE_NATIVE_FUNCTION(scroll); - JS_DECLARE_NATIVE_FUNCTION(scroll_by); - - JS_DECLARE_NATIVE_FUNCTION(screen_x_getter); - JS_DECLARE_NATIVE_FUNCTION(screen_y_getter); - JS_DECLARE_NATIVE_FUNCTION(screen_left_getter); - JS_DECLARE_NATIVE_FUNCTION(screen_top_getter); - - JS_DECLARE_NATIVE_FUNCTION(post_message); - - JS_DECLARE_NATIVE_FUNCTION(local_storage_getter); - JS_DECLARE_NATIVE_FUNCTION(session_storage_getter); - JS_DECLARE_NATIVE_FUNCTION(origin_getter); - - JS_DECLARE_NATIVE_FUNCTION(alert); - JS_DECLARE_NATIVE_FUNCTION(confirm); - JS_DECLARE_NATIVE_FUNCTION(prompt); - JS_DECLARE_NATIVE_FUNCTION(set_interval); - JS_DECLARE_NATIVE_FUNCTION(set_timeout); - JS_DECLARE_NATIVE_FUNCTION(clear_interval); - JS_DECLARE_NATIVE_FUNCTION(clear_timeout); - JS_DECLARE_NATIVE_FUNCTION(request_animation_frame); - JS_DECLARE_NATIVE_FUNCTION(cancel_animation_frame); - JS_DECLARE_NATIVE_FUNCTION(atob); - JS_DECLARE_NATIVE_FUNCTION(btoa); - - JS_DECLARE_NATIVE_FUNCTION(get_computed_style); - JS_DECLARE_NATIVE_FUNCTION(match_media); - JS_DECLARE_NATIVE_FUNCTION(get_selection); - - JS_DECLARE_NATIVE_FUNCTION(queue_microtask); - - JS_DECLARE_NATIVE_FUNCTION(request_idle_callback); - JS_DECLARE_NATIVE_FUNCTION(cancel_idle_callback); - - JS_DECLARE_NATIVE_FUNCTION(crypto_getter); - -#define __ENUMERATE(attribute, event_name) \ - JS_DECLARE_NATIVE_FUNCTION(attribute##_getter); \ - JS_DECLARE_NATIVE_FUNCTION(attribute##_setter); - ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE); - ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE); -#undef __ENUMERATE - - NonnullRefPtr m_impl; - - LocationObject* m_location_object { nullptr }; - - HashMap m_prototypes; - HashMap m_constructors; - - // [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap - CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map; }; } diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h index ae967d4d128ac118b7aee7055ada51e393de09d2..4865ba607aaf94c3d5d8884ff9f44930d55b0188 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h @@ -376,9 +376,9 @@ #define ADD_WINDOW_OBJECT_CONSTRUCTOR_AND_PROTOTYPE(interface_name, constructor_name, prototype_name) \ { \ - auto& constructor = ensure_web_constructor(#interface_name); \ + auto& constructor = ensure_web_constructor(#interface_name); \ constructor.define_direct_property(vm.names.name, js_string(vm, #interface_name), JS::Attribute::Configurable); \ - auto& prototype = ensure_web_prototype(#interface_name); \ + auto& prototype = ensure_web_prototype(#interface_name); \ prototype.define_direct_property(vm.names.constructor, &constructor, JS::Attribute::Writable | JS::Attribute::Configurable); \ } diff --git a/Userland/Libraries/LibWeb/Bindings/WindowPrototype.h b/Userland/Libraries/LibWeb/Bindings/WindowPrototype.h index 9d99573be7ba918eaec9d46c28d666a579188ffc..8f16471bc4ecf19f1a8bfa6447f4f22eb32d4d57 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowPrototype.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowPrototype.h @@ -10,8 +10,8 @@ #include #include #include -#include #include +#include namespace Web::Bindings { @@ -20,7 +20,7 @@ class WindowPrototype final : public JS::Object { public: explicit WindowPrototype(JS::Realm& realm) - : JS::Object(static_cast(realm.global_object()).ensure_web_prototype("EventTarget")) + : JS::Object(verify_cast(realm.global_object()).ensure_web_prototype("EventTarget")) { } }; diff --git a/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp b/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp index 04fffa57cda63f295b31d0235c057cee6faae097..f943bef8b1c983a34c1476b11196287d69c0217f 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -22,9 +21,9 @@ namespace Web::Bindings { // 7.4 The WindowProxy exotic object, https://html.spec.whatwg.org/multipage/window-object.html#the-windowproxy-exotic-object -WindowProxy::WindowProxy(JS::Realm& realm, WindowObject& window) +WindowProxy::WindowProxy(JS::Realm& realm, HTML::Window& window) : JS::Object(realm, nullptr) - , m_window(&window) + , m_window(window) { } @@ -105,7 +104,7 @@ JS::ThrowCompletionOr> WindowProxy::internal_ge return m_window->internal_get_own_property(property_key); // 4. Let property be CrossOriginGetOwnPropertyHelper(W, P). - auto property = cross_origin_get_own_property_helper(m_window, property_key); + auto property = cross_origin_get_own_property_helper(const_cast(m_window.ptr()), property_key); // 5. If property is not undefined, then return property. if (property.has_value()) @@ -155,7 +154,7 @@ JS::ThrowCompletionOr WindowProxy::internal_get(JS::PropertyKey const // 1. Let W be the value of the [[Window]] internal slot of this. // 2. Check if an access between two browsing contexts should be reported, given the current global object's browsing context, W's browsing context, P, and the current settings object. - HTML::check_if_access_between_two_browsing_contexts_should_be_reported(*static_cast(HTML::current_global_object()).impl().browsing_context(), *m_window->impl().browsing_context(), property_key, HTML::current_settings_object()); + HTML::check_if_access_between_two_browsing_contexts_should_be_reported(*verify_cast(HTML::current_global_object()).impl().browsing_context(), *m_window->browsing_context(), property_key, HTML::current_settings_object()); // 3. If IsPlatformObjectSameOrigin(W) is true, then return ? OrdinaryGet(this, P, Receiver). // NOTE: this is passed rather than W as OrdinaryGet and CrossOriginGet will invoke the [[GetOwnProperty]] internal method. @@ -175,7 +174,7 @@ JS::ThrowCompletionOr WindowProxy::internal_set(JS::PropertyKey const& pro // 1. Let W be the value of the [[Window]] internal slot of this. // 2. Check if an access between two browsing contexts should be reported, given the current global object's browsing context, W's browsing context, P, and the current settings object. - HTML::check_if_access_between_two_browsing_contexts_should_be_reported(*static_cast(HTML::current_global_object()).impl().browsing_context(), *m_window->impl().browsing_context(), property_key, HTML::current_settings_object()); + HTML::check_if_access_between_two_browsing_contexts_should_be_reported(*verify_cast(HTML::current_global_object()).browsing_context(), *m_window->impl().browsing_context(), property_key, HTML::current_settings_object()); // 3. If IsPlatformObjectSameOrigin(W) is true, then: if (is_platform_object_same_origin(*m_window)) { @@ -252,13 +251,14 @@ JS::ThrowCompletionOr> WindowProxy::internal_own_pro } // 7. Return the concatenation of keys and ! CrossOriginOwnPropertyKeys(W). - keys.extend(cross_origin_own_property_keys(m_window)); + keys.extend(cross_origin_own_property_keys(m_window.ptr())); return keys; } void WindowProxy::visit_edges(JS::Cell::Visitor& visitor) { - visitor.visit(m_window); + Base::visit_edges(visitor); + visitor.visit(m_window.ptr()); } } diff --git a/Userland/Libraries/LibWeb/Bindings/WindowProxy.h b/Userland/Libraries/LibWeb/Bindings/WindowProxy.h index 42f8c560aca7567bb0e097fcf079cf660933f210..880fe3dead662ccb41d938ad73837764f9d6a01d 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowProxy.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowProxy.h @@ -17,7 +17,6 @@ class WindowProxy final : public JS::Object { JS_OBJECT(WindowProxy, JS::Object); public: - WindowProxy(JS::Realm&, WindowObject&); virtual ~WindowProxy() override = default; virtual JS::ThrowCompletionOr internal_get_prototype_of() const override; @@ -31,18 +30,20 @@ public: virtual JS::ThrowCompletionOr internal_delete(JS::PropertyKey const&) override; virtual JS::ThrowCompletionOr> internal_own_property_keys() const override; - WindowObject& window() { return *m_window; } - WindowObject const& window() const { return *m_window; } + HTML::Window& window() { return *m_window; } + HTML::Window const& window() const { return *m_window; } // NOTE: Someone will have to replace the wrapped window object as well: // "When the browsing context is navigated, the Window object wrapped by the browsing context's associated WindowProxy object is changed." // I haven't found where that actually happens yet. Make sure to use a Badge guarded setter. private: + WindowProxy(JS::Realm&, HTML::Window&); + virtual void visit_edges(JS::Cell::Visitor&) override; // [[Window]], https://html.spec.whatwg.org/multipage/window-object.html#concept-windowproxy-window - WindowObject* m_window { nullptr }; + JS::GCPtr m_window; }; } diff --git a/Userland/Libraries/LibWeb/Bindings/Wrappable.cpp b/Userland/Libraries/LibWeb/Bindings/Wrappable.cpp index 9f5efd78fdc2bf5963b0a2cd1e88fa4a2232cac6..bc5e052b8ba41e40ba05a2ede57e3ab5ca555f74 100644 --- a/Userland/Libraries/LibWeb/Bindings/Wrappable.cpp +++ b/Userland/Libraries/LibWeb/Bindings/Wrappable.cpp @@ -13,7 +13,7 @@ namespace Bindings { void Wrappable::set_wrapper(Wrapper& wrapper) { VERIFY(!m_wrapper); - m_wrapper = wrapper.make_weak_ptr(); + m_wrapper = wrapper.make_weak_ptr(); } } diff --git a/Userland/Libraries/LibWeb/Bindings/Wrapper.h b/Userland/Libraries/LibWeb/Bindings/Wrapper.h index 86b39899c9ba664a3c5afedb186625bfa314e68f..0ddb87938d6ccd0c03758cb730e719e2f998887c 100644 --- a/Userland/Libraries/LibWeb/Bindings/Wrapper.h +++ b/Userland/Libraries/LibWeb/Bindings/Wrapper.h @@ -12,10 +12,8 @@ namespace Web::Bindings { -class Wrapper - : public PlatformObject - , public Weakable { - JS_OBJECT(Wrapper, PlatformObject); +class Wrapper : public PlatformObject { + WEB_PLATFORM_OBJECT(Wrapper, PlatformObject); public: virtual ~Wrapper() override; diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 29c2d1d1c5231372e16accbe36d73ffec5178388..47e1f8e8654ee173c412e4acfb9f2d74bb6f0d2c 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -5,7 +5,6 @@ set(SOURCES Bindings/CSSNamespace.cpp Bindings/CallbackType.cpp Bindings/CrossOriginAbstractOperations.cpp - Bindings/EventTargetWrapperFactory.cpp Bindings/IDLAbstractOperations.cpp Bindings/ImageConstructor.cpp Bindings/LegacyPlatformObject.cpp @@ -14,11 +13,9 @@ set(SOURCES Bindings/MainThreadVM.cpp Bindings/NavigatorConstructor.cpp Bindings/NavigatorObject.cpp - Bindings/NodeWrapperFactory.cpp Bindings/OptionConstructor.cpp Bindings/PlatformObject.cpp Bindings/WindowConstructor.cpp - Bindings/WindowObject.cpp Bindings/WindowProxy.cpp Bindings/Wrappable.cpp Bindings/Wrapper.cpp diff --git a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp index cd10d4540189b25c26efd000d82e5bfc3bcb1552..9cb51a68acc7ad59204b04ab70e5e9d3a0ea9c0d 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp @@ -6,12 +6,12 @@ */ #include -#include #include +#include namespace Web::CSS { -CSSConditionRule::CSSConditionRule(Bindings::WindowObject& window_object, CSSRuleList& rules) +CSSConditionRule::CSSConditionRule(HTML::Window& window_object, CSSRuleList& rules) : CSSGroupingRule(window_object, rules) { set_prototype(&window_object.ensure_web_prototype("CSSConditionRule")); diff --git a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h index 58d040a5ee22f8f1674ca3e0be7fd8e914118bb0..f033d9587708d4f595f2a18527840927c356679b 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h @@ -13,13 +13,9 @@ namespace Web::CSS { class CSSConditionRule : public CSSGroupingRule { - AK_MAKE_NONCOPYABLE(CSSConditionRule); - AK_MAKE_NONMOVABLE(CSSConditionRule); - JS_OBJECT(CSSConditionRule, CSSGroupingRule); + WEB_PLATFORM_OBJECT(CSSConditionRule, CSSGroupingRule); public: - CSSConditionRule& impl() { return *this; } - virtual ~CSSConditionRule() = default; virtual String condition_text() const = 0; @@ -29,12 +25,9 @@ public: virtual void for_each_effective_style_rule(Function const& callback) const override; protected: - explicit CSSConditionRule(Bindings::WindowObject&, CSSRuleList&); + explicit CSSConditionRule(HTML::Window&, CSSRuleList&); }; } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSConditionRule& object) { return &object; } -using CSSConditionRuleWrapper = Web::CSS::CSSConditionRule; -} +WRAPPER_HACK(CSSConditionRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp index f6b3f69086a51497d26e743a5a79af121818ce3b..1d5d00aafa2131c4797dea2ffb08d8d456156b87 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp @@ -6,17 +6,17 @@ */ #include -#include #include +#include namespace Web::CSS { -CSSFontFaceRule* CSSFontFaceRule::create(Bindings::WindowObject& window_object, FontFace&& font_face) +CSSFontFaceRule* CSSFontFaceRule::create(HTML::Window& window_object, FontFace&& font_face) { return window_object.heap().allocate(window_object.realm(), window_object, move(font_face)); } -CSSFontFaceRule::CSSFontFaceRule(Bindings::WindowObject& window_object, FontFace&& font_face) +CSSFontFaceRule::CSSFontFaceRule(HTML::Window& window_object, FontFace&& font_face) : CSSRule(window_object) , m_font_face(move(font_face)) { diff --git a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h index 5967add8fcbcb5c3b06460ef312660978e151936..344d46b6a4e59d530b7756540c403b3f0cc2eb5b 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h @@ -13,16 +13,12 @@ namespace Web::CSS { class CSSFontFaceRule final : public CSSRule { - AK_MAKE_NONCOPYABLE(CSSFontFaceRule); - AK_MAKE_NONMOVABLE(CSSFontFaceRule); - JS_OBJECT(CSSFontFaceRule, CSSRule); + WEB_PLATFORM_OBJECT(CSSFontFaceRule, CSSRule); public: - static CSSFontFaceRule* create(Bindings::WindowObject&, FontFace&&); - explicit CSSFontFaceRule(Bindings::WindowObject&, FontFace&&); + static CSSFontFaceRule* create(HTML::Window&, FontFace&&); virtual ~CSSFontFaceRule() override = default; - CSSFontFaceRule& impl() { return *this; } virtual Type type() const override { return Type::FontFace; } @@ -30,6 +26,8 @@ public: CSSStyleDeclaration* style(); private: + explicit CSSFontFaceRule(HTML::Window&, FontFace&&); + virtual String serialized() const override; FontFace m_font_face; @@ -40,7 +38,4 @@ inline bool CSSRule::fast_is() const { return type() == CSSRule } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSFontFaceRule& object) { return &object; } -using CSSFontFaceRuleWrapper = Web::CSS::CSSFontFaceRule; -} +WRAPPER_HACK(CSSFontFaceRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp index e852b1ff44638e97d1bc2f5295c9e32cf2ca9fd3..707eab396490f1a14f2090a05665a18acd46401b 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp @@ -7,13 +7,13 @@ #include #include -#include #include #include +#include namespace Web::CSS { -CSSGroupingRule::CSSGroupingRule(Bindings::WindowObject& window_object, CSSRuleList& rules) +CSSGroupingRule::CSSGroupingRule(HTML::Window& window_object, CSSRuleList& rules) : CSSRule(window_object) , m_rules(rules) { diff --git a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h index a72b786b3451cc8576d3c07db83fb4e3286d881e..3616906120d54e51732165310ca7acd116941292 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h @@ -15,13 +15,9 @@ namespace Web::CSS { class CSSGroupingRule : public CSSRule { - AK_MAKE_NONCOPYABLE(CSSGroupingRule); - AK_MAKE_NONMOVABLE(CSSGroupingRule); - JS_OBJECT(CSSGroupingRule, CSSRule); + WEB_PLATFORM_OBJECT(CSSGroupingRule, CSSRule); public: - CSSGroupingRule& impl() { return *this; } - virtual ~CSSGroupingRule() = default; CSSRuleList const& css_rules() const { return m_rules; } @@ -35,7 +31,7 @@ public: virtual void set_parent_style_sheet(CSSStyleSheet*) override; protected: - explicit CSSGroupingRule(Bindings::WindowObject&, CSSRuleList&); + explicit CSSGroupingRule(HTML::Window&, CSSRuleList&); virtual void visit_edges(Cell::Visitor&) override; private: @@ -44,7 +40,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSGroupingRule& object) { return &object; } -using CSSGroupingRuleWrapper = Web::CSS::CSSGroupingRule; -} +WRAPPER_HACK(CSSGroupingRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp index 52c25953bbc774748225686b3eedca882da49019..bb6ee1eb853e98decca00375c5679e64879e5fc9 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp @@ -9,26 +9,26 @@ #include #include #include -#include #include #include #include +#include #include namespace Web::CSS { CSSImportRule* CSSImportRule::create(AK::URL url, DOM::Document& document) { - auto& window_object = document.preferred_window_object(); + auto& window_object = document.window(); return window_object.heap().allocate(window_object.realm(), move(url), document); } CSSImportRule::CSSImportRule(AK::URL url, DOM::Document& document) - : CSSRule(document.preferred_window_object()) + : CSSRule(document.window()) , m_url(move(url)) , m_document(document) { - set_prototype(&document.preferred_window_object().ensure_web_prototype("CSSImportRule")); + set_prototype(&document.window().ensure_web_prototype("CSSImportRule")); dbgln_if(CSS_LOADER_DEBUG, "CSSImportRule: Loading import URL: {}", m_url); auto request = LoadRequest::create_for_url_on_page(m_url, document.page()); diff --git a/Userland/Libraries/LibWeb/CSS/CSSImportRule.h b/Userland/Libraries/LibWeb/CSS/CSSImportRule.h index ac2cb26a38c49e9b965dec4509fc39249ba50b49..5c289c91f76b4ac10103ae130c279b4cf9e347da 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSImportRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSImportRule.h @@ -19,18 +19,13 @@ namespace Web::CSS { class CSSImportRule final : public CSSRule , public ResourceClient { - AK_MAKE_NONCOPYABLE(CSSImportRule); - AK_MAKE_NONMOVABLE(CSSImportRule); - JS_OBJECT(CSSImportRule, CSSRule); + WEB_PLATFORM_OBJECT(CSSImportRule, CSSRule); public: static CSSImportRule* create(AK::URL, DOM::Document&); - CSSImportRule(AK::URL, DOM::Document&); virtual ~CSSImportRule() = default; - CSSImportRule& impl() { return *this; } - AK::URL const& url() const { return m_url; } // FIXME: This should return only the specified part of the url. eg, "stuff/foo.css", not "https://example.com/stuff/foo.css". String href() const { return m_url.to_string(); } @@ -44,6 +39,8 @@ public: virtual Type type() const override { return Type::Import; }; private: + CSSImportRule(AK::URL, DOM::Document&); + virtual void visit_edges(Cell::Visitor&) override; virtual String serialized() const override; @@ -63,7 +60,4 @@ inline bool CSSRule::fast_is() const { return type() == CSSRule:: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSImportRule& object) { return &object; } -using CSSImportRuleWrapper = Web::CSS::CSSImportRule; -} +WRAPPER_HACK(CSSImportRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp index 245a80bb84a2534db4565b869d2a2ae0d63b14d5..cb72a58e3662380d3e82dd44ab71f66e6023616e 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp @@ -6,17 +6,17 @@ */ #include -#include #include +#include namespace Web::CSS { -CSSMediaRule* CSSMediaRule::create(Bindings::WindowObject& window_object, MediaList& media_queries, CSSRuleList& rules) +CSSMediaRule* CSSMediaRule::create(HTML::Window& window_object, MediaList& media_queries, CSSRuleList& rules) { return window_object.heap().allocate(window_object.realm(), window_object, media_queries, rules); } -CSSMediaRule::CSSMediaRule(Bindings::WindowObject& window_object, MediaList& media, CSSRuleList& rules) +CSSMediaRule::CSSMediaRule(HTML::Window& window_object, MediaList& media, CSSRuleList& rules) : CSSConditionRule(window_object, rules) , m_media(media) { diff --git a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h index 2c502a7e52f2a2d07c1a6c5dc30030473dc109d0..a09a3dd5aa5cb30e5d270aa8af7d4224045c47da 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h @@ -15,15 +15,10 @@ namespace Web::CSS { // https://www.w3.org/TR/css-conditional-3/#the-cssmediarule-interface class CSSMediaRule final : public CSSConditionRule { - AK_MAKE_NONCOPYABLE(CSSMediaRule); - AK_MAKE_NONMOVABLE(CSSMediaRule); - JS_OBJECT(CSSMediaRule, CSSConditionRule); + WEB_PLATFORM_OBJECT(CSSMediaRule, CSSConditionRule); public: - CSSMediaRule& impl() { return *this; } - - static CSSMediaRule* create(Bindings::WindowObject&, MediaList& media_queries, CSSRuleList&); - explicit CSSMediaRule(Bindings::WindowObject&, MediaList&, CSSRuleList&); + static CSSMediaRule* create(HTML::Window&, MediaList& media_queries, CSSRuleList&); virtual ~CSSMediaRule() = default; @@ -38,6 +33,8 @@ public: bool evaluate(HTML::Window const& window) { return m_media.evaluate(window); } private: + explicit CSSMediaRule(HTML::Window&, MediaList&, CSSRuleList&); + virtual void visit_edges(Cell::Visitor&) override; virtual String serialized() const override; @@ -49,7 +46,4 @@ inline bool CSSRule::fast_is() const { return type() == CSSRule::T } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSMediaRule& object) { return &object; } -using CSSMediaRuleWrapper = Web::CSS::CSSMediaRule; -} +WRAPPER_HACK(CSSMediaRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSRule.cpp index b3c8fcf351bb686aeb364dbc8441d05dc74bb3c7..ab1e30dafbd4238dfb72cc045e6d26c09fe8aeff 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.cpp @@ -7,13 +7,13 @@ */ #include -#include #include #include +#include namespace Web::CSS { -CSSRule::CSSRule(Bindings::WindowObject& window_object) +CSSRule::CSSRule(HTML::Window& window_object) : PlatformObject(window_object.ensure_web_prototype("CSSRule")) { } diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.h b/Userland/Libraries/LibWeb/CSS/CSSRule.h index 7b82ba62ce6b45790a3996a0be8f800960e66385..6394ec5338e355239f5a0e545ae8511638b5cdf6 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.h @@ -16,10 +16,9 @@ namespace Web::CSS { class CSSRule : public Bindings::PlatformObject { - JS_OBJECT(CSSRule, JS::Object); + WEB_PLATFORM_OBJECT(CSSRule, JS::Object); public: - CSSRule& impl() { return *this; } virtual ~CSSRule() = default; // https://drafts.csswg.org/cssom/#dom-cssrule-type @@ -46,7 +45,7 @@ public: bool fast_is() const = delete; protected: - explicit CSSRule(Bindings::WindowObject&); + explicit CSSRule(HTML::Window&); virtual String serialized() const = 0; @@ -58,7 +57,4 @@ protected: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSRule& object) { return &object; } -using CSSRuleWrapper = Web::CSS::CSSRule; -} +WRAPPER_HACK(CSSRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp index 8aa7bf293c01ee4298904c5847d42216ebce310c..674383f4039e748cd1b862c3da90162073fb262d 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp @@ -6,17 +6,17 @@ #include #include -#include #include #include #include #include #include #include +#include namespace Web::CSS { -CSSRuleList* CSSRuleList::create(Bindings::WindowObject& window_object, JS::MarkedVector const& rules) +CSSRuleList* CSSRuleList::create(HTML::Window& window_object, JS::MarkedVector const& rules) { auto* rule_list = window_object.heap().allocate(window_object.realm(), window_object); for (auto* rule : rules) @@ -24,12 +24,12 @@ CSSRuleList* CSSRuleList::create(Bindings::WindowObject& window_object, JS::Mark return rule_list; } -CSSRuleList::CSSRuleList(Bindings::WindowObject& window_object) +CSSRuleList::CSSRuleList(HTML::Window& window_object) : Bindings::LegacyPlatformObject(window_object.ensure_web_prototype("CSSRuleList")) { } -CSSRuleList* CSSRuleList::create_empty(Bindings::WindowObject& window_object) +CSSRuleList* CSSRuleList::create_empty(HTML::Window& window_object) { return window_object.heap().allocate(window_object.realm(), window_object); } @@ -65,7 +65,7 @@ DOM::ExceptionOr CSSRuleList::insert_a_css_rule(Variant()) { new_rule = parse_css_rule( - CSS::Parser::ParsingContext { static_cast(global_object()) }, + CSS::Parser::ParsingContext { static_cast(global_object()) }, rule.get()); } else { new_rule = rule.get(); diff --git a/Userland/Libraries/LibWeb/CSS/CSSRuleList.h b/Userland/Libraries/LibWeb/CSS/CSSRuleList.h index 9f94bcc1d4dc473213f1527eb75b2e1a68080552..76cab74c06cae7d3c60e4af9490f7f7e211557ab 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRuleList.h +++ b/Userland/Libraries/LibWeb/CSS/CSSRuleList.h @@ -20,15 +20,13 @@ namespace Web::CSS { // https://www.w3.org/TR/cssom/#the-cssrulelist-interface class CSSRuleList : public Bindings::LegacyPlatformObject { - JS_OBJECT(CSSRuleList, Bindings::LegacyPlatformObject); + WEB_PLATFORM_OBJECT(CSSRuleList, Bindings::LegacyPlatformObject); public: - CSSRuleList& impl() { return *this; } + static CSSRuleList* create(HTML::Window&, JS::MarkedVector const&); + static CSSRuleList* create_empty(HTML::Window&); - static CSSRuleList* create(Bindings::WindowObject&, JS::MarkedVector const&); - static CSSRuleList* create_empty(Bindings::WindowObject&); - - explicit CSSRuleList(Bindings::WindowObject&); + explicit CSSRuleList(HTML::Window&); ~CSSRuleList() = default; CSSRule const* item(size_t index) const @@ -74,7 +72,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSRuleList& object) { return &object; } -using CSSRuleListWrapper = Web::CSS::CSSRuleList; -} +WRAPPER_HACK(CSSRuleList, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp index e5b4644463e11bb69c4ec0273bd6dd4206b75a80..1cb49c536a32a5778295c24bedeff95ac752b965 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp @@ -5,25 +5,25 @@ */ #include -#include #include #include #include #include +#include namespace Web::CSS { -CSSStyleDeclaration::CSSStyleDeclaration(Bindings::WindowObject& window_object) +CSSStyleDeclaration::CSSStyleDeclaration(HTML::Window& window_object) : PlatformObject(window_object.ensure_web_prototype("CSSStyleDeclaration")) { } -PropertyOwningCSSStyleDeclaration* PropertyOwningCSSStyleDeclaration::create(Bindings::WindowObject& window_object, Vector properties, HashMap custom_properties) +PropertyOwningCSSStyleDeclaration* PropertyOwningCSSStyleDeclaration::create(HTML::Window& window_object, Vector properties, HashMap custom_properties) { return window_object.heap().allocate(window_object.realm(), window_object, move(properties), move(custom_properties)); } -PropertyOwningCSSStyleDeclaration::PropertyOwningCSSStyleDeclaration(Bindings::WindowObject& window_object, Vector properties, HashMap custom_properties) +PropertyOwningCSSStyleDeclaration::PropertyOwningCSSStyleDeclaration(HTML::Window& window_object, Vector properties, HashMap custom_properties) : CSSStyleDeclaration(window_object) , m_properties(move(properties)) , m_custom_properties(move(custom_properties)) @@ -39,16 +39,22 @@ String PropertyOwningCSSStyleDeclaration::item(size_t index) const ElementInlineCSSStyleDeclaration* ElementInlineCSSStyleDeclaration::create(DOM::Element& element, Vector properties, HashMap custom_properties) { - auto& window_object = element.document().preferred_window_object(); + auto& window_object = element.document().window(); return window_object.heap().allocate(window_object.realm(), element, move(properties), move(custom_properties)); } ElementInlineCSSStyleDeclaration::ElementInlineCSSStyleDeclaration(DOM::Element& element, Vector properties, HashMap custom_properties) - : PropertyOwningCSSStyleDeclaration(element.document().preferred_window_object(), move(properties), move(custom_properties)) + : PropertyOwningCSSStyleDeclaration(element.document().window(), move(properties), move(custom_properties)) , m_element(element.make_weak_ptr()) { } +void ElementInlineCSSStyleDeclaration::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_element.ptr()); +} + size_t PropertyOwningCSSStyleDeclaration::length() const { return m_properties.size(); diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h index ac8a3e24716be5328574802ee33dc354394bca04..6679125e8e4f54a397c698ab3ab7dabea4f4124f 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h @@ -26,13 +26,11 @@ struct StyleProperty { }; class CSSStyleDeclaration : public Bindings::PlatformObject { - JS_OBJECT(CSSStyleDeclaration, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(CSSStyleDeclaration, Bindings::PlatformObject); public: virtual ~CSSStyleDeclaration() = default; - CSSStyleDeclaration& impl() { return *this; } - virtual size_t length() const = 0; virtual String item(size_t index) const = 0; @@ -57,16 +55,15 @@ public: virtual JS::ThrowCompletionOr internal_set(JS::PropertyKey const&, JS::Value value, JS::Value receiver) override; protected: - CSSStyleDeclaration(Bindings::WindowObject&); + explicit CSSStyleDeclaration(HTML::Window&); }; class PropertyOwningCSSStyleDeclaration : public CSSStyleDeclaration { - JS_OBJECT(PropertyOwningCSSStyleDeclaration, CSSStyleDeclaration); + WEB_PLATFORM_OBJECT(PropertyOwningCSSStyleDeclaration, CSSStyleDeclaration); friend class ElementInlineCSSStyleDeclaration; public: - static PropertyOwningCSSStyleDeclaration* create(Bindings::WindowObject&, Vector, HashMap custom_properties); - PropertyOwningCSSStyleDeclaration(Bindings::WindowObject&, Vector, HashMap); + static PropertyOwningCSSStyleDeclaration* create(HTML::Window&, Vector, HashMap custom_properties); virtual ~PropertyOwningCSSStyleDeclaration() override = default; @@ -86,6 +83,8 @@ public: virtual String serialized() const final override; protected: + PropertyOwningCSSStyleDeclaration(HTML::Window&, Vector, HashMap); + virtual void update_style_attribute() { } private: @@ -96,11 +95,10 @@ private: }; class ElementInlineCSSStyleDeclaration final : public PropertyOwningCSSStyleDeclaration { - JS_OBJECT(ElementInlineCSSStyleDeclaration, PropertyOwningCSSStyleDeclaration); + WEB_PLATFORM_OBJECT(ElementInlineCSSStyleDeclaration, PropertyOwningCSSStyleDeclaration); public: static ElementInlineCSSStyleDeclaration* create(DOM::Element&, Vector properties, HashMap custom_properties); - explicit ElementInlineCSSStyleDeclaration(DOM::Element&, Vector properties, HashMap custom_properties); virtual ~ElementInlineCSSStyleDeclaration() override = default; @@ -110,9 +108,13 @@ public: bool is_updating() const { return m_updating; } private: + explicit ElementInlineCSSStyleDeclaration(DOM::Element&, Vector properties, HashMap custom_properties); + + virtual void visit_edges(Cell::Visitor&) override; + virtual void update_style_attribute() override; - WeakPtr m_element; + JS::GCPtr m_element; // https://drafts.csswg.org/cssom/#cssstyledeclaration-updating-flag bool m_updating { false }; @@ -120,7 +122,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSStyleDeclaration& object) { return &object; } -using CSSStyleDeclarationWrapper = Web::CSS::CSSStyleDeclaration; -} +WRAPPER_HACK(CSSStyleDeclaration, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp index 47d829a36c6932e1bec31421ba0e8f3d5afde9b9..15bb1463e178c325259f5856531af21802012c40 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp @@ -5,18 +5,18 @@ */ #include -#include #include #include +#include namespace Web::CSS { -CSSStyleRule* CSSStyleRule::create(Bindings::WindowObject& window_object, NonnullRefPtrVector&& selectors, CSSStyleDeclaration& declaration) +CSSStyleRule* CSSStyleRule::create(HTML::Window& window_object, NonnullRefPtrVector&& selectors, CSSStyleDeclaration& declaration) { return window_object.heap().allocate(window_object.realm(), window_object, move(selectors), declaration); } -CSSStyleRule::CSSStyleRule(Bindings::WindowObject& window_object, NonnullRefPtrVector&& selectors, CSSStyleDeclaration& declaration) +CSSStyleRule::CSSStyleRule(HTML::Window& window_object, NonnullRefPtrVector&& selectors, CSSStyleDeclaration& declaration) : CSSRule(window_object) , m_selectors(move(selectors)) , m_declaration(declaration) diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h index 27f2ced9cce4ea0f5b46d742d9c74bacd5a4ae6c..07292800a9c6d72ecbddd9f4ae7f8b25cd830f36 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h @@ -16,18 +16,13 @@ namespace Web::CSS { class CSSStyleRule final : public CSSRule { - JS_OBJECT(CSSStyleRule, CSSRule); - AK_MAKE_NONCOPYABLE(CSSStyleRule); - AK_MAKE_NONMOVABLE(CSSStyleRule); + WEB_PLATFORM_OBJECT(CSSStyleRule, CSSRule); public: - static CSSStyleRule* create(Bindings::WindowObject&, NonnullRefPtrVector&&, CSSStyleDeclaration&); - CSSStyleRule(Bindings::WindowObject&, NonnullRefPtrVector&&, CSSStyleDeclaration&); + static CSSStyleRule* create(HTML::Window&, NonnullRefPtrVector&&, CSSStyleDeclaration&); virtual ~CSSStyleRule() override = default; - CSSStyleRule& impl() { return *this; } - NonnullRefPtrVector const& selectors() const { return m_selectors; } CSSStyleDeclaration const& declaration() const { return m_declaration; } @@ -39,6 +34,8 @@ public: CSSStyleDeclaration* style(); private: + CSSStyleRule(HTML::Window&, NonnullRefPtrVector&&, CSSStyleDeclaration&); + virtual void visit_edges(Cell::Visitor&) override; virtual String serialized() const override; @@ -51,7 +48,4 @@ inline bool CSSRule::fast_is() const { return type() == CSSRule::T } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSStyleRule& object) { return &object; } -using CSSStyleRuleWrapper = Web::CSS::CSSStyleRule; -} +WRAPPER_HACK(CSSStyleRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp index 1828e30f628ce92be434c660a4f4d30747330d39..5d210155f7e8e46b2689e452b47c7eed97c40cc3 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp @@ -13,12 +13,12 @@ namespace Web::CSS { -CSSStyleSheet* CSSStyleSheet::create(Bindings::WindowObject& window_object, CSSRuleList& rules, Optional location) +CSSStyleSheet* CSSStyleSheet::create(HTML::Window& window_object, CSSRuleList& rules, Optional location) { return window_object.heap().allocate(window_object.realm(), window_object, rules, move(location)); } -CSSStyleSheet::CSSStyleSheet(Bindings::WindowObject& window_object, CSSRuleList& rules, Optional location) +CSSStyleSheet::CSSStyleSheet(HTML::Window& window_object, CSSRuleList& rules, Optional location) : StyleSheet(window_object) , m_rules(&rules) { diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h index 7712a13f3fa3736a07844a9dbb93829523c1cb16..fd6ca3685d6d6103ea8489bbdbc0bd66d793c00d 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h @@ -21,16 +21,14 @@ class CSSImportRule; class CSSStyleSheet final : public StyleSheet , public Weakable { - JS_OBJECT(CSSStyleSheet, StyleSheet); + WEB_PLATFORM_OBJECT(CSSStyleSheet, StyleSheet); public: - static CSSStyleSheet* create(Bindings::WindowObject&, CSSRuleList& rules, Optional location); + static CSSStyleSheet* create(HTML::Window&, CSSRuleList& rules, Optional location); - explicit CSSStyleSheet(Bindings::WindowObject&, CSSRuleList&, Optional location); + explicit CSSStyleSheet(HTML::Window&, CSSRuleList&, Optional location); virtual ~CSSStyleSheet() override = default; - CSSStyleSheet& impl() { return *this; } - void set_owner_css_rule(CSSRule* rule) { m_owner_css_rule = rule; } virtual String type() const override { return "text/css"; } @@ -63,7 +61,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSStyleSheet& object) { return &object; } -using CSSStyleSheetWrapper = Web::CSS::CSSStyleSheet; -} +WRAPPER_HACK(CSSStyleSheet, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp index 602ca34768a7858b5a7a45d63cb2fc3cd3d20b84..860f142115cb3b6a5304524130896e82ab375920 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp @@ -5,18 +5,18 @@ */ #include -#include #include #include +#include namespace Web::CSS { -CSSSupportsRule* CSSSupportsRule::create(Bindings::WindowObject& window_object, NonnullRefPtr&& supports, CSSRuleList& rules) +CSSSupportsRule* CSSSupportsRule::create(HTML::Window& window_object, NonnullRefPtr&& supports, CSSRuleList& rules) { return window_object.heap().allocate(window_object.realm(), window_object, move(supports), rules); } -CSSSupportsRule::CSSSupportsRule(Bindings::WindowObject& window_object, NonnullRefPtr&& supports, CSSRuleList& rules) +CSSSupportsRule::CSSSupportsRule(HTML::Window& window_object, NonnullRefPtr&& supports, CSSRuleList& rules) : CSSConditionRule(window_object, rules) , m_supports(move(supports)) { diff --git a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h index 31e0dcac7b9eb9b7faf02001f8d1697e4a9c89ec..1cabc601f95add2900efcf85d6a6731cb2cb5cb6 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h @@ -17,18 +17,13 @@ namespace Web::CSS { // https://www.w3.org/TR/css-conditional-3/#the-csssupportsrule-interface class CSSSupportsRule final : public CSSConditionRule { - JS_OBJECT(CSSSupportsRule, CSSConditionRule); - AK_MAKE_NONCOPYABLE(CSSSupportsRule); - AK_MAKE_NONMOVABLE(CSSSupportsRule); + WEB_PLATFORM_OBJECT(CSSSupportsRule, CSSConditionRule); public: - static CSSSupportsRule* create(Bindings::WindowObject&, NonnullRefPtr&&, CSSRuleList&); - explicit CSSSupportsRule(Bindings::WindowObject&, NonnullRefPtr&&, CSSRuleList&); + static CSSSupportsRule* create(HTML::Window&, NonnullRefPtr&&, CSSRuleList&); virtual ~CSSSupportsRule() = default; - CSSSupportsRule& impl() { return *this; } - virtual Type type() const override { return Type::Supports; }; String condition_text() const override; @@ -36,6 +31,8 @@ public: virtual bool condition_matches() const override { return m_supports->matches(); } private: + explicit CSSSupportsRule(HTML::Window&, NonnullRefPtr&&, CSSRuleList&); + virtual String serialized() const override; NonnullRefPtr m_supports; @@ -46,7 +43,4 @@ inline bool CSSRule::fast_is() const { return type() == CSSRule } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSSupportsRule& object) { return &object; } -using CSSSupportsRuleWrapper = Web::CSS::CSSSupportsRule; -} +WRAPPER_HACK(CSSSupportsRule, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/MediaList.cpp b/Userland/Libraries/LibWeb/CSS/MediaList.cpp index dbcea1fa353ee6bc79bae7027636ffaf744c3fff..7003b702b3e98a949a52c477d6911e9bfeda49aa 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaList.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaList.cpp @@ -6,18 +6,18 @@ */ #include -#include #include #include +#include namespace Web::CSS { -MediaList* MediaList::create(Bindings::WindowObject& window_object, NonnullRefPtrVector&& media) +MediaList* MediaList::create(HTML::Window& window_object, NonnullRefPtrVector&& media) { return window_object.heap().allocate(window_object.realm(), window_object, move(media)); } -MediaList::MediaList(Bindings::WindowObject& window_object, NonnullRefPtrVector&& media) +MediaList::MediaList(HTML::Window& window_object, NonnullRefPtrVector&& media) : Bindings::LegacyPlatformObject(window_object.ensure_web_prototype("MediaList")) , m_media(move(media)) { diff --git a/Userland/Libraries/LibWeb/CSS/MediaList.h b/Userland/Libraries/LibWeb/CSS/MediaList.h index 4ffe4b91067864966868c44bd6fc32c1ff580508..25a272c93974b2c8f9dd6cca6da6b3eea556864f 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaList.h +++ b/Userland/Libraries/LibWeb/CSS/MediaList.h @@ -17,17 +17,12 @@ namespace Web::CSS { // https://www.w3.org/TR/cssom-1/#the-medialist-interface class MediaList final : public Bindings::LegacyPlatformObject { - AK_MAKE_NONCOPYABLE(MediaList); - AK_MAKE_NONMOVABLE(MediaList); - JS_OBJECT(MediaList, Bindings::LegacyPlatformObject); + WEB_PLATFORM_OBJECT(MediaList, Bindings::LegacyPlatformObject); public: - static MediaList* create(Bindings::WindowObject&, NonnullRefPtrVector&& media); - explicit MediaList(Bindings::WindowObject&, NonnullRefPtrVector&&); + static MediaList* create(HTML::Window&, NonnullRefPtrVector&& media); ~MediaList() = default; - MediaList& impl() { return *this; } - String media_text() const; void set_media_text(String const&); size_t length() const { return m_media.size(); } @@ -42,12 +37,11 @@ public: bool matches() const; private: + explicit MediaList(HTML::Window&, NonnullRefPtrVector&&); + NonnullRefPtrVector m_media; }; } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::MediaList& object) { return &object; } -using MediaListWrapper = Web::CSS::MediaList; -} +WRAPPER_HACK(MediaList, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp b/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp index 74caf27013297c83c816ec30ffa5257873865791..bbcf17a2646a5e4befa5a82e5c00869252bffb85 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include #include @@ -14,14 +14,26 @@ namespace Web::CSS { +JS::NonnullGCPtr MediaQueryList::create(DOM::Document& document, NonnullRefPtrVector&& media) +{ + return *document.heap().allocate(document.realm(), document, move(media)); +} + MediaQueryList::MediaQueryList(DOM::Document& document, NonnullRefPtrVector&& media) - : DOM::EventTarget() + : DOM::EventTarget(document.realm()) , m_document(document) , m_media(move(media)) { + set_prototype(&document.window().ensure_web_prototype("MediaQueryList")); evaluate(); } +void MediaQueryList::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_document.ptr()); +} + // https://drafts.csswg.org/cssom-view/#dom-mediaquerylist-media String MediaQueryList::media() const { @@ -40,9 +52,6 @@ bool MediaQueryList::matches() const bool MediaQueryList::evaluate() { - if (!m_document) - return false; - bool now_matches = false; for (auto& media : m_media) { now_matches = now_matches || media.evaluate(m_document->window()); @@ -51,11 +60,6 @@ bool MediaQueryList::evaluate() return now_matches; } -JS::Object* MediaQueryList::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - // https://www.w3.org/TR/cssom-view/#dom-mediaquerylist-addlistener void MediaQueryList::add_listener(DOM::IDLEventListener* listener) { diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryList.h b/Userland/Libraries/LibWeb/CSS/MediaQueryList.h index 71f88439bb7983ab5d3d72a1ddaa69ab19ac7f9b..a302425c933f84d412b05dd74fcbeb27d246d185 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryList.h +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryList.h @@ -17,22 +17,11 @@ namespace Web::CSS { // 4.2. The MediaQueryList Interface, https://drafts.csswg.org/cssom-view/#the-mediaquerylist-interface -class MediaQueryList final - : public RefCounted - , public Weakable - , public DOM::EventTarget - , public Bindings::Wrappable { +class MediaQueryList final : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(MediaQueryList, DOM::EventTarget); public: - using WrapperType = Bindings::MediaQueryListWrapper; - - using RefCounted::ref; - using RefCounted::unref; - - static NonnullRefPtr create(DOM::Document& document, NonnullRefPtrVector&& media_queries) - { - return adopt_ref(*new MediaQueryList(document, move(media_queries))); - } + static JS::NonnullGCPtr create(DOM::Document&, NonnullRefPtrVector&&); virtual ~MediaQueryList() override = default; @@ -40,11 +29,6 @@ public: bool matches() const; bool evaluate(); - // ^EventTarget - virtual void ref_event_target() override { ref(); } - virtual void unref_event_target() override { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; - void add_listener(DOM::IDLEventListener*); void remove_listener(DOM::IDLEventListener*); @@ -54,14 +38,12 @@ public: private: MediaQueryList(DOM::Document&, NonnullRefPtrVector&&); - WeakPtr m_document; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr m_document; NonnullRefPtrVector m_media; }; } -namespace Web::Bindings { - -MediaQueryListWrapper* wrap(JS::Realm&, CSS::MediaQueryList&); - -} +WRAPPER_HACK(MediaQueryList, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp index ed16e9d712073906a97b621870aff127045c7923..6bd7b37606fae97452fa309f17fa318da66b8f1d 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp @@ -5,22 +5,22 @@ */ #include -#include #include +#include namespace Web::CSS { -MediaQueryListEvent* MediaQueryListEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init) +MediaQueryListEvent* MediaQueryListEvent::create(HTML::Window& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init) { return window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); } -MediaQueryListEvent* MediaQueryListEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init) +MediaQueryListEvent* MediaQueryListEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init) { return create(window_object, event_name, event_init); } -MediaQueryListEvent::MediaQueryListEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init) +MediaQueryListEvent::MediaQueryListEvent(HTML::Window& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init) : DOM::Event(window_object, event_name, event_init) , m_media(event_init.media) , m_matches(event_init.matches) diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h index e934b9fd50fae5d2f9d3aea89ffce74d55621197..e217559dc44392e9c18719f011d7d3a871e5aff4 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h @@ -16,17 +16,15 @@ struct MediaQueryListEventInit : public DOM::EventInit { }; class MediaQueryListEvent final : public DOM::Event { - JS_OBJECT(MediaQueryListEvent, DOM::Event); + WEB_PLATFORM_OBJECT(MediaQueryListEvent, DOM::Event); public: - static MediaQueryListEvent* create(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init = {}); - static MediaQueryListEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init); + static MediaQueryListEvent* create(HTML::Window&, FlyString const& event_name, MediaQueryListEventInit const& event_init = {}); + static MediaQueryListEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, MediaQueryListEventInit const& event_init); - MediaQueryListEvent(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init); + MediaQueryListEvent(HTML::Window&, FlyString const& event_name, MediaQueryListEventInit const& event_init); virtual ~MediaQueryListEvent() override; - MediaQueryListEvent& impl() { return *this; } - String const& media() const { return m_media; } bool matches() const { return m_matches; } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index dd3cf53e55606c1f7d50fd5df99252e08b6dc562..dae4505fe68fbe478069d21b436d9585d0f68222 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -44,27 +44,27 @@ ParsingContext::ParsingContext() { } -ParsingContext::ParsingContext(Bindings::WindowObject& window_object) +ParsingContext::ParsingContext(HTML::Window& window_object) : m_window_object(window_object) { } ParsingContext::ParsingContext(DOM::Document const& document, AK::URL url) - : m_window_object(document.preferred_window_object()) + : m_window_object(const_cast(document.window())) , m_document(&document) , m_url(move(url)) { } ParsingContext::ParsingContext(DOM::Document const& document) - : m_window_object(document.preferred_window_object()) + : m_window_object(const_cast(document.window())) , m_document(&document) , m_url(document.url()) { } ParsingContext::ParsingContext(DOM::ParentNode& parent_node) - : m_window_object(parent_node.document().preferred_window_object()) + : m_window_object(parent_node.document().window()) , m_document(&parent_node.document()) , m_url(parent_node.document().url()) { diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 088756d81afdca4fd7fdb8f38b5bca8967d8a17d..004e665da86d53825b3720863ce708670e7099a2 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -35,7 +35,7 @@ namespace Web::CSS::Parser { class ParsingContext { public: ParsingContext(); - explicit ParsingContext(Bindings::WindowObject&); + explicit ParsingContext(HTML::Window&); explicit ParsingContext(DOM::Document const&); explicit ParsingContext(DOM::Document const&, AK::URL); explicit ParsingContext(DOM::ParentNode&); @@ -47,10 +47,10 @@ public: PropertyID current_property_id() const { return m_current_property_id; } void set_current_property_id(PropertyID property_id) { m_current_property_id = property_id; } - Bindings::WindowObject& window_object() const { return m_window_object; } + HTML::Window& window_object() const { return m_window_object; } private: - Bindings::WindowObject& m_window_object; + HTML::Window& m_window_object; DOM::Document const* m_document { nullptr }; PropertyID m_current_property_id { PropertyID::Invalid }; AK::URL m_url; diff --git a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp index 061214295b9e082d2c5873a522d4c41386cd2832..d52749ce0cad270e8b5ca967fbb54951eba49416 100644 --- a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp +++ b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp @@ -21,16 +21,22 @@ namespace Web::CSS { ResolvedCSSStyleDeclaration* ResolvedCSSStyleDeclaration::create(DOM::Element& element) { - auto& window_object = element.document().preferred_window_object(); + auto& window_object = element.document().window(); return window_object.heap().allocate(window_object.realm(), element); } ResolvedCSSStyleDeclaration::ResolvedCSSStyleDeclaration(DOM::Element& element) - : CSSStyleDeclaration(element.document().preferred_window_object()) + : CSSStyleDeclaration(element.document().window()) , m_element(element) { } +void ResolvedCSSStyleDeclaration::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_element.ptr()); +} + size_t ResolvedCSSStyleDeclaration::length() const { return 0; diff --git a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.h b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.h index 285e853bfd0313762d88b039e02e1ec682626157..f1bd202117607d0dede783a62293866fcd3dc26a 100644 --- a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.h +++ b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.h @@ -11,7 +11,7 @@ namespace Web::CSS { class ResolvedCSSStyleDeclaration final : public CSSStyleDeclaration { - JS_OBJECT(ResolvedCSSStyleDeclaration, CSSStyleDeclaration); + WEB_PLATFORM_OBJECT(ResolvedCSSStyleDeclaration, CSSStyleDeclaration); public: static ResolvedCSSStyleDeclaration* create(DOM::Element& element); @@ -28,9 +28,11 @@ public: virtual String serialized() const override; private: + virtual void visit_edges(Cell::Visitor&) override; + RefPtr style_value_for_property(Layout::NodeWithStyle const&, PropertyID) const; - NonnullRefPtr m_element; + JS::NonnullGCPtr m_element; }; } diff --git a/Userland/Libraries/LibWeb/CSS/Screen.cpp b/Userland/Libraries/LibWeb/CSS/Screen.cpp index 42ec7256024371bf51449da9deee77ea31d446fa..b4458e72566dd17eff54b130ce4f669159916e09 100644 --- a/Userland/Libraries/LibWeb/CSS/Screen.cpp +++ b/Userland/Libraries/LibWeb/CSS/Screen.cpp @@ -12,7 +12,7 @@ namespace Web::CSS { Screen::Screen(HTML::Window& window) - : RefCountForwarder(window) + : m_window(JS::make_handle(window)) { } diff --git a/Userland/Libraries/LibWeb/CSS/Screen.h b/Userland/Libraries/LibWeb/CSS/Screen.h index ea6de94951b1fd3153d5fe7d2411064d9797a013..ce0e1abd9e2f0cb2a17dcac95f2933904c77415e 100644 --- a/Userland/Libraries/LibWeb/CSS/Screen.h +++ b/Userland/Libraries/LibWeb/CSS/Screen.h @@ -15,7 +15,7 @@ namespace Web::CSS { class Screen final - : public RefCountForwarder + : public RefCounted , public Bindings::Wrappable { public: @@ -37,9 +37,11 @@ public: private: explicit Screen(HTML::Window&); - HTML::Window const& window() const { return ref_count_target(); } + HTML::Window const& window() const { return *m_window; } Gfx::IntRect screen_rect() const; + + JS::Handle m_window; }; } diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp b/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp index ae5d52088973afa8fb8a21cd03cf777e98b7cd5c..894d0cdf857f4475378f7952b50bb89d699013c9 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp @@ -6,14 +6,14 @@ */ #include -#include #include #include #include +#include namespace Web::CSS { -StyleSheet::StyleSheet(Bindings::WindowObject& window_object) +StyleSheet::StyleSheet(HTML::Window& window_object) : PlatformObject(window_object.ensure_web_prototype("StyleSheet")) { } diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheet.h b/Userland/Libraries/LibWeb/CSS/StyleSheet.h index 5c5d2ff466bd2caa4d8efe46c1bd79f3f0f5cfcb..3304962b9d2ce111e521960f841b7d3482ed0180 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleSheet.h +++ b/Userland/Libraries/LibWeb/CSS/StyleSheet.h @@ -13,11 +13,9 @@ namespace Web::CSS { class StyleSheet : public Bindings::PlatformObject { - JS_OBJECT(StyleSheet, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(StyleSheet, Bindings::PlatformObject); public: - StyleSheet& impl() { return *this; } - virtual ~StyleSheet() = default; virtual String type() const = 0; @@ -48,7 +46,7 @@ public: void set_parent_css_style_sheet(CSSStyleSheet*); protected: - explicit StyleSheet(Bindings::WindowObject&); + explicit StyleSheet(HTML::Window&); virtual void visit_edges(Cell::Visitor&) override; private: @@ -68,7 +66,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::StyleSheet& object) { return &object; } -using StyleSheetWrapper = Web::CSS::StyleSheet; -} +WRAPPER_HACK(StyleSheet, Web::CSS) diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp b/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp index c61fd64874650564ae57e67993cb8d406e56cd5b..bcb3f470f9aa8f2cea7354435e28f9f594f5b4ca 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp @@ -31,12 +31,12 @@ void StyleSheetList::remove_sheet(CSSStyleSheet& sheet) StyleSheetList* StyleSheetList::create(DOM::Document& document) { - auto& realm = document.preferred_window_object().realm(); + auto& realm = document.window().realm(); return realm.heap().allocate(realm, document); } StyleSheetList::StyleSheetList(DOM::Document& document) - : Bindings::LegacyPlatformObject(document.preferred_window_object().ensure_web_prototype("StyleSheetList")) + : Bindings::LegacyPlatformObject(document.window().ensure_web_prototype("StyleSheetList")) , m_document(document) { } diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheetList.h b/Userland/Libraries/LibWeb/CSS/StyleSheetList.h index 32e26d54a6aeca4b510b7de32ee4586cac076124..18fa197ef0a532e7641a27dee732b2423b7401c1 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleSheetList.h +++ b/Userland/Libraries/LibWeb/CSS/StyleSheetList.h @@ -16,12 +16,10 @@ namespace Web::CSS { class StyleSheetList : public Bindings::LegacyPlatformObject { - JS_OBJECT(StyleSheetList, Bindings::LegacyPlatformObject); + WEB_PLATFORM_OBJECT(StyleSheetList, Bindings::LegacyPlatformObject); public: - StyleSheetList& impl() { return *this; } static StyleSheetList* create(DOM::Document& document); - explicit StyleSheetList(DOM::Document&); void add_sheet(CSSStyleSheet&); void remove_sheet(CSSStyleSheet&); @@ -45,6 +43,8 @@ public: DOM::Document const& document() const { return m_document; } private: + explicit StyleSheetList(DOM::Document&); + virtual void visit_edges(Cell::Visitor&) override; DOM::Document& m_document; @@ -53,7 +53,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::CSS::StyleSheetList& object) { return &object; } -using StyleSheetListWrapper = Web::CSS::StyleSheetList; -} +WRAPPER_HACK(StyleSheetList, Web::CSS) diff --git a/Userland/Libraries/LibWeb/DOM/AbortController.cpp b/Userland/Libraries/LibWeb/DOM/AbortController.cpp index 4e92ee301e726eecba25206687c1a7e89d886d01..76640bcf27b037b4549bdab06e1809871c556565 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortController.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbortController.cpp @@ -10,8 +10,8 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#dom-abortcontroller-abortcontroller -AbortController::AbortController() - : m_signal(AbortSignal::create()) +AbortController::AbortController(HTML::Window& window) + : m_signal(JS::make_handle(*AbortSignal::create_with_global_object(window))) { } diff --git a/Userland/Libraries/LibWeb/DOM/AbortController.h b/Userland/Libraries/LibWeb/DOM/AbortController.h index dc616ecc671f8b93ff7c1bffc0bdf3d39768b620..bb597309e5d4a91dca76e0566ef9089d41154444 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortController.h +++ b/Userland/Libraries/LibWeb/DOM/AbortController.h @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -24,28 +23,23 @@ class AbortController final public: using WrapperType = Bindings::AbortControllerWrapper; - static NonnullRefPtr create() + static NonnullRefPtr create_with_global_object(HTML::Window& window) { - return adopt_ref(*new AbortController()); - } - - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&) - { - return AbortController::create(); + return adopt_ref(*new AbortController(window)); } virtual ~AbortController() override = default; // https://dom.spec.whatwg.org/#dom-abortcontroller-signal - NonnullRefPtr signal() const { return m_signal; } + JS::NonnullGCPtr signal() const { return *m_signal; } void abort(JS::Value reason); private: - AbortController(); + explicit AbortController(HTML::Window&); // https://dom.spec.whatwg.org/#abortcontroller-signal - NonnullRefPtr m_signal; + JS::Handle m_signal; }; } diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp index dc28fb3d11144fa3138fed5bedbf261845a4cdaf..a4cf9b4269875aa0bcf2d02c62df09ecbf2770f6 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp @@ -4,7 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include #include #include @@ -14,14 +13,14 @@ namespace Web::DOM { -AbortSignal::AbortSignal() - : EventTarget() +JS::NonnullGCPtr AbortSignal::create_with_global_object(HTML::Window& window) { + return *window.heap().allocate(window.realm(), window); } -JS::Object* AbortSignal::create_wrapper(JS::Realm& realm) +AbortSignal::AbortSignal(HTML::Window& window) + : EventTarget(window.realm()) { - return wrap(realm, *this); } // https://dom.spec.whatwg.org/#abortsignal-add @@ -38,10 +37,6 @@ void AbortSignal::add_abort_algorithm(Function abort_algorithm) // https://dom.spec.whatwg.org/#abortsignal-signal-abort void AbortSignal::signal_abort(JS::Value reason) { - VERIFY(wrapper()); - auto& vm = wrapper()->vm(); - auto& realm = *vm.current_realm(); - // 1. If signal is aborted, then return. if (aborted()) return; @@ -50,7 +45,7 @@ void AbortSignal::signal_abort(JS::Value reason) if (!reason.is_undefined()) m_abort_reason = reason; else - m_abort_reason = wrap(realm, AbortError::create("Aborted without reason")); + m_abort_reason = wrap(realm(), AbortError::create("Aborted without reason")); // 3. For each algorithm in signal’s abort algorithms: run algorithm. for (auto& algorithm : m_abort_algorithms) @@ -60,7 +55,7 @@ void AbortSignal::signal_abort(JS::Value reason) m_abort_algorithms.clear(); // 5. Fire an event named abort at signal. - dispatch_event(*Event::create(verify_cast(wrapper()->global_object()), HTML::EventNames::abort)); + dispatch_event(*Event::create(global_object(), HTML::EventNames::abort)); } void AbortSignal::set_onabort(Bindings::CallbackType* event_handler) @@ -85,6 +80,7 @@ JS::ThrowCompletionOr AbortSignal::throw_if_aborted() const void AbortSignal::visit_edges(JS::Cell::Visitor& visitor) { + Base::visit_edges(visitor); visitor.visit(m_abort_reason); } diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.h b/Userland/Libraries/LibWeb/DOM/AbortSignal.h index 3166e87a67dc518b6a8d5ee7cce5176a26d2e158..572a8d453d0207c73a01d501f52ece8a34cfcf7e 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.h +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.h @@ -16,26 +16,11 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#abortsignal -class AbortSignal final - : public RefCounted - , public Weakable - , public EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::AbortSignalWrapper; - - using RefCounted::ref; - using RefCounted::unref; +class AbortSignal final : public EventTarget { + WEB_PLATFORM_OBJECT(AbortSignal, EventTarget); - static NonnullRefPtr create() - { - return adopt_ref(*new AbortSignal()); - } - - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&) - { - return AbortSignal::create(); - } +public: + static JS::NonnullGCPtr create_with_global_object(HTML::Window&); virtual ~AbortSignal() override = default; @@ -55,15 +40,10 @@ public: JS::ThrowCompletionOr throw_if_aborted() const; - void visit_edges(JS::Cell::Visitor&); - - // ^EventTarget - virtual void ref_event_target() override { ref(); } - virtual void unref_event_target() override { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; - private: - AbortSignal(); + explicit AbortSignal(HTML::Window&); + + virtual void visit_edges(JS::Cell::Visitor&) override; // https://dom.spec.whatwg.org/#abortsignal-abort-reason // An AbortSignal object has an associated abort reason, which is a JavaScript value. It is undefined unless specified otherwise. @@ -75,3 +55,5 @@ private: }; } + +WRAPPER_HACK(AbortSignal, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp b/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp index 357a0da71fb38e939ca931817929ea5ec4be09ce..28e45ba65ead4d9dec3942fdd0010d2b76593683 100644 --- a/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp @@ -5,14 +5,14 @@ */ #include -#include #include #include +#include namespace Web::DOM { AbstractRange::AbstractRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset) - : Bindings::PlatformObject(start_container.document().preferred_window_object().ensure_web_prototype("AbstractRange")) + : Bindings::PlatformObject(start_container.document().window().ensure_web_prototype("AbstractRange")) , m_start_container(start_container) , m_start_offset(start_offset) , m_end_container(end_container) @@ -22,4 +22,11 @@ AbstractRange::AbstractRange(Node& start_container, u32 start_offset, Node& end_ AbstractRange::~AbstractRange() = default; +void AbstractRange::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_start_container.ptr()); + visitor.visit(m_end_container.ptr()); +} + } diff --git a/Userland/Libraries/LibWeb/DOM/AbstractRange.h b/Userland/Libraries/LibWeb/DOM/AbstractRange.h index e0dded63728ac95998512f9f01e50b8720db2636..ae97dc54be4c3917674ed99dbdadc7a69cfd2381 100644 --- a/Userland/Libraries/LibWeb/DOM/AbstractRange.h +++ b/Userland/Libraries/LibWeb/DOM/AbstractRange.h @@ -13,19 +13,17 @@ namespace Web::DOM { class AbstractRange : public Bindings::PlatformObject { - JS_OBJECT(AbstractRange, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(AbstractRange, Bindings::PlatformObject); public: virtual ~AbstractRange() override; - AbstractRange& impl() { return *this; } - - Node* start_container() { return m_start_container; } - Node const* start_container() const { return m_start_container; } + Node* start_container() { return m_start_container.ptr(); } + Node const* start_container() const { return m_start_container.ptr(); } unsigned start_offset() const { return m_start_offset; } - Node* end_container() { return m_end_container; } - Node const* end_container() const { return m_end_container; } + Node* end_container() { return m_end_container.ptr(); } + Node const* end_container() const { return m_end_container.ptr(); } unsigned end_offset() const { return m_end_offset; } // https://dom.spec.whatwg.org/#range-collapsed @@ -38,10 +36,12 @@ public: protected: AbstractRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset); - NonnullRefPtr m_start_container; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr m_start_container; u32 m_start_offset; - NonnullRefPtr m_end_container; + JS::NonnullGCPtr m_end_container; u32 m_end_offset; }; diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.cpp b/Userland/Libraries/LibWeb/DOM/Attribute.cpp index da29d7cdc068ffc52703ad102a9ddf126655b3b4..122e3d1ce3d6e59f2a3639608859935ceaec5289 100644 --- a/Userland/Libraries/LibWeb/DOM/Attribute.cpp +++ b/Userland/Libraries/LibWeb/DOM/Attribute.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -12,9 +13,9 @@ namespace Web::DOM { -NonnullRefPtr Attribute::create(Document& document, FlyString local_name, String value, Element const* owner_element) +JS::NonnullGCPtr Attribute::create(Document& document, FlyString local_name, String value, Element const* owner_element) { - return adopt_ref(*new Attribute(document, move(local_name), move(value), owner_element)); + return *document.heap().allocate(document.realm(), document, move(local_name), move(value), owner_element); } Attribute::Attribute(Document& document, FlyString local_name, String value, Element const* owner_element) @@ -23,16 +24,23 @@ Attribute::Attribute(Document& document, FlyString local_name, String value, Ele , m_value(move(value)) , m_owner_element(owner_element) { + set_prototype(&window().ensure_web_prototype("Attribute")); +} + +void Attribute::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_owner_element.ptr()); } Element* Attribute::owner_element() { - return m_owner_element; + return m_owner_element.ptr(); } Element const* Attribute::owner_element() const { - return m_owner_element; + return m_owner_element.ptr(); } void Attribute::set_owner_element(Element const* owner_element) diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.h b/Userland/Libraries/LibWeb/DOM/Attribute.h index 1431d3083b56c8ed5b162e4040ad5aace18f8a9c..4f9787fb0b5e7ecf43e3ebd3aa479aa497c8b68d 100644 --- a/Userland/Libraries/LibWeb/DOM/Attribute.h +++ b/Userland/Libraries/LibWeb/DOM/Attribute.h @@ -15,10 +15,10 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#attr class Attribute final : public Node { -public: - using WrapperType = Bindings::AttributeWrapper; + WEB_PLATFORM_OBJECT(Attribute, Node); - static NonnullRefPtr create(Document&, FlyString local_name, String value, Element const* = nullptr); +public: + static JS::NonnullGCPtr create(Document&, FlyString local_name, String value, Element const* = nullptr); virtual ~Attribute() override = default; @@ -44,12 +44,16 @@ public: private: Attribute(Document&, FlyString local_name, String value, Element const*); + virtual void visit_edges(Cell::Visitor&) override; + QualifiedName m_qualified_name; String m_value; - WeakPtr m_owner_element; + JS::GCPtr m_owner_element; }; template<> inline bool Node::fast_is() const { return is_attribute(); } } + +WRAPPER_HACK(Attribute, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/CDATASection.cpp b/Userland/Libraries/LibWeb/DOM/CDATASection.cpp index bce61e89c34dca25606f675fa500958ce171611a..5203875e96b1dcff24322c956b3e96b7bc1656b1 100644 --- a/Userland/Libraries/LibWeb/DOM/CDATASection.cpp +++ b/Userland/Libraries/LibWeb/DOM/CDATASection.cpp @@ -4,17 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::DOM { CDATASection::CDATASection(Document& document, String const& data) : Text(document, NodeType::CDATA_SECTION_NODE, data) { + set_prototype(&window().ensure_web_prototype("CDATASection")); } -CDATASection::~CDATASection() -{ -} +CDATASection::~CDATASection() = default; } diff --git a/Userland/Libraries/LibWeb/DOM/CDATASection.h b/Userland/Libraries/LibWeb/DOM/CDATASection.h index bf57d3fad0574c635254839ccc24987e86e58b16..a5b18c0cc0756e34724d9d406e7ed5d98a565814 100644 --- a/Userland/Libraries/LibWeb/DOM/CDATASection.h +++ b/Userland/Libraries/LibWeb/DOM/CDATASection.h @@ -12,17 +12,21 @@ namespace Web::DOM { class CDATASection final : public Text { -public: - using WrapperType = Bindings::CDATASectionWrapper; + WEB_PLATFORM_OBJECT(Text, CDATASection); - CDATASection(Document&, String const&); +public: virtual ~CDATASection() override; // ^Node virtual FlyString node_name() const override { return "#cdata-section"; } + +private: + CDATASection(Document&, String const&); }; template<> inline bool Node::fast_is() const { return is_cdata_section(); } } + +WRAPPER_HACK(CDATASection, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp index ab1e1342716bea773315c09aa7ca87b7550f2bcf..929d4774904b09a5559c3c2e1a48b6d8ab8ad78c 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -16,6 +17,7 @@ CharacterData::CharacterData(Document& document, NodeType type, String const& da : Node(document, type) , m_data(data) { + set_prototype(&window().ensure_web_prototype("CharacterData")); } // https://dom.spec.whatwg.org/#dom-characterdata-data diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.h b/Userland/Libraries/LibWeb/DOM/CharacterData.h index 5765ee3f3da8521002a1238df60e4663ed2bd69e..481ed6bf690dc2423f67cab46fd866729c968b73 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.h +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.h @@ -17,9 +17,9 @@ class CharacterData : public Node , public ChildNode , public NonDocumentTypeChildNode { -public: - using WrapperType = Bindings::CharacterDataWrapper; + WEB_PLATFORM_OBJECT(CharacterData, Node); +public: virtual ~CharacterData() override = default; String const& data() const { return m_data; } @@ -41,3 +41,4 @@ private: }; } +WRAPPER_HACK(CharacterData, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/ChildNode.h b/Userland/Libraries/LibWeb/DOM/ChildNode.h index 4493e41afb5c06a21c4a011da3cf9957eb712084..ca7b48ae1d61c372b5aae4d29cc0907e441cf2cd 100644 --- a/Userland/Libraries/LibWeb/DOM/ChildNode.h +++ b/Userland/Libraries/LibWeb/DOM/ChildNode.h @@ -16,7 +16,7 @@ template class ChildNode { public: // https://dom.spec.whatwg.org/#dom-childnode-before - ExceptionOr before(Vector, String>> const& nodes) + ExceptionOr before(Vector, String>> const& nodes) { auto* node = static_cast(this); @@ -46,7 +46,7 @@ public: } // https://dom.spec.whatwg.org/#dom-childnode-after - ExceptionOr after(Vector, String>> const& nodes) + ExceptionOr after(Vector, String>> const& nodes) { auto* node = static_cast(this); @@ -70,7 +70,7 @@ public: } // https://dom.spec.whatwg.org/#dom-childnode-replacewith - ExceptionOr replace_with(Vector, String>> const& nodes) + ExceptionOr replace_with(Vector, String>> const& nodes) { auto* node = static_cast(this); @@ -117,7 +117,7 @@ protected: ChildNode() = default; private: - RefPtr viable_previous_sibling_for_insertion(Vector, String>> const& nodes) const + JS::GCPtr viable_previous_sibling_for_insertion(Vector, String>> const& nodes) const { auto* node = static_cast(this); @@ -125,11 +125,11 @@ private: bool contained_in_nodes = false; for (auto const& node_or_string : nodes) { - if (!node_or_string.template has>()) + if (!node_or_string.template has>()) continue; - auto node_in_vector = node_or_string.template get>(); - if (node_in_vector.ptr() == previous_sibling) { + auto node_in_vector = node_or_string.template get>(); + if (node_in_vector.cell() == previous_sibling) { contained_in_nodes = true; break; } @@ -142,7 +142,7 @@ private: return nullptr; } - RefPtr viable_nest_sibling_for_insertion(Vector, String>> const& nodes) const + JS::GCPtr viable_nest_sibling_for_insertion(Vector, String>> const& nodes) const { auto* node = static_cast(this); @@ -150,11 +150,11 @@ private: bool contained_in_nodes = false; for (auto const& node_or_string : nodes) { - if (!node_or_string.template has>()) + if (!node_or_string.template has>()) continue; - auto node_in_vector = node_or_string.template get>(); - if (node_in_vector.ptr() == next_sibling) { + auto& node_in_vector = node_or_string.template get>(); + if (node_in_vector.cell() == next_sibling) { contained_in_nodes = true; break; } diff --git a/Userland/Libraries/LibWeb/DOM/Comment.cpp b/Userland/Libraries/LibWeb/DOM/Comment.cpp index 9e79dd586995bc9fdbfd7c54d5301a30dde3de93..b442edc0b2a0a37b04e095e2059f1c03424e2c4b 100644 --- a/Userland/Libraries/LibWeb/DOM/Comment.cpp +++ b/Userland/Libraries/LibWeb/DOM/Comment.cpp @@ -16,9 +16,9 @@ Comment::Comment(Document& document, String const& data) } // https://dom.spec.whatwg.org/#dom-comment-comment -NonnullRefPtr Comment::create_with_global_object(Bindings::WindowObject& window, String const& data) +JS::NonnullGCPtr Comment::create_with_global_object(HTML::Window& window, String const& data) { - return make_ref_counted(window.impl().associated_document(), data); + return *window.heap().allocate(window.realm(), window.associated_document(), data); } } diff --git a/Userland/Libraries/LibWeb/DOM/Comment.h b/Userland/Libraries/LibWeb/DOM/Comment.h index 9696a3113785efb01ed8239d3822131c01b15d75..9f4c37ef3d65ab7f21d860d3d3c37fedf2798d1d 100644 --- a/Userland/Libraries/LibWeb/DOM/Comment.h +++ b/Userland/Libraries/LibWeb/DOM/Comment.h @@ -12,18 +12,21 @@ namespace Web::DOM { class Comment final : public CharacterData { -public: - using WrapperType = Bindings::CommentWrapper; + WEB_PLATFORM_OBJECT(Comment, CharacterData); - explicit Comment(Document&, String const&); +public: + static JS::NonnullGCPtr create_with_global_object(HTML::Window&, String const& data); virtual ~Comment() override = default; virtual FlyString node_name() const override { return "#comment"; } - static NonnullRefPtr create_with_global_object(Bindings::WindowObject& window, String const& data); +private: + explicit Comment(Document&, String const&); }; template<> inline bool Node::fast_is() const { return is_comment(); } } + +WRAPPER_HACK(Comment, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp index 1d5aefb56e7d91e1fd67c3c967f24cac0c66e849..0cf777aa74f314a457227bfafedd4dbfa1fe7062 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp @@ -6,28 +6,28 @@ */ #include -#include #include +#include namespace Web::DOM { -CustomEvent* CustomEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init) +CustomEvent* CustomEvent::create(HTML::Window& window_object, FlyString const& event_name, CustomEventInit const& event_init) { return window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); } -CustomEvent* CustomEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init) +CustomEvent* CustomEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, CustomEventInit const& event_init) { return create(window_object, event_name, event_init); } -CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name) +CustomEvent::CustomEvent(HTML::Window& window_object, FlyString const& event_name) : Event(window_object, event_name) { set_prototype(&window_object.ensure_web_prototype("CustomEvent")); } -CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init) +CustomEvent::CustomEvent(HTML::Window& window_object, FlyString const& event_name, CustomEventInit const& event_init) : Event(window_object, event_name, event_init) , m_detail(event_init.detail) { diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.h b/Userland/Libraries/LibWeb/DOM/CustomEvent.h index 5111b346be345fd942748107026994ee42146b72..50cfd7b63a22923ea56e4fdaeaa588263a7b9e57 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.h +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.h @@ -17,19 +17,17 @@ struct CustomEventInit : public EventInit { // https://dom.spec.whatwg.org/#customevent class CustomEvent : public Event { - JS_OBJECT(CustomEvent, Event); + WEB_PLATFORM_OBJECT(CustomEvent, Event); public: - static CustomEvent* create(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init = {}); - static CustomEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init); + static CustomEvent* create(HTML::Window&, FlyString const& event_name, CustomEventInit const& event_init = {}); + static CustomEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, CustomEventInit const& event_init); - CustomEvent(Bindings::WindowObject&, FlyString const& event_name); - CustomEvent(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init); + CustomEvent(HTML::Window&, FlyString const& event_name); + CustomEvent(HTML::Window&, FlyString const& event_name, CustomEventInit const& event_init); virtual ~CustomEvent() override; - CustomEvent& impl() { return *this; } - // https://dom.spec.whatwg.org/#dom-customevent-detail JS::Value detail() const { return m_detail; } diff --git a/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp b/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp index 29c53a1b59e97dbb683ebebf4d914fb27a84d88e..8ad08a11a1c10d5fef0e845c192abf5529e72201 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp @@ -17,6 +17,7 @@ void DOMEventListener::visit_edges(Cell::Visitor& visitor) { Cell::visit_edges(visitor); visitor.visit(callback.ptr()); + visitor.visit(signal.ptr()); } } diff --git a/Userland/Libraries/LibWeb/DOM/DOMEventListener.h b/Userland/Libraries/LibWeb/DOM/DOMEventListener.h index a5a9b5d5d55aa23b10382a906a104a789a2f1813..87a3b744a8dd07ecb4f6359aab7c1e391bf04973 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMEventListener.h +++ b/Userland/Libraries/LibWeb/DOM/DOMEventListener.h @@ -27,7 +27,7 @@ public: JS::GCPtr callback; // signal (null or an AbortSignal object) - RefPtr signal; + JS::GCPtr signal; // capture (a boolean, initially false) bool capture { false }; diff --git a/Userland/Libraries/LibWeb/DOM/DOMException.h b/Userland/Libraries/LibWeb/DOM/DOMException.h index d3f113e1090875f21e994ffb3974df69377b7f9d..8240a300a97db10766bedeade9fbfb930028729f 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMException.h +++ b/Userland/Libraries/LibWeb/DOM/DOMException.h @@ -111,7 +111,7 @@ public: } // JS constructor has message first, name second - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&, FlyString const& message, FlyString const& name) + static NonnullRefPtr create_with_global_object(HTML::Window&, FlyString const& message, FlyString const& name) { return adopt_ref(*new DOMException(name, message)); } diff --git a/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp b/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp index 2216cc2f463e2b559d3f940a03343d171681951f..afe7045c95937ffb46c1af4c0f3d83dc6b6d7557 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp @@ -6,25 +6,26 @@ */ #include -#include +#include #include #include #include #include #include #include +#include #include namespace Web::DOM { JS::NonnullGCPtr DOMImplementation::create(Document& document) { - auto& window_object = document.preferred_window_object(); - return *window_object.heap().allocate(window_object.realm(), document); + auto& window = document.window(); + return *window.heap().allocate(document.realm(), document); } DOMImplementation::DOMImplementation(Document& document) - : PlatformObject(document.preferred_window_object().ensure_web_prototype("DOMImplementation")) + : PlatformObject(document.window().ensure_web_prototype("DOMImplementation")) , m_document(document) { } @@ -38,23 +39,23 @@ void DOMImplementation::visit_edges(Cell::Visitor& visitor) } // https://dom.spec.whatwg.org/#dom-domimplementation-createdocument -ExceptionOr> DOMImplementation::create_document(String const& namespace_, String const& qualified_name, RefPtr doctype) const +ExceptionOr> DOMImplementation::create_document(String const& namespace_, String const& qualified_name, JS::GCPtr doctype) const { // FIXME: This should specifically be an XML document. - auto xml_document = Document::create(); + auto xml_document = Document::create(Bindings::main_thread_internal_window_object()); xml_document->set_ready_for_post_load_tasks(true); - RefPtr element; + JS::GCPtr element; if (!qualified_name.is_empty()) element = TRY(xml_document->create_element_ns(namespace_, qualified_name /* FIXME: and an empty dictionary */)); if (doctype) - xml_document->append_child(doctype.release_nonnull()); + xml_document->append_child(*doctype); if (element) - xml_document->append_child(element.release_nonnull()); + xml_document->append_child(*element); xml_document->set_origin(document().origin()); @@ -69,16 +70,16 @@ ExceptionOr> DOMImplementation::create_document(String c } // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument -NonnullRefPtr DOMImplementation::create_html_document(String const& title) const +JS::NonnullGCPtr DOMImplementation::create_html_document(String const& title) const { - auto html_document = Document::create(); + auto html_document = Document::create(Bindings::main_thread_internal_window_object()); html_document->set_content_type("text/html"); html_document->set_ready_for_post_load_tasks(true); - auto doctype = adopt_ref(*new DocumentType(html_document)); + auto doctype = heap().allocate(realm(), html_document); doctype->set_name("html"); - html_document->append_child(doctype); + html_document->append_child(*doctype); auto html_element = create_element(html_document, HTML::TagNames::html, Namespace::HTML); html_document->append_child(html_element); @@ -90,8 +91,8 @@ NonnullRefPtr DOMImplementation::create_html_document(String const& ti auto title_element = create_element(html_document, HTML::TagNames::title, Namespace::HTML); head_element->append_child(title_element); - auto text_node = adopt_ref(*new Text(html_document, title)); - title_element->append_child(text_node); + auto text_node = heap().allocate(realm(), html_document, title); + title_element->append_child(*text_node); } auto body_element = create_element(html_document, HTML::TagNames::body, Namespace::HTML); @@ -103,7 +104,7 @@ NonnullRefPtr DOMImplementation::create_html_document(String const& ti } // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype -ExceptionOr> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id) +ExceptionOr> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id) { TRY(Document::validate_qualified_name(qualified_name)); auto document_type = DocumentType::create(document()); diff --git a/Userland/Libraries/LibWeb/DOM/DOMImplementation.h b/Userland/Libraries/LibWeb/DOM/DOMImplementation.h index 136cd83e1bbeba61614e391d7345589048d829ef..9315e459eb24009e7b2964f1753c972a120be296 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMImplementation.h +++ b/Userland/Libraries/LibWeb/DOM/DOMImplementation.h @@ -7,30 +7,29 @@ #pragma once -#include +#include #include #include namespace Web::DOM { class DOMImplementation final : public Bindings::PlatformObject { - JS_OBJECT(DOMImplementation, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(DOMImplementation, Bindings::PlatformObject); public: static JS::NonnullGCPtr create(Document&); - explicit DOMImplementation(Document&); virtual ~DOMImplementation(); - DOMImplementation& impl() { return *this; } - - ExceptionOr> create_document(String const&, String const&, RefPtr) const; - NonnullRefPtr create_html_document(String const& title) const; - ExceptionOr> create_document_type(String const& qualified_name, String const& public_id, String const& system_id); + ExceptionOr> create_document(String const&, String const&, JS::GCPtr) const; + JS::NonnullGCPtr create_html_document(String const& title) const; + ExceptionOr> create_document_type(String const& qualified_name, String const& public_id, String const& system_id); // https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature bool has_feature() const { return true; } private: + explicit DOMImplementation(Document&); + virtual void visit_edges(Cell::Visitor&) override; Document& document() { return m_document; } @@ -41,7 +40,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::DOM::DOMImplementation& object) { return &object; } -using DOMImplementationWrapper = Web::DOM::DOMImplementation; -} +WRAPPER_HACK(DOMImplementation, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp b/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp index 4b3575920f37e24b63324f4d6e90bf52deb15e32..439d9a36064d51356efa1fa78200f7621a97b411 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp @@ -8,11 +8,11 @@ #include #include #include -#include #include #include #include #include +#include namespace { @@ -56,13 +56,13 @@ namespace Web::DOM { DOMTokenList* DOMTokenList::create(Element const& associated_element, FlyString associated_attribute) { - auto& realm = associated_element.document().preferred_window_object().realm(); + auto& realm = associated_element.document().window().realm(); return realm.heap().allocate(realm, associated_element, move(associated_attribute)); } // https://dom.spec.whatwg.org/#ref-for-domtokenlist%E2%91%A0%E2%91%A2 DOMTokenList::DOMTokenList(Element const& associated_element, FlyString associated_attribute) - : Bindings::LegacyPlatformObject(associated_element.document().preferred_window_object().ensure_web_prototype("DOMTokenList")) + : Bindings::LegacyPlatformObject(associated_element.document().window().ensure_web_prototype("DOMTokenList")) , m_associated_element(associated_element) , m_associated_attribute(move(associated_attribute)) { @@ -225,7 +225,7 @@ String DOMTokenList::value() const // https://dom.spec.whatwg.org/#ref-for-concept-element-attributes-set-value%E2%91%A2 void DOMTokenList::set_value(String value) { - auto associated_element = m_associated_element.strong_ref(); + JS::GCPtr associated_element = m_associated_element.ptr(); if (!associated_element) return; @@ -244,7 +244,7 @@ ExceptionOr DOMTokenList::validate_token(StringView token) const // https://dom.spec.whatwg.org/#concept-dtl-update void DOMTokenList::run_update_steps() { - auto associated_element = m_associated_element.strong_ref(); + JS::GCPtr associated_element = m_associated_element.ptr(); if (!associated_element) return; diff --git a/Userland/Libraries/LibWeb/DOM/DOMTokenList.h b/Userland/Libraries/LibWeb/DOM/DOMTokenList.h index 890caffbc34831b69ab5167c90ebe711277454cc..658a5457cee8c5e41b34300ada969c900c808a6c 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMTokenList.h +++ b/Userland/Libraries/LibWeb/DOM/DOMTokenList.h @@ -20,15 +20,12 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#domtokenlist class DOMTokenList final : public Bindings::LegacyPlatformObject { - JS_OBJECT(DOMTokenList, Bindings::LegacyPlatformObject); + WEB_PLATFORM_OBJECT(DOMTokenList, Bindings::LegacyPlatformObject); public: static DOMTokenList* create(Element const& associated_element, FlyString associated_attribute); - DOMTokenList(Element const& associated_element, FlyString associated_attribute); ~DOMTokenList() = default; - DOMTokenList& impl() { return *this; } - void associated_attribute_changed(StringView value); virtual bool is_supported_property_index(u32 index) const override; @@ -46,6 +43,8 @@ public: void set_value(String value); private: + DOMTokenList(Element const& associated_element, FlyString associated_attribute); + ExceptionOr validate_token(StringView token) const; void run_update_steps(); @@ -56,7 +55,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::DOM::DOMTokenList& object) { return &object; } -using DOMTokenListWrapper = Web::DOM::DOMTokenList; -} +WRAPPER_HACK(DOMTokenList, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index e53ace8fd825030727bd8ec3f27810f89dc9a6f8..dd180b8f4a08ab57a7d9cc98bc67b532d436f65f 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -14,8 +14,9 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -100,7 +101,7 @@ static NonnullRefPtr obtain_a_browsing_context_to_use_for VERIFY(browsing_context.page()); auto new_browsing_context = HTML::BrowsingContext::create_a_new_browsing_context(*browsing_context.page(), nullptr, nullptr); - // FIXME: 4. If navigationCOOP's value is "same-origin-plus-COEP", then set newBrowsingContext's group's + // FIXME: 4. If navigationCOOP's value is "same-origin-plurs-COEP", then set newBrowsingContext's group's // cross-origin isolation mode to either "logical" or "concrete". The choice of which is implementation-defined. // 5. If sandboxFlags is not empty, then: @@ -120,7 +121,7 @@ static NonnullRefPtr obtain_a_browsing_context_to_use_for } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#initialise-the-document-object -NonnullRefPtr Document::create_and_initialize(Type type, String content_type, HTML::NavigationParams navigation_params) +JS::NonnullGCPtr Document::create_and_initialize(Type type, String content_type, HTML::NavigationParams navigation_params) { // 1. Let browsingContext be the result of the obtaining a browsing context to use for a navigation response // given navigationParams's browsing context, navigationParams's final sandboxing flag set, @@ -142,7 +143,7 @@ NonnullRefPtr Document::create_and_initialize(Type type, String conten creation_url = navigation_params.request->current_url(); } - RefPtr window; + JS::GCPtr window; // 5. If browsingContext is still on its initial about:blank Document, // and navigationParams's history handling is "replace", @@ -168,14 +169,12 @@ NonnullRefPtr Document::create_and_initialize(Type type, String conten // 5. Let realm execution context be the result of creating a new JavaScript realm given agent and the following customizations: auto realm_execution_context = Bindings::create_a_new_javascript_realm( Bindings::main_thread_vm(), - [&](JS::Realm& realm) -> JS::GlobalObject* { + [&](JS::Realm& realm) -> JS::Object* { // - For the global object, create a new Window object. - window = HTML::Window::create(); - auto* global_object = realm.heap().allocate_without_realm(realm, *window); - VERIFY(window->wrapper() == global_object); - return global_object; + window = HTML::Window::create(realm); + return window; }, - [](JS::Realm&) -> JS::GlobalObject* { + [](JS::Realm&) -> JS::Object* { // FIXME: - For the global this binding, use browsingContext's WindowProxy object. return nullptr; }); @@ -223,7 +222,7 @@ NonnullRefPtr Document::create_and_initialize(Type type, String conten // FIXME: and cross-origin opener policy is navigationParams's cross-origin opener policy, // FIXME: load timing info is loadTimingInfo, // FIXME: and navigation id is navigationParams's id. - auto document = Document::create(); + auto document = Document::create(*window); document->m_type = type; document->m_content_type = content_type; document->set_origin(navigation_params.origin); @@ -266,24 +265,25 @@ NonnullRefPtr Document::create_and_initialize(Type type, String conten return document; } -NonnullRefPtr Document::create_with_global_object(Bindings::WindowObject&) +JS::NonnullGCPtr Document::create_with_global_object(HTML::Window& window) { - return Document::create(); + return Document::create(window); } -NonnullRefPtr Document::create(AK::URL const& url) +JS::NonnullGCPtr Document::create(HTML::Window& window, AK::URL const& url) { - return adopt_ref(*new Document(url)); + auto& realm = window.realm(); + return *realm.heap().allocate(realm, window, url); } -Document::Document(const AK::URL& url) - : ParentNode(*this, NodeType::DOCUMENT_NODE) +Document::Document(HTML::Window& window, const AK::URL& url) + : ParentNode(window.realm(), *this, NodeType::DOCUMENT_NODE) , m_style_computer(make(*this)) , m_url(url) - , m_window(HTML::Window::create_with_document(*this)) + , m_window(window) , m_history(HTML::History::create(*this)) { - m_style_sheets = JS::make_handle(CSS::StyleSheetList::create(*this)); + set_prototype(&window.ensure_web_prototype("Document")); HTML::main_thread_event_loop().register_document({}, *this); @@ -296,63 +296,33 @@ Document::Document(const AK::URL& url) }); } -Document::~Document() = default; - -void Document::removed_last_ref() +Document::~Document() { - VERIFY(!ref_count()); - VERIFY(!m_deletion_has_begun); - - if (m_referencing_node_count) { - // The document has reached ref_count==0 but still has nodes keeping it alive. - // At this point, sever all the node links we control. - // If nodes remain elsewhere (e.g JS wrappers), they will keep the document alive. - - // NOTE: This makes sure we stay alive across for the duration of the cleanup below. - increment_referencing_node_count(); - - m_focused_element = nullptr; - m_hovered_node = nullptr; - m_pending_parsing_blocking_script = nullptr; - m_inspected_node = nullptr; - m_scripts_to_execute_when_parsing_has_finished.clear(); - m_scripts_to_execute_as_soon_as_possible.clear(); - m_associated_inert_template_document = nullptr; - - m_interpreter = nullptr; - - { - // Gather up all the descendants of this document and prune them from the tree. - // FIXME: This could definitely be more elegant. - NonnullRefPtrVector descendants; - for_each_in_inclusive_subtree([&](auto& node) { - if (&node != this) - descendants.append(node); - return IterationDecision::Continue; - }); - - for (auto& node : descendants) { - VERIFY(&node.document() == this); - VERIFY(!node.is_document()); - if (node.parent()) { - // We need to suppress mutation observers so that they don't try and queue a microtask for this Document which is in the process of dying, - // which will cause an `!m_in_removed_last_ref` assertion failure when it tries to ref this Document. - node.remove(true); - } - } - } - - m_in_removed_last_ref = false; - decrement_referencing_node_count(); - return; - } + HTML::main_thread_event_loop().unregister_document({}, *this); +} - m_in_removed_last_ref = false; - m_deletion_has_begun = true; +void Document::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_window.ptr()); + visitor.visit(m_style_sheets.ptr()); + visitor.visit(m_hovered_node.ptr()); + visitor.visit(m_inspected_node.ptr()); + visitor.visit(m_active_favicon.ptr()); + visitor.visit(m_focused_element.ptr()); + visitor.visit(m_active_element.ptr()); + visitor.visit(m_implementation.ptr()); + visitor.visit(m_current_script.ptr()); + visitor.visit(m_associated_inert_template_document.ptr()); + visitor.visit(m_pending_parsing_blocking_script.ptr()); - HTML::main_thread_event_loop().unregister_document({}, *this); + for (auto& script : m_scripts_to_execute_when_parsing_has_finished) + visitor.visit(script.ptr()); + for (auto& script : m_scripts_to_execute_as_soon_as_possible) + visitor.visit(script.ptr()); - delete this; + for (auto& node_iterator : m_node_iterators) + visitor.visit(node_iterator); } // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-write @@ -642,14 +612,14 @@ void Document::set_title(String const& title) if (!head_element) return; - RefPtr title_element = head_element->first_child_of_type(); + JS::GCPtr title_element = head_element->first_child_of_type(); if (!title_element) { - title_element = static_ptr_cast(create_element(HTML::TagNames::title).release_value()); + title_element = &static_cast(*create_element(HTML::TagNames::title).release_value()); head_element->append_child(*title_element); } title_element->remove_all_children(true); - title_element->append_child(adopt_ref(*new Text(*this, title))); + title_element->append_child(*heap().allocate(realm(), *this, title)); if (auto* page = this->page()) { if (browsing_context() == &page->top_level_browsing_context()) @@ -725,13 +695,13 @@ Vector const* Document::background_layers() const return &body_layout_node->background_layers(); } -RefPtr Document::first_base_element_with_href_in_tree_order() const +JS::GCPtr Document::first_base_element_with_href_in_tree_order() const { - RefPtr base_element; + JS::GCPtr base_element; for_each_in_subtree_of_type([&base_element](HTML::HTMLBaseElement const& base_element_in_tree) { if (base_element_in_tree.has_attribute(HTML::AttributeNames::href)) { - base_element = base_element_in_tree; + base_element = &base_element_in_tree; return IterationDecision::Break; } @@ -909,7 +879,7 @@ Layout::InitialContainingBlock* Document::layout_node() void Document::set_inspected_node(Node* node) { - if (m_inspected_node == node) + if (m_inspected_node.ptr() == node) return; if (m_inspected_node && m_inspected_node->layout_node()) @@ -943,10 +913,10 @@ static Node* find_common_ancestor(Node* a, Node* b) void Document::set_hovered_node(Node* node) { - if (m_hovered_node == node) + if (m_hovered_node.ptr() == node) return; - RefPtr old_hovered_node = move(m_hovered_node); + JS::GCPtr old_hovered_node = move(m_hovered_node); m_hovered_node = node; if (auto* common_ancestor = find_common_ancestor(old_hovered_node, m_hovered_node)) @@ -1077,13 +1047,6 @@ HTML::EnvironmentSettingsObject& Document::relevant_settings_object() return verify_cast(*realm().host_defined()); } -JS::Realm& Document::realm() -{ - VERIFY(m_window); - VERIFY(m_window->wrapper()); - return m_window->wrapper()->shape().realm(); -} - JS::Interpreter& Document::interpreter() { if (!m_interpreter) { @@ -1115,7 +1078,7 @@ JS::Value Document::run_javascript(StringView source, StringView filename) // https://dom.spec.whatwg.org/#dom-document-createelement // FIXME: This only implements step 6 of the algorithm and does not take in options. -DOM::ExceptionOr> Document::create_element(String const& tag_name) +DOM::ExceptionOr> Document::create_element(String const& tag_name) { if (!is_valid_name(tag_name)) return DOM::InvalidCharacterError::create("Invalid character in tag name."); @@ -1127,7 +1090,7 @@ DOM::ExceptionOr> Document::create_element(String const& // https://dom.spec.whatwg.org/#dom-document-createelementns // https://dom.spec.whatwg.org/#internal-createelementns-steps // FIXME: This only implements step 4 of the algorithm and does not take in options. -DOM::ExceptionOr> Document::create_element_ns(String const& namespace_, String const& qualified_name) +DOM::ExceptionOr> Document::create_element_ns(String const& namespace_, String const& qualified_name) { // 1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract. auto extracted_qualified_name = TRY(validate_and_extract(namespace_, qualified_name)); @@ -1139,19 +1102,19 @@ DOM::ExceptionOr> Document::create_element_ns(String cons return DOM::create_element(*this, extracted_qualified_name.local_name(), extracted_qualified_name.namespace_(), extracted_qualified_name.prefix()); } -NonnullRefPtr Document::create_document_fragment() +JS::NonnullGCPtr Document::create_document_fragment() { - return adopt_ref(*new DocumentFragment(*this)); + return *heap().allocate(realm(), *this); } -NonnullRefPtr Document::create_text_node(String const& data) +JS::NonnullGCPtr Document::create_text_node(String const& data) { - return adopt_ref(*new Text(*this, data)); + return *heap().allocate(realm(), *this, data); } -NonnullRefPtr Document::create_comment(String const& data) +JS::NonnullGCPtr Document::create_comment(String const& data) { - return adopt_ref(*new Comment(*this, data)); + return *heap().allocate(realm(), *this, data); } JS::NonnullGCPtr Document::create_range() @@ -1162,7 +1125,7 @@ JS::NonnullGCPtr Document::create_range() // https://dom.spec.whatwg.org/#dom-document-createevent DOM::ExceptionOr> Document::create_event(String const& interface) { - auto& window_object = preferred_window_object(); + auto& window_object = window(); // NOTE: This is named event here, since we do step 5 and 6 as soon as possible for each case. // 1. Let constructor be null. @@ -1238,33 +1201,36 @@ void Document::set_pending_parsing_blocking_script(Badge Document::take_pending_parsing_blocking_script(Badge) +JS::NonnullGCPtr Document::take_pending_parsing_blocking_script(Badge) { - return m_pending_parsing_blocking_script.release_nonnull(); + VERIFY(m_pending_parsing_blocking_script); + auto script = m_pending_parsing_blocking_script; + m_pending_parsing_blocking_script = nullptr; + return *script; } void Document::add_script_to_execute_when_parsing_has_finished(Badge, HTML::HTMLScriptElement& script) { - m_scripts_to_execute_when_parsing_has_finished.append(script); + m_scripts_to_execute_when_parsing_has_finished.append(JS::make_handle(script)); } -NonnullRefPtrVector Document::take_scripts_to_execute_when_parsing_has_finished(Badge) +Vector> Document::take_scripts_to_execute_when_parsing_has_finished(Badge) { return move(m_scripts_to_execute_when_parsing_has_finished); } void Document::add_script_to_execute_as_soon_as_possible(Badge, HTML::HTMLScriptElement& script) { - m_scripts_to_execute_as_soon_as_possible.append(script); + m_scripts_to_execute_as_soon_as_possible.append(JS::make_handle(script)); } -NonnullRefPtrVector Document::take_scripts_to_execute_as_soon_as_possible(Badge) +Vector> Document::take_scripts_to_execute_as_soon_as_possible(Badge) { return move(m_scripts_to_execute_as_soon_as_possible); } // https://dom.spec.whatwg.org/#dom-document-importnode -ExceptionOr> Document::import_node(NonnullRefPtr node, bool deep) +ExceptionOr> Document::import_node(JS::NonnullGCPtr node, bool deep) { // 1. If node is a document or shadow root, then throw a "NotSupportedError" DOMException. if (is(*node) || is(*node)) @@ -1299,10 +1265,11 @@ void Document::adopt_node(Node& node) // Transfer NodeIterators rooted at `node` from old_document to this document. Vector node_iterators_to_transfer; - for (auto* node_iterator : old_document.m_node_iterators) { - if (node_iterator->root() == &node) + for (auto node_iterator : old_document.m_node_iterators) { + if (node_iterator->root().ptr() == &node) node_iterators_to_transfer.append(*node_iterator); } + for (auto& node_iterator : node_iterators_to_transfer) { old_document.m_node_iterators.remove(&node_iterator); m_node_iterators.set(&node_iterator); @@ -1311,7 +1278,7 @@ void Document::adopt_node(Node& node) } // https://dom.spec.whatwg.org/#dom-document-adoptnode -ExceptionOr> Document::adopt_node_binding(NonnullRefPtr node) +ExceptionOr> Document::adopt_node_binding(JS::NonnullGCPtr node) { if (is(*node)) return DOM::NotSupportedError::create("Cannot adopt a document into a document"); @@ -1350,7 +1317,7 @@ bool Document::is_editable() const void Document::set_focused_element(Element* element) { - if (m_focused_element == element) + if (m_focused_element.ptr() == element) return; if (m_focused_element) { @@ -1371,7 +1338,7 @@ void Document::set_focused_element(Element* element) void Document::set_active_element(Element* element) { - if (m_active_element == element) + if (m_active_element.ptr() == element) return; m_active_element = element; @@ -1410,7 +1377,7 @@ void Document::update_readiness(HTML::DocumentReadyState readiness_value) // FIXME: 3. Otherwise, if readinessValue is "interactive", and document's load timing info's DOM interactive time is 0, then set document's load timing info's DOM interactive time to now. // 3. Fire an event named readystatechange at document. - dispatch_event(*Event::create(preferred_window_object(), HTML::EventNames::readystatechange)); + dispatch_event(*Event::create(window(), HTML::EventNames::readystatechange)); } Page* Document::page() @@ -1451,7 +1418,7 @@ void Document::completely_finish_loading() // Otherwise, if container is non-null, then queue an element task on the DOM manipulation task source given container to fire an event named load at container. else if (container) { container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container, this]() mutable { - container->dispatch_event(*DOM::Event::create(preferred_window_object(), HTML::EventNames::load)); + container->dispatch_event(*DOM::Event::create(window(), HTML::EventNames::load)); }); } } @@ -1531,7 +1498,7 @@ Bindings::LocationObject* Document::location() if (!is_fully_active()) return nullptr; - return window().wrapper()->location_object(); + return window().location_object(); } // https://html.spec.whatwg.org/multipage/interaction.html#dom-document-hidden @@ -1562,14 +1529,14 @@ void Document::run_the_resize_steps() return; m_last_viewport_size = viewport_size; - window().dispatch_event(*DOM::Event::create(preferred_window_object(), UIEvents::EventNames::resize)); + window().dispatch_event(*DOM::Event::create(window(), UIEvents::EventNames::resize)); update_layout(); } -void Document::add_media_query_list(NonnullRefPtr& media_query_list) +void Document::add_media_query_list(JS::NonnullGCPtr media_query_list) { - m_media_query_lists.append(media_query_list); + m_media_query_lists.append(*media_query_list); } // https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes @@ -1590,7 +1557,7 @@ void Document::evaluate_media_queries_and_report_changes() // and its matches attribute initialized to target’s matches state. if (media_query_list_ptr.is_null()) continue; - auto media_query_list = media_query_list_ptr.strong_ref(); + JS::GCPtr media_query_list = media_query_list_ptr.ptr(); bool did_match = media_query_list->matches(); bool now_matches = media_query_list->evaluate(); @@ -1598,7 +1565,7 @@ void Document::evaluate_media_queries_and_report_changes() CSS::MediaQueryListEventInit init; init.media = media_query_list->media(); init.matches = now_matches; - auto event = CSS::MediaQueryListEvent::create(preferred_window_object(), HTML::EventNames::change, init); + auto event = CSS::MediaQueryListEvent::create(window(), HTML::EventNames::change, init); event->set_is_trusted(true); media_query_list->dispatch_event(*event); } @@ -1624,9 +1591,9 @@ void Document::evaluate_media_rules() DOMImplementation* Document::implementation() { - if (!m_implementation.cell()) - m_implementation = JS::make_handle(*DOMImplementation::create(*this)); - return m_implementation.cell(); + if (!m_implementation) + m_implementation = DOMImplementation::create(*this); + return m_implementation; } bool Document::has_focus() const @@ -1821,7 +1788,7 @@ void Document::check_favicon_after_loading_link_resource() for (auto i = favicon_link_elements->length(); i-- > 0;) { auto favicon_element = favicon_link_elements->item(i); - if (favicon_element == m_active_element) + if (favicon_element == m_active_element.ptr()) return; // If the user agent tries to use an icon but that icon is determined, upon closer examination, @@ -1838,14 +1805,19 @@ void Document::check_favicon_after_loading_link_resource() void Document::set_window(Badge, HTML::Window& window) { - m_window = window; + m_window = &window; +} + +CSS::StyleSheetList& Document::style_sheets() +{ + if (!m_style_sheets) + m_style_sheets = CSS::StyleSheetList::create(*this); + return *m_style_sheets; } -Bindings::WindowObject& Document::preferred_window_object() const +CSS::StyleSheetList const& Document::style_sheets() const { - if (m_window && m_window->wrapper()) - return const_cast(*m_window->wrapper()); - return Bindings::main_thread_internal_window_object(); + return const_cast(this)->style_sheets(); } } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index ccd0cd411f12b7783a342a01fb428d16a5d9d31a..d0d90e87e717096f89750f7ea3f6185a52a9972a 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include namespace Web::DOM { @@ -44,25 +44,20 @@ class Document : public ParentNode , public NonElementParentNode , public HTML::GlobalEventHandlers { -public: - using WrapperType = Bindings::DocumentWrapper; + WEB_PLATFORM_OBJECT(Document, ParentNode); +public: enum class Type { XML, HTML }; - static NonnullRefPtr create_and_initialize(Type, String content_type, HTML::NavigationParams); + static JS::NonnullGCPtr create_and_initialize(Type, String content_type, HTML::NavigationParams); - static NonnullRefPtr create(AK::URL const& url = "about:blank"sv); - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&); + static JS::NonnullGCPtr create(HTML::Window&, AK::URL const& url = "about:blank"sv); + static JS::NonnullGCPtr create_with_global_object(HTML::Window&); virtual ~Document() override; - // NOTE: This returns the web-facing window object if there is one, - // otherwise it returns the internal window object. - // FIXME: Remove this when Document is a JS::Object. - Bindings::WindowObject& preferred_window_object() const; - size_t next_layout_node_serial_id(Badge) { return m_next_layout_node_serial_id++; } size_t layout_node_count() const { return m_next_layout_node_serial_id; } @@ -80,7 +75,7 @@ public: AK::URL fallback_base_url() const; AK::URL base_url() const; - RefPtr first_base_element_with_href_in_tree_order() const; + JS::GCPtr first_base_element_with_href_in_tree_order() const; String url_string() const { return m_url.to_string(); } String document_uri() const { return m_url.to_string(); } @@ -96,20 +91,20 @@ public: CSS::StyleComputer& style_computer() { return *m_style_computer; } const CSS::StyleComputer& style_computer() const { return *m_style_computer; } - CSS::StyleSheetList& style_sheets() { return *m_style_sheets; } - const CSS::StyleSheetList& style_sheets() const { return *m_style_sheets; } + CSS::StyleSheetList& style_sheets(); + CSS::StyleSheetList const& style_sheets() const; - CSS::StyleSheetList* style_sheets_for_bindings() { return m_style_sheets.cell(); } + CSS::StyleSheetList* style_sheets_for_bindings() { return &style_sheets(); } virtual FlyString node_name() const override { return "#document"; } void set_hovered_node(Node*); - Node* hovered_node() { return m_hovered_node; } - Node const* hovered_node() const { return m_hovered_node; } + Node* hovered_node() { return m_hovered_node.ptr(); } + Node const* hovered_node() const { return m_hovered_node.ptr(); } void set_inspected_node(Node*); - Node* inspected_node() { return m_inspected_node; } - Node const* inspected_node() const { return m_inspected_node; } + Node* inspected_node() { return m_inspected_node.ptr(); } + Node const* inspected_node() const { return m_inspected_node.ptr(); } Element* document_element(); Element const* document_element() const; @@ -193,30 +188,29 @@ public: void set_source(String const& source) { m_source = source; } HTML::EnvironmentSettingsObject& relevant_settings_object(); - JS::Realm& realm(); JS::Interpreter& interpreter(); JS::Value run_javascript(StringView source, StringView filename = "(unknown)"sv); - ExceptionOr> create_element(String const& tag_name); - ExceptionOr> create_element_ns(String const& namespace_, String const& qualified_name); - NonnullRefPtr create_document_fragment(); - NonnullRefPtr create_text_node(String const& data); - NonnullRefPtr create_comment(String const& data); + ExceptionOr> create_element(String const& tag_name); + ExceptionOr> create_element_ns(String const& namespace_, String const& qualified_name); + JS::NonnullGCPtr create_document_fragment(); + JS::NonnullGCPtr create_text_node(String const& data); + JS::NonnullGCPtr create_comment(String const& data); ExceptionOr> create_event(String const& interface); JS::NonnullGCPtr create_range(); void set_pending_parsing_blocking_script(Badge, HTML::HTMLScriptElement*); - HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; } - NonnullRefPtr take_pending_parsing_blocking_script(Badge); + HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script.ptr(); } + JS::NonnullGCPtr take_pending_parsing_blocking_script(Badge); void add_script_to_execute_when_parsing_has_finished(Badge, HTML::HTMLScriptElement&); - NonnullRefPtrVector take_scripts_to_execute_when_parsing_has_finished(Badge); - NonnullRefPtrVector& scripts_to_execute_when_parsing_has_finished() { return m_scripts_to_execute_when_parsing_has_finished; } + Vector> take_scripts_to_execute_when_parsing_has_finished(Badge); + Vector>& scripts_to_execute_when_parsing_has_finished() { return m_scripts_to_execute_when_parsing_has_finished; } void add_script_to_execute_as_soon_as_possible(Badge, HTML::HTMLScriptElement&); - NonnullRefPtrVector take_scripts_to_execute_as_soon_as_possible(Badge); - NonnullRefPtrVector& scripts_to_execute_as_soon_as_possible() { return m_scripts_to_execute_as_soon_as_possible; } + Vector> take_scripts_to_execute_as_soon_as_possible(Badge); + Vector>& scripts_to_execute_as_soon_as_possible() { return m_scripts_to_execute_as_soon_as_possible; } QuirksMode mode() const { return m_quirks_mode; } bool in_quirks_mode() const { return m_quirks_mode == QuirksMode::Yes; } @@ -228,9 +222,9 @@ public: // https://dom.spec.whatwg.org/#xml-document bool is_xml_document() const { return m_type == Type::XML; } - ExceptionOr> import_node(NonnullRefPtr node, bool deep); + ExceptionOr> import_node(JS::NonnullGCPtr node, bool deep); void adopt_node(Node&); - ExceptionOr> adopt_node_binding(NonnullRefPtr); + ExceptionOr> adopt_node_binding(JS::NonnullGCPtr); DocumentType const* doctype() const; String const& compat_mode() const; @@ -238,39 +232,26 @@ public: void set_editable(bool editable) { m_editable = editable; } virtual bool is_editable() const final; - Element* focused_element() { return m_focused_element; } - Element const* focused_element() const { return m_focused_element; } + Element* focused_element() { return m_focused_element.ptr(); } + Element const* focused_element() const { return m_focused_element.ptr(); } void set_focused_element(Element*); - Element const* active_element() const { return m_active_element; } + Element const* active_element() const { return m_active_element.ptr(); } void set_active_element(Element*); bool created_for_appropriate_template_contents() const { return m_created_for_appropriate_template_contents; } void set_created_for_appropriate_template_contents(bool value) { m_created_for_appropriate_template_contents = value; } - Document* associated_inert_template_document() { return m_associated_inert_template_document; } - Document const* associated_inert_template_document() const { return m_associated_inert_template_document; } - void set_associated_inert_template_document(Document& document) { m_associated_inert_template_document = document; } + Document* associated_inert_template_document() { return m_associated_inert_template_document.ptr(); } + Document const* associated_inert_template_document() const { return m_associated_inert_template_document.ptr(); } + void set_associated_inert_template_document(Document& document) { m_associated_inert_template_document = &document; } String ready_state() const; void update_readiness(HTML::DocumentReadyState); - void ref_from_node(Badge) - { - increment_referencing_node_count(); - } - - void unref_from_node(Badge) - { - decrement_referencing_node_count(); - } - - void removed_last_ref(); - - HTML::Window& window() { return *m_window; } - HTML::Window const& window() const { return *m_window; } + HTML::Window& window() const { return const_cast(*m_window); } void set_window(Badge, HTML::Window&); @@ -280,7 +261,7 @@ public: ExceptionOr open(String const& = "", String const& = ""); ExceptionOr close(); - HTML::Window* default_view() { return m_window; } + HTML::Window* default_view() { return m_window.ptr(); } String const& content_type() const { return m_content_type; } void set_content_type(String const& content_type) { m_content_type = content_type; } @@ -302,8 +283,8 @@ public: DOMImplementation* implementation(); - RefPtr current_script() const { return m_current_script; } - void set_current_script(Badge, RefPtr script) { m_current_script = move(script); } + JS::GCPtr current_script() const { return m_current_script.ptr(); } + void set_current_script(Badge, JS::GCPtr script) { m_current_script = move(script); } u32 ignore_destructive_writes_counter() const { return m_ignore_destructive_writes_counter; } void increment_ignore_destructive_writes_counter() { m_ignore_destructive_writes_counter++; } @@ -335,7 +316,7 @@ public: void run_the_resize_steps(); void evaluate_media_queries_and_report_changes(); - void add_media_query_list(NonnullRefPtr&); + void add_media_query_list(JS::NonnullGCPtr); bool has_focus() const; @@ -359,15 +340,13 @@ public: template void for_each_node_iterator(Callback callback) { - for (auto* node_iterator : m_node_iterators) + for (auto& node_iterator : m_node_iterators) callback(*node_iterator); } bool needs_full_style_update() const { return m_needs_full_style_update; } void set_needs_full_style_update(bool b) { m_needs_full_style_update = b; } - bool in_removed_last_ref() const { return m_in_removed_last_ref; } - bool has_active_favicon() const { return m_active_favicon; } void check_favicon_after_loading_link_resource(); @@ -375,8 +354,11 @@ public: bool is_initial_about_blank() const { return m_is_initial_about_blank; } void set_is_initial_about_blank(bool b) { m_is_initial_about_blank = b; } +protected: + virtual void visit_edges(Cell::Visitor&) override; + private: - explicit Document(const AK::URL&); + Document(HTML::Window&, AK::URL const&); // ^HTML::GlobalEventHandlers virtual EventTarget& global_event_handlers_to_event_target(FlyString const&) final { return *this; } @@ -387,36 +369,17 @@ private: ExceptionOr run_the_document_write_steps(String); - void increment_referencing_node_count() - { - VERIFY(!m_deletion_has_begun); - ++m_referencing_node_count; - } - - void decrement_referencing_node_count() - { - VERIFY(!m_deletion_has_begun); - VERIFY(m_referencing_node_count); - --m_referencing_node_count; - if (!m_referencing_node_count && !ref_count()) { - m_deletion_has_begun = true; - delete this; - } - } - - unsigned m_referencing_node_count { 0 }; - size_t m_next_layout_node_serial_id { 0 }; OwnPtr m_style_computer; - JS::Handle m_style_sheets; - RefPtr m_hovered_node; - RefPtr m_inspected_node; - RefPtr m_active_favicon; + JS::GCPtr m_style_sheets; + JS::GCPtr m_hovered_node; + JS::GCPtr m_inspected_node; + JS::GCPtr m_active_favicon; WeakPtr m_browsing_context; AK::URL m_url; - RefPtr m_window; + JS::GCPtr m_window; RefPtr m_layout_root; @@ -434,9 +397,9 @@ private: OwnPtr m_interpreter; - RefPtr m_pending_parsing_blocking_script; - NonnullRefPtrVector m_scripts_to_execute_when_parsing_has_finished; - NonnullRefPtrVector m_scripts_to_execute_as_soon_as_possible; + JS::GCPtr m_pending_parsing_blocking_script; + Vector> m_scripts_to_execute_when_parsing_has_finished; + Vector> m_scripts_to_execute_as_soon_as_possible; QuirksMode m_quirks_mode { QuirksMode::No }; @@ -445,11 +408,11 @@ private: bool m_editable { false }; - WeakPtr m_focused_element; - WeakPtr m_active_element; + JS::GCPtr m_focused_element; + JS::GCPtr m_active_element; bool m_created_for_appropriate_template_contents { false }; - RefPtr m_associated_inert_template_document; + JS::GCPtr m_associated_inert_template_document; HTML::DocumentReadyState m_readiness { HTML::DocumentReadyState::Loading }; String m_content_type { "application/xml" }; @@ -457,8 +420,8 @@ private: bool m_ready_for_post_load_tasks { false }; - JS::Handle m_implementation; - RefPtr m_current_script; + JS::GCPtr m_implementation; + JS::GCPtr m_current_script; bool m_should_invalidate_styles_on_attribute_changes { true }; @@ -506,3 +469,5 @@ private: }; } + +WRAPPER_HACK(Document, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp b/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp index 67dc77eea2281e7cc53b15d84814805a4f309b01..58ceeb3f3c8d4f30ecaa1af143dc72fd69aa4cbd 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp +++ b/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include @@ -12,12 +13,24 @@ namespace Web::DOM { DocumentFragment::DocumentFragment(Document& document) : ParentNode(document, NodeType::DOCUMENT_FRAGMENT_NODE) { + set_prototype(&window().ensure_web_prototype("DocumentFragment")); +} + +void DocumentFragment::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_host.ptr()); +} + +void DocumentFragment::set_host(Web::DOM::Element* element) +{ + m_host = element; } // https://dom.spec.whatwg.org/#dom-documentfragment-documentfragment -NonnullRefPtr DocumentFragment::create_with_global_object(Bindings::WindowObject& window) +JS::NonnullGCPtr DocumentFragment::create_with_global_object(HTML::Window& window) { - return make_ref_counted(window.impl().associated_document()); + return *window.heap().allocate(window.realm(), window.associated_document()); } } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentFragment.h b/Userland/Libraries/LibWeb/DOM/DocumentFragment.h index 715e9c8bbf1f42323915f67c89780fa1bce7a3ab..496ce67f9af6255af079c94b3b97f46a92bfa9b3 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentFragment.h +++ b/Userland/Libraries/LibWeb/DOM/DocumentFragment.h @@ -16,27 +16,33 @@ namespace Web::DOM { class DocumentFragment : public ParentNode , public NonElementParentNode { -public: - using WrapperType = Bindings::DocumentFragmentWrapper; + WEB_PLATFORM_OBJECT(DocumentFragment, ParentNode); - static NonnullRefPtr create_with_global_object(Bindings::WindowObject& window); +public: + static JS::NonnullGCPtr create_with_global_object(HTML::Window& window); - explicit DocumentFragment(Document& document); virtual ~DocumentFragment() override = default; virtual FlyString node_name() const override { return "#document-fragment"; } - Element* host() { return m_host; } - Element const* host() const { return m_host; } + Element* host() { return m_host.ptr(); } + Element const* host() const { return m_host.ptr(); } - void set_host(Element* host) { m_host = host; } + void set_host(Element*); + +protected: + explicit DocumentFragment(Document& document); + + virtual void visit_edges(Cell::Visitor&) override; private: // https://dom.spec.whatwg.org/#concept-documentfragment-host - WeakPtr m_host; + JS::GCPtr m_host; }; template<> inline bool Node::fast_is() const { return is_document_fragment(); } } + +WRAPPER_HACK(DocumentFragment, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp index 60043ea00c080af1ba4603bfd1528821bfc8156e..44771d859eff7fa72d12be21839f2abbfe0bc79c 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp +++ b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp @@ -10,7 +10,7 @@ namespace Web::DOM { DocumentLoadEventDelayer::DocumentLoadEventDelayer(Document& document) - : m_document(document) + : m_document(JS::make_handle(document)) { m_document->increment_number_of_things_delaying_the_load_event({}); } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h index ac8a17294fd8ffe8664ec3b99eeb1868ebe5124e..72cf923e7bba3ff1eb921fa2ffd47471e09dab1c 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h +++ b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h @@ -7,7 +7,7 @@ #pragma once #include -#include +#include #include namespace Web::DOM { @@ -21,7 +21,7 @@ public: ~DocumentLoadEventDelayer(); private: - NonnullRefPtr m_document; + JS::Handle m_document; }; } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentType.cpp b/Userland/Libraries/LibWeb/DOM/DocumentType.cpp index 1f03de4657a5e390a7731c4413ed65f03149a1ce..e3b34b5fd6ef19e5cbaa001b89299a6d824ceefd 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentType.cpp +++ b/Userland/Libraries/LibWeb/DOM/DocumentType.cpp @@ -1,16 +1,24 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2018-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include namespace Web::DOM { +JS::NonnullGCPtr DocumentType::create(Document& document) +{ + return *document.heap().allocate(document.realm(), document); +} + DocumentType::DocumentType(Document& document) : Node(document, NodeType::DOCUMENT_TYPE_NODE) { + set_prototype(&window().ensure_web_prototype("DocumentType")); } } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentType.h b/Userland/Libraries/LibWeb/DOM/DocumentType.h index 89816ef0eae82f5be8118365a38c0a04fa42394d..f540813aa135d55c9ff90f35afeb40a0702defd1 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentType.h +++ b/Userland/Libraries/LibWeb/DOM/DocumentType.h @@ -15,15 +15,11 @@ namespace Web::DOM { class DocumentType final : public Node , public ChildNode { -public: - using WrapperType = Bindings::DocumentTypeWrapper; + WEB_PLATFORM_OBJECT(DocumentType, Node); - static NonnullRefPtr create(Document& document) - { - return adopt_ref(*new DocumentType(document)); - } +public: + static JS::NonnullGCPtr create(Document&); - explicit DocumentType(Document&); virtual ~DocumentType() override = default; virtual FlyString node_name() const override { return "#doctype"; } @@ -38,6 +34,8 @@ public: void set_system_id(String const& system_id) { m_system_id = system_id; } private: + explicit DocumentType(Document&); + String m_name; String m_public_id; String m_system_id; @@ -47,3 +45,5 @@ template<> inline bool Node::fast_is() const { return is_document_type(); } } + +WRAPPER_HACK(DocumentType, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 89fe06ce282bea399b4f40abbad3d7c426af74ca..665bf4b40e1cce496a0e2f2f5ed01ae16320441f 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -45,13 +46,24 @@ namespace Web::DOM { Element::Element(Document& document, DOM::QualifiedName qualified_name) : ParentNode(document, NodeType::ELEMENT_NODE) , m_qualified_name(move(qualified_name)) - , m_attributes(JS::make_handle(NamedNodeMap::create(*this))) + , m_attributes(NamedNodeMap::create(*this)) { + set_prototype(&document.window().ensure_web_prototype("Element")); + make_html_uppercased_qualified_name(); } Element::~Element() = default; +void Element::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_attributes.ptr()); + visitor.visit(m_inline_style.ptr()); + visitor.visit(m_class_list.ptr()); + visitor.visit(m_shadow_root.ptr()); +} + // https://dom.spec.whatwg.org/#dom-element-getattribute String Element::get_attribute(FlyString const& name) const { @@ -295,7 +307,7 @@ RefPtr Element::create_layout_node_for_display_type(DOM::Document& CSS::CSSStyleDeclaration const* Element::inline_style() const { - return m_inline_style.cell(); + return m_inline_style.ptr(); } void Element::parse_attribute(FlyString const& name, String const& value) @@ -307,13 +319,13 @@ void Element::parse_attribute(FlyString const& name, String const& value) for (auto& new_class : new_classes) { m_classes.unchecked_append(new_class); } - if (m_class_list.cell()) + if (m_class_list) m_class_list->associated_attribute_changed(value); } else if (name == HTML::AttributeNames::style) { // https://drafts.csswg.org/cssom/#ref-for-cssstyledeclaration-updating-flag - if (m_inline_style.cell() && m_inline_style->is_updating()) + if (m_inline_style && m_inline_style->is_updating()) return; - m_inline_style = JS::make_handle(parse_css_style_attribute(CSS::Parser::ParsingContext(document()), value, *this)); + m_inline_style = parse_css_style_attribute(CSS::Parser::ParsingContext(document()), value, *this); set_needs_style_update(true); } } @@ -321,8 +333,8 @@ void Element::parse_attribute(FlyString const& name, String const& value) void Element::did_remove_attribute(FlyString const& name) { if (name == HTML::AttributeNames::style) { - if (m_inline_style.cell()) { - m_inline_style = {}; + if (m_inline_style) { + m_inline_style = nullptr; set_needs_style_update(true); } } @@ -414,9 +426,9 @@ NonnullRefPtr Element::resolved_css_values() DOMTokenList* Element::class_list() { - if (!m_class_list.cell()) - m_class_list = JS::make_handle(DOMTokenList::create(*this, HTML::AttributeNames::class_)); - return m_class_list.cell(); + if (!m_class_list) + m_class_list = DOMTokenList::create(*this, HTML::AttributeNames::class_); + return m_class_list; } // https://dom.spec.whatwg.org/#dom-element-matches @@ -495,7 +507,7 @@ NonnullRefPtr Element::get_elements_by_class_name(FlyString cons }); } -void Element::set_shadow_root(RefPtr shadow_root) +void Element::set_shadow_root(JS::GCPtr shadow_root) { if (m_shadow_root == shadow_root) return; @@ -509,9 +521,9 @@ void Element::set_shadow_root(RefPtr shadow_root) CSS::CSSStyleDeclaration* Element::style_for_bindings() { - if (m_inline_style.is_null()) - m_inline_style = JS::make_handle(CSS::ElementInlineCSSStyleDeclaration::create(*this, {}, {})); - return m_inline_style.cell(); + if (!m_inline_style) + m_inline_style = CSS::ElementInlineCSSStyleDeclaration::create(*this, {}, {}); + return m_inline_style; } // https://dom.spec.whatwg.org/#element-html-uppercased-qualified-name @@ -527,7 +539,7 @@ void Element::make_html_uppercased_qualified_name() // https://html.spec.whatwg.org/multipage/webappapis.html#queue-an-element-task void Element::queue_an_element_task(HTML::Task::Source source, Function steps) { - auto task = HTML::Task::create(source, &document(), [strong_this = NonnullRefPtr(*this), steps = move(steps)] { + auto task = HTML::Task::create(source, &document(), [strong_this = JS::make_handle(*this), steps = move(steps)] { steps(); }); HTML::main_thread_event_loop().task_queue().add(move(task)); diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 7da6d5b849a042fd49439dc5036369265a2af17c..45aa9411e10577134d5e6a5bfd43e7028e08ba03 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -29,10 +29,9 @@ class Element : public ParentNode , public ChildNode , public NonDocumentTypeChildNode { + WEB_PLATFORM_OBJECT(Element, ParentNode); public: - using WrapperType = Bindings::ElementWrapper; - Element(Document&, DOM::QualifiedName); virtual ~Element() override; @@ -59,7 +58,7 @@ public: void remove_attribute(FlyString const& name); DOM::ExceptionOr toggle_attribute(FlyString const& name, Optional force); size_t attribute_list_size() const { return m_attributes->length(); } - NamedNodeMap const* attributes() const { return m_attributes.cell(); } + NamedNodeMap const* attributes() const { return m_attributes.ptr(); } Vector get_attribute_names() const; DOMTokenList* class_list(); @@ -115,9 +114,9 @@ public: NonnullRefPtr get_elements_by_class_name(FlyString const&); - ShadowRoot* shadow_root() { return m_shadow_root; } - ShadowRoot const* shadow_root() const { return m_shadow_root; } - void set_shadow_root(RefPtr); + ShadowRoot* shadow_root() { return m_shadow_root.ptr(); } + ShadowRoot const* shadow_root() const { return m_shadow_root.ptr(); } + void set_shadow_root(JS::GCPtr); void set_custom_properties(HashMap custom_properties) { m_custom_properties = move(custom_properties); } HashMap const& custom_properties() const { return m_custom_properties; } @@ -145,23 +144,24 @@ public: protected: virtual void children_changed() override; + virtual void visit_edges(Cell::Visitor&) override; + private: void make_html_uppercased_qualified_name(); QualifiedName m_qualified_name; String m_html_uppercased_qualified_name; - JS::Handle m_attributes; - JS::Handle m_inline_style; + JS::NonnullGCPtr m_attributes; + JS::GCPtr m_inline_style; + JS::GCPtr m_class_list; + JS::GCPtr m_shadow_root; RefPtr m_computed_css_values; HashMap m_custom_properties; - JS::Handle m_class_list; Vector m_classes; - RefPtr m_shadow_root; - Array, CSS::Selector::PseudoElementCount> m_pseudo_element_nodes; }; @@ -171,3 +171,5 @@ inline bool Node::fast_is() const { return is_element(); } ExceptionOr validate_and_extract(FlyString namespace_, FlyString qualified_name); } + +WRAPPER_HACK(Element, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp index e1d7329db7a66ae259a932a75e5043ae0ba1b298..350ab64d2fac4daec3a523409fb7deb9cbe24688 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2018-2022, Andreas Kling * Copyright (c) 2020, Luke Wilde * * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -93,7 +94,7 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#concept-create-element -NonnullRefPtr create_element(Document& document, FlyString local_name, FlyString namespace_, FlyString prefix) +JS::NonnullGCPtr create_element(Document& document, FlyString local_name, FlyString namespace_, FlyString prefix) { // 1. If prefix was not given, let prefix be null. // NOTE: This is already taken care of by `prefix` having a default value. @@ -113,182 +114,183 @@ NonnullRefPtr create_element(Document& document, FlyString local_name, // then set result’s custom element state to "undefined". // 8. Return result. + auto& realm = document.realm(); auto lowercase_tag_name = local_name.to_lowercase(); auto qualified_name = QualifiedName { local_name, prefix, namespace_ }; if (lowercase_tag_name == HTML::TagNames::a) - return adopt_ref(*new HTML::HTMLAnchorElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::area) - return adopt_ref(*new HTML::HTMLAreaElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::audio) - return adopt_ref(*new HTML::HTMLAudioElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::base) - return adopt_ref(*new HTML::HTMLBaseElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::blink) - return adopt_ref(*new HTML::HTMLBlinkElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::body) - return adopt_ref(*new HTML::HTMLBodyElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::br) - return adopt_ref(*new HTML::HTMLBRElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::button) - return adopt_ref(*new HTML::HTMLButtonElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::canvas) - return adopt_ref(*new HTML::HTMLCanvasElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::data) - return adopt_ref(*new HTML::HTMLDataElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::datalist) - return adopt_ref(*new HTML::HTMLDataListElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::details) - return adopt_ref(*new HTML::HTMLDetailsElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::dialog) - return adopt_ref(*new HTML::HTMLDialogElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::dir) - return adopt_ref(*new HTML::HTMLDirectoryElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::div) - return adopt_ref(*new HTML::HTMLDivElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::dl) - return adopt_ref(*new HTML::HTMLDListElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::embed) - return adopt_ref(*new HTML::HTMLEmbedElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::fieldset) - return adopt_ref(*new HTML::HTMLFieldSetElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::font) - return adopt_ref(*new HTML::HTMLFontElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::form) - return adopt_ref(*new HTML::HTMLFormElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::frame) - return adopt_ref(*new HTML::HTMLFrameElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::frameset) - return adopt_ref(*new HTML::HTMLFrameSetElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::head) - return adopt_ref(*new HTML::HTMLHeadElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.is_one_of(HTML::TagNames::h1, HTML::TagNames::h2, HTML::TagNames::h3, HTML::TagNames::h4, HTML::TagNames::h5, HTML::TagNames::h6)) - return adopt_ref(*new HTML::HTMLHeadingElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::hr) - return adopt_ref(*new HTML::HTMLHRElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::html) - return adopt_ref(*new HTML::HTMLHtmlElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::iframe) - return adopt_ref(*new HTML::HTMLIFrameElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::img) - return adopt_ref(*new HTML::HTMLImageElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::input) - return adopt_ref(*new HTML::HTMLInputElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::label) - return adopt_ref(*new HTML::HTMLLabelElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::legend) - return adopt_ref(*new HTML::HTMLLegendElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::li) - return adopt_ref(*new HTML::HTMLLIElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::link) - return adopt_ref(*new HTML::HTMLLinkElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::map) - return adopt_ref(*new HTML::HTMLMapElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::marquee) - return adopt_ref(*new HTML::HTMLMarqueeElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::menu) - return adopt_ref(*new HTML::HTMLMenuElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::meta) - return adopt_ref(*new HTML::HTMLMetaElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::meter) - return adopt_ref(*new HTML::HTMLMeterElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.is_one_of(HTML::TagNames::ins, HTML::TagNames::del)) - return adopt_ref(*new HTML::HTMLModElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::object) - return adopt_ref(*new HTML::HTMLObjectElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::ol) - return adopt_ref(*new HTML::HTMLOListElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::optgroup) - return adopt_ref(*new HTML::HTMLOptGroupElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::option) - return adopt_ref(*new HTML::HTMLOptionElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::output) - return adopt_ref(*new HTML::HTMLOutputElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::p) - return adopt_ref(*new HTML::HTMLParagraphElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::param) - return adopt_ref(*new HTML::HTMLParamElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::picture) - return adopt_ref(*new HTML::HTMLPictureElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); // NOTE: The obsolete elements "listing" and "xmp" are explicitly mapped to HTMLPreElement in the specification. if (lowercase_tag_name.is_one_of(HTML::TagNames::pre, HTML::TagNames::listing, HTML::TagNames::xmp)) - return adopt_ref(*new HTML::HTMLPreElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::progress) - return adopt_ref(*new HTML::HTMLProgressElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.is_one_of(HTML::TagNames::blockquote, HTML::TagNames::q)) - return adopt_ref(*new HTML::HTMLQuoteElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::script) - return adopt_ref(*new HTML::HTMLScriptElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::select) - return adopt_ref(*new HTML::HTMLSelectElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::slot) - return adopt_ref(*new HTML::HTMLSlotElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::source) - return adopt_ref(*new HTML::HTMLSourceElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::span) - return adopt_ref(*new HTML::HTMLSpanElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::style) - return adopt_ref(*new HTML::HTMLStyleElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::caption) - return adopt_ref(*new HTML::HTMLTableCaptionElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.is_one_of(Web::HTML::TagNames::td, Web::HTML::TagNames::th)) - return adopt_ref(*new HTML::HTMLTableCellElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.is_one_of(HTML::TagNames::colgroup, HTML::TagNames::col)) - return adopt_ref(*new HTML::HTMLTableColElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::table) - return adopt_ref(*new HTML::HTMLTableElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::tr) - return adopt_ref(*new HTML::HTMLTableRowElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.is_one_of(HTML::TagNames::tbody, HTML::TagNames::thead, HTML::TagNames::tfoot)) - return adopt_ref(*new HTML::HTMLTableSectionElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::template_) - return adopt_ref(*new HTML::HTMLTemplateElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::textarea) - return adopt_ref(*new HTML::HTMLTextAreaElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::time) - return adopt_ref(*new HTML::HTMLTimeElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::title) - return adopt_ref(*new HTML::HTMLTitleElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::track) - return adopt_ref(*new HTML::HTMLTrackElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::ul) - return adopt_ref(*new HTML::HTMLUListElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == HTML::TagNames::video) - return adopt_ref(*new HTML::HTMLVideoElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.is_one_of( HTML::TagNames::article, HTML::TagNames::section, HTML::TagNames::nav, HTML::TagNames::aside, HTML::TagNames::hgroup, HTML::TagNames::header, HTML::TagNames::footer, HTML::TagNames::address, HTML::TagNames::dt, HTML::TagNames::dd, HTML::TagNames::figure, HTML::TagNames::figcaption, HTML::TagNames::main, HTML::TagNames::em, HTML::TagNames::strong, HTML::TagNames::small, HTML::TagNames::s, HTML::TagNames::cite, HTML::TagNames::dfn, HTML::TagNames::abbr, HTML::TagNames::ruby, HTML::TagNames::rt, HTML::TagNames::rp, HTML::TagNames::code, HTML::TagNames::var, HTML::TagNames::samp, HTML::TagNames::kbd, HTML::TagNames::sub, HTML::TagNames::sup, HTML::TagNames::i, HTML::TagNames::b, HTML::TagNames::u, HTML::TagNames::mark, HTML::TagNames::bdi, HTML::TagNames::bdo, HTML::TagNames::wbr, HTML::TagNames::summary, HTML::TagNames::noscript, // Obsolete HTML::TagNames::acronym, HTML::TagNames::basefont, HTML::TagNames::big, HTML::TagNames::center, HTML::TagNames::nobr, HTML::TagNames::noembed, HTML::TagNames::noframes, HTML::TagNames::plaintext, HTML::TagNames::rb, HTML::TagNames::rtc, HTML::TagNames::strike, HTML::TagNames::tt)) - return adopt_ref(*new HTML::HTMLElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::svg) - return adopt_ref(*new SVG::SVGSVGElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); // FIXME: Support SVG's mixedCase tag names properly. if (lowercase_tag_name.equals_ignoring_case(SVG::TagNames::clipPath)) - return adopt_ref(*new SVG::SVGClipPathElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::circle) - return adopt_ref(*new SVG::SVGCircleElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name.equals_ignoring_case(SVG::TagNames::defs)) - return adopt_ref(*new SVG::SVGDefsElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::ellipse) - return adopt_ref(*new SVG::SVGEllipseElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::line) - return adopt_ref(*new SVG::SVGLineElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::path) - return adopt_ref(*new SVG::SVGPathElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::polygon) - return adopt_ref(*new SVG::SVGPolygonElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::polyline) - return adopt_ref(*new SVG::SVGPolylineElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::rect) - return adopt_ref(*new SVG::SVGRectElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::g) - return adopt_ref(*new SVG::SVGGElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); if (lowercase_tag_name == SVG::TagNames::text) - return adopt_ref(*new SVG::SVGTextContentElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); // FIXME: If name is a valid custom element name, then return HTMLElement. - return adopt_ref(*new HTML::HTMLUnknownElement(document, move(qualified_name))); + return *realm.heap().allocate(realm, document, move(qualified_name)); } } diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.h b/Userland/Libraries/LibWeb/DOM/ElementFactory.h index 879b1e004b46586120be25f8f6d9f51a2a82a366..3c9ac81cbb149306dd616dfe3c7815f86d3665ff 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.h +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.h @@ -10,6 +10,6 @@ namespace Web::DOM { -NonnullRefPtr create_element(Document&, FlyString local_name, FlyString namespace_, FlyString prefix = {}); +JS::NonnullGCPtr create_element(Document&, FlyString local_name, FlyString namespace_, FlyString prefix = {}); } diff --git a/Userland/Libraries/LibWeb/DOM/Event.cpp b/Userland/Libraries/LibWeb/DOM/Event.cpp index 5ccba65e31daa6e01f14b803e89cee0bde2c4579..024fa0104f69230f96146b9e8b569600eeff800c 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.cpp +++ b/Userland/Libraries/LibWeb/DOM/Event.cpp @@ -8,31 +8,31 @@ #include #include -#include #include #include #include +#include namespace Web::DOM { -JS::NonnullGCPtr Event::create(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init) +JS::NonnullGCPtr Event::create(HTML::Window& window_object, FlyString const& event_name, EventInit const& event_init) { return *window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); } -JS::NonnullGCPtr Event::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init) +JS::NonnullGCPtr Event::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, EventInit const& event_init) { return create(window_object, event_name, event_init); } -Event::Event(Bindings::WindowObject& window_object, FlyString const& type) +Event::Event(HTML::Window& window_object, FlyString const& type) : PlatformObject(window_object.ensure_web_prototype("Event")) , m_type(type) , m_initialized(true) { } -Event::Event(Bindings::WindowObject& window_object, FlyString const& type, EventInit const& event_init) +Event::Event(HTML::Window& window_object, FlyString const& type, EventInit const& event_init) : PlatformObject(window_object.ensure_web_prototype("Event")) , m_type(type) , m_bubbles(event_init.bubbles) @@ -43,7 +43,7 @@ Event::Event(Bindings::WindowObject& window_object, FlyString const& type, Event } // https://dom.spec.whatwg.org/#concept-event-path-append -void Event::append_to_path(EventTarget& invocation_target, RefPtr shadow_adjusted_target, RefPtr related_target, TouchTargetList& touch_targets, bool slot_in_closed_tree) +void Event::append_to_path(EventTarget& invocation_target, JS::GCPtr shadow_adjusted_target, JS::GCPtr related_target, TouchTargetList& touch_targets, bool slot_in_closed_tree) { // 1. Let invocationTargetInShadowTree be false. bool invocation_target_in_shadow_tree = false; @@ -120,10 +120,10 @@ double Event::time_stamp() const } // https://dom.spec.whatwg.org/#dom-event-composedpath -NonnullRefPtrVector Event::composed_path() const +Vector> Event::composed_path() const { // 1. Let composedPath be an empty list. - NonnullRefPtrVector composed_path; + Vector> composed_path; // 2. Let path be this’s path. (NOTE: Not necessary) @@ -136,7 +136,7 @@ NonnullRefPtrVector Event::composed_path() const // 5. Append currentTarget to composedPath. // NOTE: If path is not empty, then the event is being dispatched and will have a currentTarget. VERIFY(m_current_target); - composed_path.append(*m_current_target); + composed_path.append(const_cast(m_current_target.ptr())); // 6. Let currentTargetIndex be 0. size_t current_target_index = 0; @@ -182,7 +182,7 @@ NonnullRefPtrVector Event::composed_path() const // 2. If currentHiddenLevel is less than or equal to maxHiddenLevel, then prepend path[index]'s invocation target to composedPath. if (current_hidden_level <= max_hidden_level) { VERIFY(path_entry.invocation_target); - composed_path.prepend(*path_entry.invocation_target); + composed_path.prepend(const_cast(path_entry.invocation_target.ptr())); } // 3. If path[index]'s slot-in-closed-tree is true, then: @@ -214,7 +214,7 @@ NonnullRefPtrVector Event::composed_path() const // 2. If currentHiddenLevel is less than or equal to maxHiddenLevel, then append path[index]'s invocation target to composedPath. if (current_hidden_level <= max_hidden_level) { VERIFY(path_entry.invocation_target); - composed_path.append(*path_entry.invocation_target); + composed_path.append(const_cast(path_entry.invocation_target.ptr())); } // 3. If path[index]'s root-of-closed-tree is true, then: diff --git a/Userland/Libraries/LibWeb/DOM/Event.h b/Userland/Libraries/LibWeb/DOM/Event.h index 51e8533025c795ad672328922ecc7f24a5ba4de5..d4cb3edd3485765f56e72c391e963fefefd42ebc 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.h +++ b/Userland/Libraries/LibWeb/DOM/Event.h @@ -8,8 +8,8 @@ #include #include -#include #include +#include namespace Web::DOM { @@ -20,7 +20,7 @@ struct EventInit { }; class Event : public Bindings::PlatformObject { - JS_OBJECT(Event, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(Event, Bindings::PlatformObject); public: enum Phase : u16 { @@ -30,13 +30,14 @@ public: BubblingPhase = 3, }; - using TouchTargetList = Vector>; + // FIXME: These need explicit marking somehow. + using TouchTargetList = Vector>; struct PathEntry { - RefPtr invocation_target; + JS::GCPtr invocation_target; bool invocation_target_in_shadow_tree { false }; - RefPtr shadow_adjusted_target; - RefPtr related_target; + JS::GCPtr shadow_adjusted_target; + JS::GCPtr related_target; TouchTargetList touch_target_list; bool root_of_closed_tree { false }; bool slot_in_closed_tree { false }; @@ -45,28 +46,26 @@ public: using Path = Vector; - static JS::NonnullGCPtr create(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init = {}); - static JS::NonnullGCPtr create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init); + static JS::NonnullGCPtr create(HTML::Window&, FlyString const& event_name, EventInit const& event_init = {}); + static JS::NonnullGCPtr create_with_global_object(HTML::Window&, FlyString const& event_name, EventInit const& event_init); - Event(Bindings::WindowObject&, FlyString const& type); - Event(Bindings::WindowObject&, FlyString const& type, EventInit const& event_init); + Event(HTML::Window&, FlyString const& type); + Event(HTML::Window&, FlyString const& type, EventInit const& event_init); virtual ~Event() = default; - Event& impl() { return *this; } - double time_stamp() const; FlyString const& type() const { return m_type; } void set_type(StringView type) { m_type = type; } - RefPtr target() const { return m_target; } + JS::GCPtr target() const { return m_target; } void set_target(EventTarget* target) { m_target = target; } // NOTE: This is intended for the JS bindings. - RefPtr src_element() const { return target(); } + JS::GCPtr src_element() const { return target(); } - RefPtr related_target() const { return m_related_target; } + JS::GCPtr related_target() const { return m_related_target; } void set_related_target(EventTarget* related_target) { m_related_target = related_target; } bool should_stop_propagation() const { return m_stop_propagation; } @@ -96,7 +95,7 @@ public: u16 event_phase() const { return m_phase; } void set_phase(Phase phase) { m_phase = phase; } - RefPtr current_target() const { return m_current_target; } + JS::GCPtr current_target() const { return m_current_target; } void set_current_target(EventTarget* current_target) { m_current_target = current_target; } bool return_value() const { return !m_cancelled; } @@ -106,7 +105,7 @@ public: set_cancelled_flag(); } - void append_to_path(EventTarget&, RefPtr, RefPtr, TouchTargetList&, bool); + void append_to_path(EventTarget&, JS::GCPtr, JS::GCPtr, TouchTargetList&, bool); Path& path() { return m_path; } Path const& path() const { return m_path; } void clear_path() { m_path.clear(); } @@ -143,16 +142,16 @@ public: void set_time_stamp(double time_stamp) { m_time_stamp = time_stamp; } - NonnullRefPtrVector composed_path() const; + Vector> composed_path() const; protected: void initialize_event(String const&, bool, bool); private: FlyString m_type; - RefPtr m_target; - RefPtr m_related_target; - RefPtr m_current_target; + JS::GCPtr m_target; + JS::GCPtr m_related_target; + JS::GCPtr m_current_target; Phase m_phase { None }; @@ -179,7 +178,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::DOM::Event& object) { return &object; } -using EventWrapper = Web::DOM::Event; -} +WRAPPER_HACK(Event, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp index 5112681d9283f17e92ad33da8eaefc2f4a1b3e65..19a9bb9da37145a4b1243cfebab94283f21073d3 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp @@ -8,10 +8,7 @@ #include #include #include -#include -#include #include -#include #include #include #include @@ -93,8 +90,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector(global)) { - auto& bindings_window_global = verify_cast(global); + if (is(global)) { + auto& bindings_window_global = verify_cast(global); auto& window_impl = bindings_window_global.impl(); // 1. Set currentEvent to global’s current event. @@ -111,8 +108,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector(global)) { - auto& bindings_window_global = verify_cast(global); + if (is(global)) { + auto& bindings_window_global = verify_cast(global); auto& window_impl = bindings_window_global.impl(); window_impl.set_current_event(current_event); } @@ -146,17 +143,17 @@ bool EventDispatcher::inner_invoke(Event& event, Vector target, Event& event, bool legacy_target_override) +bool EventDispatcher::dispatch(JS::NonnullGCPtr target, Event& event, bool legacy_target_override) { // 1. Set event’s dispatch flag. event.set_dispatched(true); // 2. Let targetOverride be target, if legacy target override flag is not given, and target’s associated Document otherwise. [HTML] // NOTE: legacy target override flag is only used by HTML and only when target is a Window object. - RefPtr target_override; + JS::GCPtr target_override; if (!legacy_target_override) { target_override = target; } else { - target_override = verify_cast(*target).associated_document(); + target_override = &verify_cast(*target).associated_document(); } // 3. Let activationTarget be null. - RefPtr activation_target; + JS::GCPtr activation_target; // 4. Let relatedTarget be the result of retargeting event’s relatedTarget against target. - RefPtr related_target = retarget(event.related_target(), target); + JS::GCPtr related_target = retarget(event.related_target(), target); bool clear_targets = false; // 5. If target is not relatedTarget or target is event’s relatedTarget, then: @@ -285,12 +282,12 @@ bool EventDispatcher::dispatch(NonnullRefPtr target, Event& event, } // 7. Otherwise, if parent is relatedTarget, then set parent to null. - else if (related_target == parent) { + else if (related_target.ptr() == parent) { parent = nullptr; } // 8. Otherwise, set target to parent and then: else { - target = *parent; + target = parent; // 1. If isActivationEvent is true, activationTarget is null, and target has activation behavior, then set activationTarget to target. if (is_activation_event && !activation_target && target->activation_behavior) @@ -311,7 +308,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr target, Event& event, // 10. Let clearTargetsStruct be the last struct in event’s path whose shadow-adjusted target is non-null. auto clear_targets_struct = event.path().last_matching([](auto& entry) { - return !entry.shadow_adjusted_target.is_null(); + return entry.shadow_adjusted_target; }); VERIFY(clear_targets_struct.has_value()); diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.h b/Userland/Libraries/LibWeb/DOM/EventDispatcher.h index 09431927870f11e8c9b6a0f8b0b83124200c627c..26db70fa00c0339f911b7f1cd380fd04f951ad5b 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.h +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.h @@ -14,7 +14,7 @@ namespace Web::DOM { class EventDispatcher { public: - static bool dispatch(NonnullRefPtr, Event&, bool legacy_target_override = false); + static bool dispatch(JS::NonnullGCPtr, Event&, bool legacy_target_override = false); private: static void invoke(Event::PathEntry&, Event&, Event::Phase); diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp index c20e87f79fb07b332fc7cd9f7d28349cc46398a1..58eb036cce7b4d6867e9d65944380790ff390f78 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp @@ -13,8 +13,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -36,9 +35,32 @@ namespace Web::DOM { -EventTarget::EventTarget() = default; +EventTarget::EventTarget(JS::Realm& realm) + : PlatformObject(realm) +{ +} + EventTarget::~EventTarget() = default; +void EventTarget::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + + for (auto& event_listener : m_event_listener_list) + visitor.visit(event_listener.ptr()); + + for (auto& it : m_event_handler_map) + visitor.visit(it.value.ptr()); +} + +Vector> EventTarget::event_listener_list() +{ + Vector> list; + for (auto& listener : m_event_listener_list) + list.append(*listener); + return list; +} + // https://dom.spec.whatwg.org/#concept-flatten-options static bool flatten_event_listener_options(Variant const& options) { @@ -64,7 +86,7 @@ struct FlattenedAddEventListenerOptions { bool capture { false }; bool passive { false }; bool once { false }; - RefPtr signal; + JS::GCPtr signal; }; // https://dom.spec.whatwg.org/#event-flatten-more @@ -78,7 +100,7 @@ static FlattenedAddEventListenerOptions flatten_add_event_listener_options(Varia bool passive = false; // 3. Let signal be null. - RefPtr signal; + JS::GCPtr signal; // 4. If options is a dictionary, then: if (options.has()) { @@ -90,11 +112,11 @@ static FlattenedAddEventListenerOptions flatten_add_event_listener_options(Varia // 2. If options["signal"] exists, then set signal to options["signal"]. if (add_event_listener_options.signal.has_value()) - signal = add_event_listener_options.signal.value(); + signal = add_event_listener_options.signal.value().ptr(); } // 5. Return capture, passive, once, and signal. - return FlattenedAddEventListenerOptions { .capture = capture, .passive = passive, .once = once, .signal = signal }; + return FlattenedAddEventListenerOptions { .capture = capture, .passive = passive, .once = once, .signal = signal.ptr() }; } // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener @@ -145,11 +167,11 @@ void EventTarget::add_an_event_listener(DOMEventListener& listener) && entry->capture == listener.capture; }); if (it == m_event_listener_list.end()) - m_event_listener_list.append(JS::make_handle(listener)); + m_event_listener_list.append(listener); // 5. If listener’s signal is not null, then add the following abort steps to it: if (listener.signal) { - listener.signal->add_abort_algorithm([strong_event_target = NonnullRefPtr(*this), listener = JS::make_handle(&listener)]() mutable { + listener.signal->add_abort_algorithm([strong_event_target = JS::make_handle(*this), listener = JS::make_handle(&listener)]() mutable { // 1. Remove an event listener with eventTarget and listener. strong_event_target->remove_an_event_listener(*listener); }); @@ -193,12 +215,12 @@ void EventTarget::remove_an_event_listener(DOMEventListener& listener) // 2. Set listener’s removed to true and remove listener from eventTarget’s event listener list. listener.removed = true; - m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.cell() == &listener; }); + m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.ptr() == &listener; }); } void EventTarget::remove_from_event_listener_list(DOMEventListener& listener) { - m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.cell() == &listener; }); + m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.ptr() == &listener; }); } // https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent @@ -313,17 +335,17 @@ Bindings::CallbackType* EventTarget::get_current_value_of_event_handler(FlyStrin if (event_handler->value.has()) { // 1. If eventTarget is an element, then let element be eventTarget, and document be element's node document. // Otherwise, eventTarget is a Window object, let element be null, and document be eventTarget's associated Document. - RefPtr element; - RefPtr document; + JS::GCPtr element; + JS::GCPtr document; if (is(this)) { auto* element_event_target = verify_cast(this); element = element_event_target; - document = element_event_target->document(); + document = &element_event_target->document(); } else { VERIFY(is(this)); auto* window_event_target = verify_cast(this); - document = window_event_target->associated_document(); + document = &window_event_target->associated_document(); } VERIFY(document); @@ -338,7 +360,7 @@ Bindings::CallbackType* EventTarget::get_current_value_of_event_handler(FlyStrin // FIXME: 4. Let location be the location where the script body originated, as given by eventHandler's value. // 5. If element is not null and element has a form owner, let form owner be that form owner. Otherwise, let form owner be null. - RefPtr form_owner; + JS::GCPtr form_owner; if (is(element.ptr())) { auto* form_associated_element = dynamic_cast(element.ptr()); VERIFY(form_associated_element); @@ -491,7 +513,7 @@ void EventTarget::set_event_handler_attribute(FlyString const& name, Bindings::C // unique call to activate_event_handler. event_target->activate_event_handler(name, *new_event_handler); - handler_map.set(name, JS::make_handle(new_event_handler)); + handler_map.set(name, new_event_handler); return; } @@ -515,21 +537,7 @@ void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandl if (event_handler.listener) return; - JS::Realm* realm = nullptr; - // See step 3.1. in get_current_value_of_event_handler(), which explains these assumptions. - if (event_handler.value.has()) { - realm = &event_handler.value.get()->callback_context.realm(); - } else if (is(this)) { - realm = &verify_cast(*this).document().realm(); - } else { - auto& window = verify_cast(*this); - // If an element attribute is set on a element before any script is run, Window::wrapper() will be null. - // Force creation of the global object via the Document::interpreter() lazy initialization mechanism. - if (window.wrapper() == nullptr) - window.associated_document().interpreter(); - realm = &window.wrapper()->shape().realm(); - } - VERIFY(realm); + JS::Realm& realm = shape().realm(); // 4. Let callback be the result of creating a Web IDL EventListener instance representing a reference to a function of one argument that executes the steps of the event handler processing algorithm, given eventTarget, name, and its argument. // The EventListener's callback context can be arbitrary; it does not impact the steps of the event handler processing algorithm. [DOM] @@ -540,28 +548,28 @@ void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandl // location.reload(); // The body element is no longer in the DOM and there is no variable holding onto it. However, the onunload handler is still called, meaning the callback keeps the body element alive. auto callback_function = JS::NativeFunction::create( - *realm, [event_target = NonnullRefPtr(*this), name](JS::VM& vm) mutable -> JS::ThrowCompletionOr { + realm, [event_target = JS::make_handle(*this), name](JS::VM& vm) mutable -> JS::ThrowCompletionOr { // The event dispatcher should only call this with one argument. VERIFY(vm.argument_count() == 1); - // The argument must be an object and it must be an EventWrapper. + // The argument must be an object and it must be an Event. auto event_wrapper_argument = vm.argument(0); VERIFY(event_wrapper_argument.is_object()); - auto& event_wrapper = verify_cast(event_wrapper_argument.as_object()); + auto& event_wrapper = verify_cast(event_wrapper_argument.as_object()); auto& event = event_wrapper.impl(); TRY(event_target->process_event_handler_for_event(name, event)); return JS::js_undefined(); }, - 0, "", realm); + 0, "", &realm); // NOTE: As per the spec, the callback context is arbitrary. - auto* callback = realm->heap().allocate_without_realm(*callback_function, verify_cast(*realm->host_defined())); + auto* callback = realm.heap().allocate_without_realm(*callback_function, verify_cast(*realm.host_defined())); // 5. Let listener be a new event listener whose type is the event handler event type corresponding to eventHandler and callback is callback. - auto* listener = realm->heap().allocate_without_realm(); + auto* listener = realm.heap().allocate_without_realm(); listener->type = name; - listener->callback = IDLEventListener::create(*realm, *callback).ptr(); + listener->callback = IDLEventListener::create(realm, *callback).ptr(); // 6. Add an event listener with eventTarget and listener. add_an_event_listener(*listener); @@ -723,7 +731,7 @@ void EventTarget::element_event_handler_attribute_changed(FlyString const& local // 6. Activate an event handler given eventTarget and name. event_target->activate_event_handler(local_name, *new_event_handler); - handler_map.set(local_name, JS::make_handle(new_event_handler)); + handler_map.set(local_name, new_event_handler); return; } diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.h b/Userland/Libraries/LibWeb/DOM/EventTarget.h index 9d94fb91290274e82f4352c8ded2d16e49b8d0d0..cbd785643e522dc5eb99e624677bb150142a33ff 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -17,16 +18,12 @@ namespace Web::DOM { -class EventTarget { - AK_MAKE_NONCOPYABLE(EventTarget); - AK_MAKE_NONMOVABLE(EventTarget); +class EventTarget : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(EventTarget, Bindings::PlatformObject); public: virtual ~EventTarget(); - void ref() { ref_event_target(); } - void unref() { unref_event_target(); } - virtual bool is_focusable() const { return false; } void add_event_listener(FlyString const& type, IDLEventListener* callback, Variant const& options); @@ -39,16 +36,13 @@ public: virtual bool dispatch_event(Event&); ExceptionOr dispatch_event_binding(Event&); - virtual JS::Object* create_wrapper(JS::Realm&) = 0; - virtual EventTarget* get_parent(Event const&) { return nullptr; } void add_an_event_listener(DOMEventListener&); void remove_an_event_listener(DOMEventListener&); void remove_from_event_listener_list(DOMEventListener&); - auto& event_listener_list() { return m_event_listener_list; } - auto const& event_listener_list() const { return m_event_listener_list; } + Vector> event_listener_list(); Function activation_behavior; @@ -61,19 +55,18 @@ public: void set_event_handler_attribute(FlyString const& name, Bindings::CallbackType*); protected: - EventTarget(); - - virtual void ref_event_target() = 0; - virtual void unref_event_target() = 0; + explicit EventTarget(JS::Realm&); void element_event_handler_attribute_changed(FlyString const& local_name, String const& value); + virtual void visit_edges(Cell::Visitor&) override; + private: - Vector> m_event_listener_list; + Vector> m_event_listener_list; // https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-map // Spec Note: The order of the entries of event handler map could be arbitrary. It is not observable through any algorithms that operate on the map. - HashMap> m_event_handler_map; + HashMap> m_event_handler_map; Bindings::CallbackType* get_current_value_of_event_handler(FlyString const& name); void activate_event_handler(FlyString const& name, HTML::EventHandler& event_handler); @@ -84,3 +77,5 @@ private: bool is_window_reflecting_body_element_event_handler(FlyString const& name); } + +WRAPPER_HACK(EventTarget, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp b/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp index c4f4bb7c63b7ebdc86b43a7b0f609c024f4525ed..9f95e3009446a90a7c8126378be4ff04433c11a3 100644 --- a/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp +++ b/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp @@ -13,19 +13,19 @@ namespace Web::DOM { HTMLCollection::HTMLCollection(ParentNode& root, Function filter) - : m_root(root) + : m_root(JS::make_handle(root)) , m_filter(move(filter)) { } HTMLCollection::~HTMLCollection() = default; -Vector> HTMLCollection::collect_matching_elements() const +JS::MarkedVector HTMLCollection::collect_matching_elements() const { - Vector> elements; + JS::MarkedVector elements(m_root->heap()); m_root->for_each_in_inclusive_subtree_of_type([&](auto& element) { if (m_filter(element)) - elements.append(element); + elements.append(const_cast(&element)); return IterationDecision::Continue; }); return elements; diff --git a/Userland/Libraries/LibWeb/DOM/HTMLCollection.h b/Userland/Libraries/LibWeb/DOM/HTMLCollection.h index ea1ceaa883e400b3fad6d0c6e529b9cc78276aec..eae346bf0701e7e9193f3de8f725caa508c26544 100644 --- a/Userland/Libraries/LibWeb/DOM/HTMLCollection.h +++ b/Userland/Libraries/LibWeb/DOM/HTMLCollection.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,7 @@ public: Element* item(size_t index) const; Element* named_item(FlyString const& name) const; - Vector> collect_matching_elements() const; + JS::MarkedVector collect_matching_elements() const; Vector supported_property_names() const; bool is_supported_property_index(u32) const; @@ -53,10 +54,10 @@ public: protected: HTMLCollection(ParentNode& root, Function filter); - NonnullRefPtr root() { return m_root; } + JS::NonnullGCPtr root() { return *m_root; } private: - NonnullRefPtr m_root; + JS::Handle m_root; Function m_filter; }; diff --git a/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp b/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp index 5c4c75f582b0633789331f13f458c68b029b4265..6fd55576e4692ec00a131df1a7b1d94ea1ed71a9 100644 --- a/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp +++ b/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include +#include namespace Web::DOM { diff --git a/Userland/Libraries/LibWeb/DOM/IDLEventListener.h b/Userland/Libraries/LibWeb/DOM/IDLEventListener.h index f372353462674f6d77a4e80cf704e0bf9bb9883d..451ed6098010037b8211fe6178e4d5eeaa40b87a 100644 --- a/Userland/Libraries/LibWeb/DOM/IDLEventListener.h +++ b/Userland/Libraries/LibWeb/DOM/IDLEventListener.h @@ -22,15 +22,13 @@ struct EventListenerOptions { struct AddEventListenerOptions : public EventListenerOptions { bool passive { false }; bool once { false }; - Optional> signal; + Optional> signal; }; class IDLEventListener final : public JS::Object { JS_OBJECT(IDLEventListener, JS::Object); public: - IDLEventListener& impl() { return *this; } - static JS::NonnullGCPtr create(JS::Realm&, JS::NonnullGCPtr); IDLEventListener(JS::Realm&, JS::NonnullGCPtr); diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp index 544f3bc244b5d010d2c2b29be28b41c56a7afe7f..5f191460941089da0589e284d73c0f709a970223 100644 --- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp +++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp @@ -10,17 +10,17 @@ namespace Web::DOM { LiveNodeList::LiveNodeList(Node& root, Function filter) - : m_root(root) + : m_root(JS::make_handle(root)) , m_filter(move(filter)) { } -NonnullRefPtrVector LiveNodeList::collection() const +JS::MarkedVector LiveNodeList::collection() const { - NonnullRefPtrVector nodes; + JS::MarkedVector nodes(m_root->heap()); m_root->for_each_in_inclusive_subtree([&](auto& node) { if (m_filter(node)) - nodes.append(node); + nodes.append(const_cast(&node)); return IterationDecision::Continue; }); @@ -40,7 +40,7 @@ Node const* LiveNodeList::item(u32 index) const auto nodes = collection(); if (index >= nodes.size()) return nullptr; - return &nodes[index]; + return nodes[index]; } // https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-indices diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h index 1fe1c70a31eaf9c2fdf281d1b1975189600ad2ac..4c35b9e2b02ad841ee51e3193690919a18f758a8 100644 --- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h +++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h @@ -29,9 +29,9 @@ public: private: LiveNodeList(Node& root, Function filter); - NonnullRefPtrVector collection() const; + JS::MarkedVector collection() const; - NonnullRefPtr m_root; + JS::Handle m_root; Function m_filter; }; diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp index e600ac58d9dd5f7ce647b5d8550e9ed33e1f1029..7a7e9e8114ba909c7ad5ad4b21e703e3defd7097 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp +++ b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp @@ -5,14 +5,14 @@ */ #include -#include #include #include +#include namespace Web::DOM { // https://dom.spec.whatwg.org/#dom-mutationobserver-mutationobserver -MutationObserver::MutationObserver(Bindings::WindowObject& window_object, JS::Handle callback) +MutationObserver::MutationObserver(HTML::Window& window_object, JS::Handle callback) : m_callback(move(callback)) { // 1. Set this’s callback to callback. @@ -83,7 +83,7 @@ ExceptionOr MutationObserver::observe(Node& target, MutationObserverInit o target.add_registered_observer(new_registered_observer); // 2. Append target to this’s node list. - m_node_list.append(target.make_weak_ptr()); + m_node_list.append(target.make_weak_ptr()); } return {}; diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.h b/Userland/Libraries/LibWeb/DOM/MutationObserver.h index 961220fda67bc55630f9223ea1f3d56cdaa36e1d..b222d9eaa413d6d909d630bb4e12982404af36fb 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationObserver.h +++ b/Userland/Libraries/LibWeb/DOM/MutationObserver.h @@ -34,7 +34,7 @@ class MutationObserver final public: using WrapperType = Bindings::MutationObserverWrapper; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject& window_object, Bindings::CallbackType* callback) + static NonnullRefPtr create_with_global_object(HTML::Window& window_object, Bindings::CallbackType* callback) { return adopt_ref(*new MutationObserver(window_object, JS::make_handle(callback))); } @@ -56,7 +56,7 @@ public: } private: - MutationObserver(Bindings::WindowObject& window_object, JS::Handle callback); + MutationObserver(HTML::Window& window_object, JS::Handle callback); // https://dom.spec.whatwg.org/#concept-mo-callback JS::Handle m_callback; diff --git a/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp b/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp index ded0a0ec718185f469bdaaa831889b60764d7b10..78fdbdb9c60d0914fdc71a8c467de88950f31762 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp +++ b/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp @@ -14,11 +14,11 @@ class MutationRecordImpl final : public MutationRecord { public: MutationRecordImpl(FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value) : m_type(type) - , m_target(target) + , m_target(JS::make_handle(target)) , m_added_nodes(added_nodes) , m_removed_nodes(removed_nodes) - , m_previous_sibling(previous_sibling) - , m_next_sibling(next_sibling) + , m_previous_sibling(JS::make_handle(previous_sibling)) + , m_next_sibling(JS::make_handle(next_sibling)) , m_attribute_name(attribute_name) , m_attribute_namespace(attribute_namespace) , m_old_value(old_value) @@ -28,22 +28,22 @@ public: virtual ~MutationRecordImpl() override = default; virtual FlyString const& type() const override { return m_type; } - virtual Node const* target() const override { return m_target; } + virtual Node const* target() const override { return m_target.ptr(); } virtual NodeList const* added_nodes() const override { return m_added_nodes; } virtual NodeList const* removed_nodes() const override { return m_removed_nodes; } - virtual Node const* previous_sibling() const override { return m_previous_sibling; } - virtual Node const* next_sibling() const override { return m_next_sibling; } + virtual Node const* previous_sibling() const override { return m_previous_sibling.ptr(); } + virtual Node const* next_sibling() const override { return m_next_sibling.ptr(); } virtual String const& attribute_name() const override { return m_attribute_name; } virtual String const& attribute_namespace() const override { return m_attribute_namespace; } virtual String const& old_value() const override { return m_old_value; } private: FlyString m_type; - NonnullRefPtr m_target; + JS::Handle m_target; NonnullRefPtr m_added_nodes; NonnullRefPtr m_removed_nodes; - RefPtr m_previous_sibling; - RefPtr m_next_sibling; + JS::Handle m_previous_sibling; + JS::Handle m_next_sibling; String m_attribute_name; String m_attribute_namespace; String m_old_value; diff --git a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp index bcc41bc824d8f472c60da37af84c4c8765177463..3a80acc74896e8e203e7c5c21af5ea8443fefd09 100644 --- a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp +++ b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp @@ -6,9 +6,6 @@ */ #include -#include -#include -#include #include #include #include @@ -16,18 +13,26 @@ namespace Web::DOM { -NamedNodeMap* NamedNodeMap::create(Element& element) +JS::NonnullGCPtr NamedNodeMap::create(Element& element) { - auto& realm = element.document().preferred_window_object().realm(); - return realm.heap().allocate(realm, element); + auto& realm = element.realm(); + return *realm.heap().allocate(realm, element); } NamedNodeMap::NamedNodeMap(Element& element) - : Bindings::LegacyPlatformObject(element.document().preferred_window_object().ensure_web_prototype("NamedNodeMap")) + : Bindings::LegacyPlatformObject(element.document().window().ensure_web_prototype("NamedNodeMap")) , m_element(element) { } +void NamedNodeMap::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_element.ptr()); + for (auto& attribute : m_attributes) + visitor.visit(attribute.ptr()); +} + // https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-indices%E2%91%A3 bool NamedNodeMap::is_supported_property_index(u32 index) const { @@ -42,8 +47,8 @@ Vector NamedNodeMap::supported_property_names() const names.ensure_capacity(m_attributes.size()); for (auto const& attribute : m_attributes) { - if (!names.contains_slow(attribute.name())) - names.append(attribute.name()); + if (!names.contains_slow(attribute->name())) + names.append(attribute->name()); } // 2. If this NamedNodeMap object’s element is in the HTML namespace and its node document is an HTML document, then for each name in names: @@ -66,7 +71,7 @@ Attribute const* NamedNodeMap::item(u32 index) const return nullptr; // 2. Otherwise, return this’s attribute list[index]. - return &m_attributes[index]; + return m_attributes[index].ptr(); } // https://dom.spec.whatwg.org/#dom-namednodemap-getnameditem @@ -114,11 +119,11 @@ Attribute const* NamedNodeMap::get_attribute(StringView qualified_name, size_t* // 2. Return the first attribute in element’s attribute list whose qualified name is qualifiedName; otherwise null. for (auto const& attribute : m_attributes) { if (compare_as_lowercase) { - if (attribute.name().equals_ignoring_case(qualified_name)) - return &attribute; + if (attribute->name().equals_ignoring_case(qualified_name)) + return attribute.ptr(); } else { - if (attribute.name() == qualified_name) - return &attribute; + if (attribute->name() == qualified_name) + return attribute.ptr(); } if (item_index) @@ -191,7 +196,7 @@ void NamedNodeMap::append_attribute(Attribute& attribute) // https://dom.spec.whatwg.org/#concept-element-attributes-remove void NamedNodeMap::remove_attribute_at_index(size_t attribute_index) { - NonnullRefPtr attribute = m_attributes.at(attribute_index); + JS::NonnullGCPtr attribute = m_attributes.at(attribute_index); // 1. Handle attribute changes for attribute with attribute’s element, attribute’s value, and null. VERIFY(attribute->owner_element()); @@ -225,7 +230,7 @@ JS::Value NamedNodeMap::item_value(size_t index) const auto const* node = item(index); if (!node) return JS::js_undefined(); - return Bindings::wrap(shape().realm(), const_cast(*node)); + return node; } JS::Value NamedNodeMap::named_item_value(FlyString const& name) const @@ -233,7 +238,7 @@ JS::Value NamedNodeMap::named_item_value(FlyString const& name) const auto const* node = get_named_item(name); if (!node) return JS::js_undefined(); - return Bindings::wrap(shape().realm(), const_cast(*node)); + return node; } } diff --git a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h index d03d3402900440bb87a4b0b3511afe4df6776b91..7cc33a63b68f1960958d23b1780c335531de041d 100644 --- a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h +++ b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h @@ -18,15 +18,12 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#interface-namednodemap class NamedNodeMap : public Bindings::LegacyPlatformObject { - JS_OBJECT(NamedNodeMap, Bindings::LegacyPlatformObject); + WEB_PLATFORM_OBJECT(NamedNodeMap, Bindings::LegacyPlatformObject); public: - static NamedNodeMap* create(Element&); - explicit NamedNodeMap(Element&); + static JS::NonnullGCPtr create(Element&); ~NamedNodeMap() = default; - NamedNodeMap& impl() { return *this; } - virtual bool is_supported_property_index(u32 index) const override; virtual Vector supported_property_names() const override; virtual JS::Value item_value(size_t index) const override; @@ -50,18 +47,19 @@ public: Attribute const* remove_attribute(StringView qualified_name); private: - Element& associated_element() { return m_element; } - Element const& associated_element() const { return m_element; } + explicit NamedNodeMap(Element&); + + virtual void visit_edges(Cell::Visitor&) override; + + Element& associated_element() { return *m_element; } + Element const& associated_element() const { return *m_element; } void remove_attribute_at_index(size_t attribute_index); - DOM::Element& m_element; - NonnullRefPtrVector m_attributes; + JS::NonnullGCPtr m_element; + Vector> m_attributes; }; } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::DOM::NamedNodeMap& object) { return &object; } -using NamedNodeMapWrapper = Web::DOM::NamedNodeMap; -} +WRAPPER_HACK(NamedNodeMap, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index b3825ccee82dcb5563c51ed2c2f252b232050060..fc08dac50d74fe48904f64af8497ad46453b59f7 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -11,8 +11,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -23,7 +22,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -58,28 +59,38 @@ Node* Node::from_id(i32 node_id) return s_node_directory.get(node_id).value_or(nullptr); } -Node::Node(Document& document, NodeType type) - : EventTarget() +Node::Node(JS::Realm& realm, Document& document, NodeType type) + : EventTarget(realm) , m_document(&document) , m_type(type) , m_id(allocate_node_id(this)) { - if (!is_document()) - m_document->ref_from_node({}); +} + +Node::Node(Document& document, NodeType type) + : Node(document.realm(), document, type) +{ } Node::~Node() { - VERIFY(m_deletion_has_begun); if (layout_node() && layout_node()->parent()) layout_node()->parent()->remove_child(*layout_node()); - if (!is_document()) - m_document->unref_from_node({}); - deallocate_node_id(m_id); } +void Node::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_document.ptr()); + visitor.visit(m_parent.ptr()); + visitor.visit(m_first_child.ptr()); + visitor.visit(m_last_child.ptr()); + visitor.visit(m_next_sibling.ptr()); + visitor.visit(m_previous_sibling.ptr()); +} + // https://dom.spec.whatwg.org/#dom-node-baseuri String Node::base_uri() const { @@ -291,7 +302,7 @@ Element const* Node::parent_element() const } // https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity -ExceptionOr Node::ensure_pre_insertion_validity(NonnullRefPtr node, RefPtr child) const +ExceptionOr Node::ensure_pre_insertion_validity(JS::NonnullGCPtr node, JS::GCPtr child) const { // 1. If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException. if (!is(this) && !is(this) && !is(this)) @@ -342,14 +353,14 @@ ExceptionOr Node::ensure_pre_insertion_validity(NonnullRefPtr node, } // https://dom.spec.whatwg.org/#concept-node-insert -void Node::insert_before(NonnullRefPtr node, RefPtr child, bool suppress_observers) +void Node::insert_before(JS::NonnullGCPtr node, JS::GCPtr child, bool suppress_observers) { // 1. Let nodes be node’s children, if node is a DocumentFragment node; otherwise « node ». - NonnullRefPtrVector nodes; + Vector> nodes; if (is(*node)) nodes = node->children_as_vector(); else - nodes.append(node); + nodes.append(JS::make_handle(*node)); // 2. Let count be nodes’s size. auto count = nodes.size(); @@ -384,7 +395,7 @@ void Node::insert_before(NonnullRefPtr node, RefPtr child, bool supp } // 6. Let previousSibling be child’s previous sibling or parent’s last child if child is null. - RefPtr previous_sibling; + JS::GCPtr previous_sibling; if (child) previous_sibling = child->previous_sibling(); else @@ -394,14 +405,14 @@ void Node::insert_before(NonnullRefPtr node, RefPtr child, bool supp // FIXME: In tree order for (auto& node_to_insert : nodes) { // 1. Adopt node into parent’s node document. - document().adopt_node(node_to_insert); + document().adopt_node(*node_to_insert); // 2. If child is null, then append node to parent’s children. if (!child) - TreeNode::append_child(node_to_insert); + append_child_impl(*node_to_insert); // 3. Otherwise, insert node into parent’s children before child’s index. else - TreeNode::insert_before(node_to_insert, child); + insert_before_impl(*node_to_insert, child); // FIXME: 4. If parent is a shadow host and node is a slottable, then assign a slot for node. // FIXME: 5. If parent’s root is a shadow root, and parent is a slot whose assigned nodes is the empty list, then run signal a slot change for parent. @@ -409,7 +420,7 @@ void Node::insert_before(NonnullRefPtr node, RefPtr child, bool supp // FIXME: This should be shadow-including. // 7. For each shadow-including inclusive descendant inclusiveDescendant of node, in shadow-including tree order: - node_to_insert.for_each_in_inclusive_subtree([&](Node& inclusive_descendant) { + node_to_insert->for_each_in_inclusive_subtree([&](Node& inclusive_descendant) { // 1. Run the insertion steps with inclusiveDescendant. inclusive_descendant.inserted(); @@ -427,7 +438,7 @@ void Node::insert_before(NonnullRefPtr node, RefPtr child, bool supp // 8. If suppress observers flag is unset, then queue a tree mutation record for parent with nodes, « », previousSibling, and child. if (!suppress_observers) - queue_tree_mutation_record(StaticNodeList::create(move(nodes)), StaticNodeList::create({}), previous_sibling, child); + queue_tree_mutation_record(StaticNodeList::create(move(nodes)), StaticNodeList::create({}), previous_sibling.ptr(), child.ptr()); // 9. Run the children changed steps for parent. children_changed(); @@ -436,7 +447,7 @@ void Node::insert_before(NonnullRefPtr node, RefPtr child, bool supp } // https://dom.spec.whatwg.org/#concept-node-pre-insert -ExceptionOr> Node::pre_insert(NonnullRefPtr node, RefPtr child) +ExceptionOr> Node::pre_insert(JS::NonnullGCPtr node, JS::GCPtr child) { // 1. Ensure pre-insertion validity of node into parent before child. TRY(ensure_pre_insertion_validity(node, child)); @@ -456,14 +467,14 @@ ExceptionOr> Node::pre_insert(NonnullRefPtr node, RefP } // https://dom.spec.whatwg.org/#dom-node-removechild -ExceptionOr> Node::remove_child(NonnullRefPtr child) +ExceptionOr> Node::remove_child(JS::NonnullGCPtr child) { // The removeChild(child) method steps are to return the result of pre-removing child from this. return pre_remove(child); } // https://dom.spec.whatwg.org/#concept-node-pre-remove -ExceptionOr> Node::pre_remove(NonnullRefPtr child) +ExceptionOr> Node::pre_remove(JS::NonnullGCPtr child) { // 1. If child’s parent is not parent, then throw a "NotFoundError" DOMException. if (child->parent() != this) @@ -477,7 +488,7 @@ ExceptionOr> Node::pre_remove(NonnullRefPtr child) } // https://dom.spec.whatwg.org/#concept-node-append -ExceptionOr> Node::append_child(NonnullRefPtr node) +ExceptionOr> Node::append_child(JS::NonnullGCPtr node) { // To append a node to a parent, pre-insert node into parent before null. return pre_insert(node, nullptr); @@ -487,7 +498,7 @@ ExceptionOr> Node::append_child(NonnullRefPtr node) void Node::remove(bool suppress_observers) { // 1. Let parent be node’s parent - auto* parent = TreeNode::parent(); + auto* parent = this->parent(); // 2. Assert: parent is non-null. VERIFY(parent); @@ -525,13 +536,13 @@ void Node::remove(bool suppress_observers) }); // 9. Let oldPreviousSibling be node’s previous sibling. - RefPtr old_previous_sibling = previous_sibling(); + JS::GCPtr old_previous_sibling = previous_sibling(); // 10. Let oldNextSibling be node’s next sibling. - RefPtr old_next_sibling = next_sibling(); + JS::GCPtr old_next_sibling = next_sibling(); // 11. Remove node from its parent’s children. - parent->TreeNode::remove_child(*this); + parent->remove_child_impl(*this); // FIXME: 12. If node is assigned, then run assign slottables for node’s assigned slot. @@ -576,9 +587,9 @@ void Node::remove(bool suppress_observers) // 20. If suppress observers flag is unset, then queue a tree mutation record for parent with « », « node », oldPreviousSibling, and oldNextSibling. if (!suppress_observers) { - NonnullRefPtrVector removed_nodes; - removed_nodes.append(*this); - parent->queue_tree_mutation_record(StaticNodeList::create({}), StaticNodeList::create(move(removed_nodes)), old_previous_sibling, old_next_sibling); + Vector> removed_nodes; + removed_nodes.append(JS::make_handle(*this)); + parent->queue_tree_mutation_record(StaticNodeList::create({}), StaticNodeList::create(move(removed_nodes)), old_previous_sibling.ptr(), old_next_sibling.ptr()); } // 21. Run the children changed steps for parent. @@ -588,7 +599,7 @@ void Node::remove(bool suppress_observers) } // https://dom.spec.whatwg.org/#concept-node-replace -ExceptionOr> Node::replace_child(NonnullRefPtr node, NonnullRefPtr child) +ExceptionOr> Node::replace_child(JS::NonnullGCPtr node, JS::NonnullGCPtr child) { // If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException. if (!is(this) && !is(this) && !is(this)) @@ -637,52 +648,52 @@ ExceptionOr> Node::replace_child(NonnullRefPtr node, N } // 7. Let referenceChild be child’s next sibling. - RefPtr reference_child = child->next_sibling(); + JS::GCPtr reference_child = child->next_sibling(); // 8. If referenceChild is node, then set referenceChild to node’s next sibling. if (reference_child == node) reference_child = node->next_sibling(); // 9. Let previousSibling be child’s previous sibling. - RefPtr previous_sibling = child->previous_sibling(); + JS::GCPtr previous_sibling = child->previous_sibling(); // 10. Let removedNodes be the empty set. - NonnullRefPtrVector removed_nodes; + Vector> removed_nodes; // 11. If child’s parent is non-null, then: // NOTE: The above can only be false if child is node. if (child->parent()) { // 1. Set removedNodes to « child ». - removed_nodes.append(child); + removed_nodes.append(JS::make_handle(*child)); // 2. Remove child with the suppress observers flag set. child->remove(true); } // 12. Let nodes be node’s children if node is a DocumentFragment node; otherwise « node ». - NonnullRefPtrVector nodes; + Vector> nodes; if (is(*node)) nodes = node->children_as_vector(); else - nodes.append(node); + nodes.append(JS::make_handle(*node)); // 13. Insert node into parent before referenceChild with the suppress observers flag set. insert_before(node, reference_child, true); // 14. Queue a tree mutation record for parent with nodes, removedNodes, previousSibling, and referenceChild. - queue_tree_mutation_record(StaticNodeList::create(move(nodes)), StaticNodeList::create(move(removed_nodes)), previous_sibling, reference_child); + queue_tree_mutation_record(StaticNodeList::create(move(nodes)), StaticNodeList::create(move(removed_nodes)), previous_sibling.ptr(), reference_child.ptr()); // 15. Return child. return child; } // https://dom.spec.whatwg.org/#concept-node-clone -NonnullRefPtr Node::clone_node(Document* document, bool clone_children) +JS::NonnullGCPtr Node::clone_node(Document* document, bool clone_children) { // 1. If document is not given, let document be node’s node document. if (!document) - document = m_document; - RefPtr copy; + document = m_document.ptr(); + JS::GCPtr copy; // 2. If node is an element, then: if (is(this)) { @@ -703,7 +714,7 @@ NonnullRefPtr Node::clone_node(Document* document, bool clone_children) else if (is(this)) { // Document auto document_ = verify_cast(this); - auto document_copy = Document::create(document_->url()); + auto document_copy = Document::create(Bindings::main_thread_internal_window_object(), document_->url()); // Set copy’s encoding, content type, URL, origin, type, and mode to those of node. document_copy->set_encoding(document_->encoding()); @@ -716,7 +727,7 @@ NonnullRefPtr Node::clone_node(Document* document, bool clone_children) } else if (is(this)) { // DocumentType auto document_type = verify_cast(this); - auto document_type_copy = adopt_ref(*new DocumentType(*document)); + auto document_type_copy = heap().allocate(realm(), *document); // Set copy’s name, public ID, and system ID to those of node. document_type_copy->set_name(document_type->name()); @@ -733,26 +744,26 @@ NonnullRefPtr Node::clone_node(Document* document, bool clone_children) auto text = verify_cast(this); // Set copy’s data to that of node. - auto text_copy = adopt_ref(*new Text(*document, text->data())); + auto text_copy = heap().allocate(realm(), *document, text->data()); copy = move(text_copy); } else if (is(this)) { // Comment auto comment = verify_cast(this); // Set copy’s data to that of node. - auto comment_copy = adopt_ref(*new Comment(*document, comment->data())); + auto comment_copy = heap().allocate(realm(), *document, comment->data()); copy = move(comment_copy); } else if (is(this)) { // ProcessingInstruction auto processing_instruction = verify_cast(this); // Set copy’s target and data to those of node. - auto processing_instruction_copy = adopt_ref(*new ProcessingInstruction(*document, processing_instruction->data(), processing_instruction->target())); - copy = move(processing_instruction_copy); + auto processing_instruction_copy = heap().allocate(realm(), *document, processing_instruction->data(), processing_instruction->target()); + copy = processing_instruction_copy; } // Otherwise, Do nothing. else if (is(this)) { - copy = adopt_ref(*new DocumentFragment(*document)); + copy = heap().allocate(realm(), *document); } // FIXME: 4. Set copy’s node document and document to copy, if copy is a document, and set copy’s node document to document otherwise. @@ -768,11 +779,11 @@ NonnullRefPtr Node::clone_node(Document* document, bool clone_children) } // 7. Return copy. - return copy.release_nonnull(); + return *copy; } // https://dom.spec.whatwg.org/#dom-node-clonenode -ExceptionOr> Node::clone_node_binding(bool deep) +ExceptionOr> Node::clone_node_binding(bool deep) { // 1. If this is a shadow root, then throw a "NotSupportedError" DOMException. if (is(*this)) @@ -784,11 +795,9 @@ ExceptionOr> Node::clone_node_binding(bool deep) void Node::set_document(Badge, Document& document) { - if (m_document == &document) + if (m_document.ptr() == &document) return; - document.ref_from_node({}); - m_document->unref_from_node({}); m_document = &document; if (needs_style_update() || child_needs_style_update()) { @@ -805,21 +814,6 @@ bool Node::is_editable() const return parent() && parent()->is_editable(); } -JS::Object* Node::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - -void Node::removed_last_ref() -{ - if (is(*this)) { - verify_cast(*this).removed_last_ref(); - return; - } - m_deletion_has_begun = true; - delete this; -} - void Node::set_layout_node(Badge, Layout::Node* layout_node) const { m_layout_node = layout_node; @@ -866,12 +860,12 @@ NonnullRefPtr Node::child_nodes() }); } -NonnullRefPtrVector Node::children_as_vector() const +Vector> Node::children_as_vector() const { - NonnullRefPtrVector nodes; + Vector> nodes; for_each_child([&](auto& child) { - nodes.append(child); + nodes.append(JS::make_handle(child)); }); return nodes; @@ -879,12 +873,12 @@ NonnullRefPtrVector Node::children_as_vector() const void Node::remove_all_children(bool suppress_observers) { - while (RefPtr child = first_child()) + while (JS::GCPtr child = first_child()) child->remove(suppress_observers); } // https://dom.spec.whatwg.org/#dom-node-comparedocumentposition -u16 Node::compare_document_position(RefPtr other) +u16 Node::compare_document_position(JS::GCPtr other) { enum Position : u16 { DOCUMENT_POSITION_EQUAL = 0, @@ -897,7 +891,7 @@ u16 Node::compare_document_position(RefPtr other) }; // 1. If this is other, then return zero. - if (this == other) + if (this == other.ptr()) return DOCUMENT_POSITION_EQUAL; // 2. Let node1 be other and node2 be this. @@ -967,7 +961,7 @@ bool Node::is_host_including_inclusive_ancestor_of(Node const& other) const } // https://dom.spec.whatwg.org/#dom-node-ownerdocument -RefPtr Node::owner_document() const +JS::GCPtr Node::owner_document() const { // The ownerDocument getter steps are to return null, if this is a document; otherwise this’s node document. if (is_document()) @@ -1067,7 +1061,7 @@ bool Node::is_scripting_disabled() const } // https://dom.spec.whatwg.org/#dom-node-contains -bool Node::contains(RefPtr other) const +bool Node::contains(JS::GCPtr other) const { // The contains(other) method steps are to return true if other is an inclusive descendant of this; otherwise false (including when other is null). return other && other->is_inclusive_descendant_of(*this); @@ -1113,13 +1107,13 @@ bool Node::is_shadow_including_inclusive_ancestor_of(Node const& other) const } // https://dom.spec.whatwg.org/#concept-node-replace-all -void Node::replace_all(RefPtr node) +void Node::replace_all(JS::GCPtr node) { // 1. Let removedNodes be parent’s children. auto removed_nodes = children_as_vector(); // 2. Let addedNodes be the empty set. - NonnullRefPtrVector added_nodes; + Vector> added_nodes; // 3. If node is a DocumentFragment node, then set addedNodes to node’s children. if (node && is(*node)) { @@ -1127,7 +1121,7 @@ void Node::replace_all(RefPtr node) } // 4. Otherwise, if node is non-null, set addedNodes to « node ». else if (node) { - added_nodes.append(*node); + added_nodes.append(JS::make_handle(*node)); } // 5. Remove all parent’s children, in tree order, with the suppress observers flag set. @@ -1146,11 +1140,11 @@ void Node::replace_all(RefPtr node) void Node::string_replace_all(String const& string) { // 1. Let node be null. - RefPtr node; + JS::GCPtr node; // 2. If string is not the empty string, then set node to a new Text node whose data is string and node document is parent’s node document. if (!string.is_empty()) - node = make_ref_counted(document(), string); + node = heap().allocate(realm(), document(), string); // 3. Replace all with node within parent. replace_all(node); @@ -1267,7 +1261,7 @@ bool Node::in_a_document_tree() const } // https://dom.spec.whatwg.org/#dom-node-getrootnode -NonnullRefPtr Node::get_root_node(GetRootNodeOptions const& options) +JS::NonnullGCPtr Node::get_root_node(GetRootNodeOptions const& options) { // The getRootNode(options) method steps are to return this’s shadow-including root if options["composed"] is true; if (options.composed) @@ -1332,15 +1326,15 @@ void Node::queue_mutation_record(FlyString const& type, String attribute_name, S OrderedHashMap, String> interested_observers; // 2. Let nodes be the inclusive ancestors of target. - NonnullRefPtrVector nodes; - nodes.append(*this); + Vector> nodes; + nodes.append(JS::make_handle(*this)); for (auto* parent_node = parent(); parent_node; parent_node = parent_node->parent()) - nodes.append(*parent_node); + nodes.append(JS::make_handle(*parent_node)); // 3. For each node in nodes, and then for each registered of node’s registered observer list: for (auto& node : nodes) { - for (auto& registered_observer : node.m_registered_observer_list) { + for (auto& registered_observer : node->m_registered_observer_list) { // 1. Let options be registered’s options. auto& options = registered_observer.options; @@ -1351,7 +1345,7 @@ void Node::queue_mutation_record(FlyString const& type, String attribute_name, S // - type is "characterData" and options["characterData"] either does not exist or is false // - type is "childList" and options["childList"] is false // then: - if (!(&node != this && !options.subtree) + if (!(node.ptr() != this && !options.subtree) && !(type == MutationType::attributes && (!options.attributes.has_value() || !options.attributes.value())) && !(type == MutationType::attributes && options.attribute_filter.has_value() && (!attribute_namespace.is_null() || !options.attribute_filter->contains_slow(attribute_name))) && !(type == MutationType::characterData && (!options.character_data.has_value() || !options.character_data.value())) @@ -1394,4 +1388,99 @@ void Node::queue_tree_mutation_record(NonnullRefPtr added_nodes, Nonnu queue_mutation_record(MutationType::childList, {}, {}, {}, move(added_nodes), move(removed_nodes), previous_sibling, next_sibling); } +void Node::append_child_impl(JS::NonnullGCPtr node) +{ + VERIFY(!node->m_parent); + + if (!is_child_allowed(*node)) + return; + + if (m_last_child) + m_last_child->m_next_sibling = node.ptr(); + node->m_previous_sibling = m_last_child; + node->m_parent = this; + m_last_child = node.ptr(); + if (!m_first_child) + m_first_child = m_last_child; +} + +void Node::insert_before_impl(JS::NonnullGCPtr node, JS::GCPtr child) +{ + if (!child) + return append_child_impl(move(node)); + + VERIFY(!node->m_parent); + VERIFY(child->parent() == this); + + node->m_previous_sibling = child->m_previous_sibling; + node->m_next_sibling = child; + + if (child->m_previous_sibling) + child->m_previous_sibling->m_next_sibling = node; + + if (m_first_child == child) + m_first_child = node; + + child->m_previous_sibling = node; + + node->m_parent = this; +} + +void Node::remove_child_impl(JS::NonnullGCPtr node) +{ + VERIFY(node->m_parent.ptr() == this); + + if (m_first_child == node) + m_first_child = node->m_next_sibling; + + if (m_last_child == node) + m_last_child = node->m_previous_sibling; + + if (node->m_next_sibling) + node->m_next_sibling->m_previous_sibling = node->m_previous_sibling; + + if (node->m_previous_sibling) + node->m_previous_sibling->m_next_sibling = node->m_next_sibling; + + node->m_next_sibling = nullptr; + node->m_previous_sibling = nullptr; + node->m_parent = nullptr; +} + +bool Node::is_ancestor_of(Node const& other) const +{ + for (auto* ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) { + if (ancestor == this) + return true; + } + return false; +} + +bool Node::is_inclusive_ancestor_of(Node const& other) const +{ + return &other == this || is_ancestor_of(other); +} + +bool Node::is_descendant_of(Node const& other) const +{ + return other.is_ancestor_of(*this); +} + +bool Node::is_inclusive_descendant_of(Node const& other) const +{ + return other.is_inclusive_ancestor_of(*this); +} + +// https://dom.spec.whatwg.org/#concept-tree-following +bool Node::is_following(Node const& other) const +{ + // An object A is following an object B if A and B are in the same tree and A comes after B in tree order. + for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) { + if (node == &other) + return true; + } + + return false; +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h index d0e7354d69c179e535222749c1542bc928f3a515..f4d4b90120d206457cb5905b10bc4aa0ac96acaa 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.h +++ b/Userland/Libraries/LibWeb/DOM/Node.h @@ -16,7 +16,6 @@ #include #include #include -#include namespace Web::DOM { @@ -40,26 +39,16 @@ struct GetRootNodeOptions { bool composed { false }; }; -class Node - : public TreeNode - , public EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::NodeWrapper; - - using TreeNode::ref; - using TreeNode::unref; +class Node : public EventTarget { + WEB_PLATFORM_OBJECT(Node, EventTarget); +public: ParentNode* parent_or_shadow_host(); ParentNode const* parent_or_shadow_host() const { return const_cast(this)->parent_or_shadow_host(); } - // ^EventTarget - virtual void ref_event_target() final { ref(); } - virtual void unref_event_target() final { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; - virtual ~Node(); + // FIXME: Move cleanup to the regular destructor. void removed_last_ref(); NodeType type() const { return m_type; } @@ -94,26 +83,26 @@ public: virtual bool is_html_template_element() const { return false; } virtual bool is_browsing_context_container() const { return false; } - ExceptionOr> pre_insert(NonnullRefPtr, RefPtr); - ExceptionOr> pre_remove(NonnullRefPtr); + ExceptionOr> pre_insert(JS::NonnullGCPtr, JS::GCPtr); + ExceptionOr> pre_remove(JS::NonnullGCPtr); - ExceptionOr> append_child(NonnullRefPtr); - ExceptionOr> remove_child(NonnullRefPtr); + ExceptionOr> append_child(JS::NonnullGCPtr); + ExceptionOr> remove_child(JS::NonnullGCPtr); - void insert_before(NonnullRefPtr node, RefPtr child, bool suppress_observers = false); + void insert_before(JS::NonnullGCPtr node, JS::GCPtr child, bool suppress_observers = false); void remove(bool suppress_observers = false); void remove_all_children(bool suppress_observers = false); - u16 compare_document_position(RefPtr other); + u16 compare_document_position(JS::GCPtr other); - ExceptionOr> replace_child(NonnullRefPtr node, NonnullRefPtr child); + ExceptionOr> replace_child(JS::NonnullGCPtr node, JS::NonnullGCPtr child); - NonnullRefPtr clone_node(Document* document = nullptr, bool clone_children = false); - ExceptionOr> clone_node_binding(bool deep); + JS::NonnullGCPtr clone_node(Document* document = nullptr, bool clone_children = false); + ExceptionOr> clone_node_binding(bool deep); // NOTE: This is intended for the JS bindings. bool has_child_nodes() const { return has_children(); } NonnullRefPtr child_nodes(); - NonnullRefPtrVector children_as_vector() const; + Vector> children_as_vector() const; virtual FlyString node_name() const = 0; @@ -129,7 +118,7 @@ public: Document& document() { return *m_document; } Document const& document() const { return *m_document; } - RefPtr owner_document() const; + JS::GCPtr owner_document() const; const HTML::HTMLAnchorElement* enclosing_link_element() const; const HTML::HTMLElement* enclosing_html_element() const; @@ -190,14 +179,14 @@ public: template bool fast_is() const = delete; - ExceptionOr ensure_pre_insertion_validity(NonnullRefPtr node, RefPtr child) const; + ExceptionOr ensure_pre_insertion_validity(JS::NonnullGCPtr node, JS::GCPtr child) const; bool is_host_including_inclusive_ancestor_of(Node const&) const; bool is_scripting_enabled() const; bool is_scripting_disabled() const; - bool contains(RefPtr) const; + bool contains(JS::GCPtr) const; // Used for dumping the DOM Tree void serialize_tree_as_json(JsonObjectSerializer&) const; @@ -212,13 +201,13 @@ public: String serialize_fragment() const; - void replace_all(RefPtr); + void replace_all(JS::GCPtr); void string_replace_all(String const&); bool is_same_node(Node const*) const; bool is_equal_node(Node const*) const; - NonnullRefPtr get_root_node(GetRootNodeOptions const& options = {}); + JS::NonnullGCPtr get_root_node(GetRootNodeOptions const& options = {}); bool is_uninteresting_whitespace_node() const; @@ -237,10 +226,407 @@ public: template IterationDecision for_each_shadow_including_descendant(Callback); + Node* parent() { return m_parent.ptr(); } + Node const* parent() const { return m_parent.ptr(); } + + bool has_children() const { return m_first_child; } + Node* next_sibling() { return m_next_sibling.ptr(); } + Node* previous_sibling() { return m_previous_sibling.ptr(); } + Node* first_child() { return m_first_child.ptr(); } + Node* last_child() { return m_last_child.ptr(); } + Node const* next_sibling() const { return m_next_sibling.ptr(); } + Node const* previous_sibling() const { return m_previous_sibling.ptr(); } + Node const* first_child() const { return m_first_child.ptr(); } + Node const* last_child() const { return m_last_child.ptr(); } + + size_t child_count() const + { + size_t count = 0; + for (auto* child = first_child(); child; child = child->next_sibling()) + ++count; + return count; + } + + Node* child_at_index(int index) + { + int count = 0; + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (count == index) + return child; + ++count; + } + return nullptr; + } + + Node const* child_at_index(int index) const + { + return const_cast(this)->child_at_index(index); + } + + // https://dom.spec.whatwg.org/#concept-tree-index + size_t index() const + { + // The index of an object is its number of preceding siblings, or 0 if it has none. + size_t index = 0; + for (auto* node = previous_sibling(); node; node = node->previous_sibling()) + ++index; + return index; + } + + Optional index_of_child(Node const& search_child) + { + VERIFY(search_child.parent() == this); + size_t index = 0; + auto* child = first_child(); + VERIFY(child); + + do { + if (child == &search_child) + return index; + index++; + } while (child && (child = child->next_sibling())); + return {}; + } + + template + Optional index_of_child(Node const& search_child) + { + VERIFY(search_child.parent() == this); + size_t index = 0; + auto* child = first_child(); + VERIFY(child); + + do { + if (!is(child)) + continue; + if (child == &search_child) + return index; + index++; + } while (child && (child = child->next_sibling())); + return {}; + } + + bool is_ancestor_of(Node const&) const; + bool is_inclusive_ancestor_of(Node const&) const; + bool is_descendant_of(Node const&) const; + bool is_inclusive_descendant_of(Node const&) const; + + bool is_following(Node const&) const; + + void prepend_child(JS::NonnullGCPtr node); + + Node* next_in_pre_order() + { + if (first_child()) + return first_child(); + Node* node; + if (!(node = next_sibling())) { + node = parent(); + while (node && !node->next_sibling()) + node = node->parent(); + if (node) + node = node->next_sibling(); + } + return node; + } + + Node* next_in_pre_order(Node const* stay_within) + { + if (first_child()) + return first_child(); + + Node* node = static_cast(this); + Node* next = nullptr; + while (!(next = node->next_sibling())) { + node = node->parent(); + if (!node || node == stay_within) + return nullptr; + } + return next; + } + + Node const* next_in_pre_order() const + { + return const_cast(this)->next_in_pre_order(); + } + + Node const* next_in_pre_order(Node const* stay_within) const + { + return const_cast(this)->next_in_pre_order(stay_within); + } + + Node* previous_in_pre_order() + { + if (auto* node = previous_sibling()) { + while (node->last_child()) + node = node->last_child(); + + return node; + } + + return parent(); + } + + Node const* previous_in_pre_order() const + { + return const_cast(this)->previous_in_pre_order(); + } + + bool is_before(Node const& other) const + { + if (this == &other) + return false; + for (auto* node = this; node; node = node->next_in_pre_order()) { + if (node == &other) + return true; + } + return false; + } + + // https://dom.spec.whatwg.org/#concept-tree-preceding (Object A is 'typename U' and Object B is 'this') + template + bool has_preceding_node_of_type_in_tree_order() const + { + for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) { + if (is(node)) + return true; + } + return false; + } + + // https://dom.spec.whatwg.org/#concept-tree-following (Object A is 'typename U' and Object B is 'this') + template + bool has_following_node_of_type_in_tree_order() const + { + for (auto* node = next_in_pre_order(); node; node = node->next_in_pre_order()) { + if (is(node)) + return true; + } + return false; + } + + template + IterationDecision for_each_in_inclusive_subtree(Callback callback) const + { + if (callback(static_cast(*this)) == IterationDecision::Break) + return IterationDecision::Break; + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + IterationDecision for_each_in_inclusive_subtree(Callback callback) + { + if (callback(static_cast(*this)) == IterationDecision::Break) + return IterationDecision::Break; + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) + { + if (is(static_cast(*this))) { + if (callback(static_cast(*this)) == IterationDecision::Break) + return IterationDecision::Break; + } + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->template for_each_in_inclusive_subtree_of_type(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) const + { + if (is(static_cast(*this))) { + if (callback(static_cast(*this)) == IterationDecision::Break) + return IterationDecision::Break; + } + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->template for_each_in_inclusive_subtree_of_type(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + IterationDecision for_each_in_subtree(Callback callback) const + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + IterationDecision for_each_in_subtree(Callback callback) + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + IterationDecision for_each_in_subtree_of_type(Callback callback) + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->template for_each_in_inclusive_subtree_of_type(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + IterationDecision for_each_in_subtree_of_type(Callback callback) const + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (child->template for_each_in_inclusive_subtree_of_type(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template + void for_each_child(Callback callback) const + { + return const_cast(this)->template for_each_child(move(callback)); + } + + template + void for_each_child(Callback callback) + { + for (auto* node = first_child(); node; node = node->next_sibling()) + callback(*node); + } + + template + void for_each_child_of_type(Callback callback) + { + for (auto* node = first_child(); node; node = node->next_sibling()) { + if (is(node)) + callback(verify_cast(*node)); + } + } + + template + void for_each_child_of_type(Callback callback) const + { + return const_cast(this)->template for_each_child_of_type(move(callback)); + } + + template + U const* next_sibling_of_type() const + { + return const_cast(this)->template next_sibling_of_type(); + } + + template + inline U* next_sibling_of_type() + { + for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) { + if (is(*sibling)) + return &verify_cast(*sibling); + } + return nullptr; + } + + template + U const* previous_sibling_of_type() const + { + return const_cast(this)->template previous_sibling_of_type(); + } + + template + U* previous_sibling_of_type() + { + for (auto* sibling = previous_sibling(); sibling; sibling = sibling->previous_sibling()) { + if (is(*sibling)) + return &verify_cast(*sibling); + } + return nullptr; + } + + template + U const* first_child_of_type() const + { + return const_cast(this)->template first_child_of_type(); + } + + template + U const* last_child_of_type() const + { + return const_cast(this)->template last_child_of_type(); + } + + template + U* first_child_of_type() + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (is(*child)) + return &verify_cast(*child); + } + return nullptr; + } + + template + U* last_child_of_type() + { + for (auto* child = last_child(); child; child = child->previous_sibling()) { + if (is(*child)) + return &verify_cast(*child); + } + return nullptr; + } + + template + bool has_child_of_type() const + { + return first_child_of_type() != nullptr; + } + + template + U const* first_ancestor_of_type() const + { + return const_cast(this)->template first_ancestor_of_type(); + } + + template + U* first_ancestor_of_type() + { + for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + if (is(*ancestor)) + return &verify_cast(*ancestor); + } + return nullptr; + } + + bool is_parent_of(Node const& other) const + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (&other == child) + return true; + } + return false; + } + protected: + Node(JS::Realm&, Document&, NodeType); Node(Document&, NodeType); - Document* m_document { nullptr }; + virtual void visit_edges(Cell::Visitor&) override; + + JS::GCPtr m_document; mutable WeakPtr m_layout_node; NodeType m_type { NodeType::INVALID }; bool m_needs_style_update { false }; @@ -254,6 +640,18 @@ protected: private: void queue_tree_mutation_record(NonnullRefPtr added_nodes, NonnullRefPtr removed_nodes, Node* previous_sibling, Node* next_sibling); + + void insert_before_impl(JS::NonnullGCPtr, JS::GCPtr child); + void append_child_impl(JS::NonnullGCPtr); + void remove_child_impl(JS::NonnullGCPtr); + + JS::GCPtr m_parent; + JS::GCPtr m_first_child; + JS::GCPtr m_last_child; + JS::GCPtr m_next_sibling; + JS::GCPtr m_previous_sibling; }; } + +WRAPPER_HACK(Node, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/NodeFilter.cpp b/Userland/Libraries/LibWeb/DOM/NodeFilter.cpp index d1dbec9136940c9ca016d955866d266061700659..5f02bb1cb5f41b642b6f7a2003875f66667991b4 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeFilter.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeFilter.cpp @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include +#include namespace Web::DOM { diff --git a/Userland/Libraries/LibWeb/DOM/NodeFilter.h b/Userland/Libraries/LibWeb/DOM/NodeFilter.h index 89b7aa1354015b2dc407488f7ddab2e53ad08110..5ecf02865042b87b76f8a279c16c3bb0dec537f8 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeFilter.h +++ b/Userland/Libraries/LibWeb/DOM/NodeFilter.h @@ -12,16 +12,13 @@ namespace Web::DOM { class NodeFilter final : public Bindings::PlatformObject { - JS_OBJECT(NodeFilter, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(NodeFilter, Bindings::PlatformObject); public: static JS::NonnullGCPtr create(JS::Realm&, Bindings::CallbackType&); - NodeFilter(JS::Realm&, Bindings::CallbackType&); virtual ~NodeFilter() = default; - NodeFilter& impl() { return *this; } - Bindings::CallbackType& callback() { return m_callback; } enum Result { @@ -31,14 +28,13 @@ public: }; private: + NodeFilter(JS::Realm&, Bindings::CallbackType&); + virtual void visit_edges(Cell::Visitor&) override; Bindings::CallbackType& m_callback; }; -inline JS::Object* wrap(JS::Realm&, Web::DOM::NodeFilter& filter) -{ - return &filter.callback().callback; } -} +WRAPPER_HACK(NodeFilter, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp b/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp index a0421dc179b7f7620d79729fb7d55b24f8fa64fd..f57e7777dbc15bade5eb409238dd548c198de2ff 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp @@ -7,15 +7,14 @@ #include #include #include -#include -#include +#include #include #include namespace Web::DOM { NodeIterator::NodeIterator(Node& root) - : PlatformObject(root.document().preferred_window_object().ensure_web_prototype("NodeIterator")) + : PlatformObject(root.document().window().ensure_web_prototype("NodeIterator")) , m_root(root) , m_reference({ root }) { @@ -31,6 +30,11 @@ void NodeIterator::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_filter.ptr()); + visitor.visit(m_root.ptr()); + visitor.visit(m_reference.node.ptr()); + + if (m_traversal_pointer.has_value()) + visitor.visit(m_traversal_pointer->node.ptr()); } // https://dom.spec.whatwg.org/#dom-document-createnodeiterator @@ -39,7 +43,7 @@ JS::NonnullGCPtr NodeIterator::create(Node& root, unsigned what_to // 1. Let iterator be a new NodeIterator object. // 2. Set iterator’s root and iterator’s reference to root. // 3. Set iterator’s pointer before reference to true. - auto& window_object = root.document().preferred_window_object(); + auto& window_object = root.document().window(); auto* iterator = window_object.heap().allocate(window_object.realm(), root); // 4. Set iterator’s whatToShow to whatToShow. @@ -60,13 +64,13 @@ void NodeIterator::detach() } // https://dom.spec.whatwg.org/#concept-nodeiterator-traverse -JS::ThrowCompletionOr> NodeIterator::traverse(Direction direction) +JS::ThrowCompletionOr> NodeIterator::traverse(Direction direction) { // 1. Let node be iterator’s reference. // 2. Let beforeNode be iterator’s pointer before reference. m_traversal_pointer = m_reference; - RefPtr candidate; + JS::GCPtr candidate; // 3. While true: while (true) { @@ -79,7 +83,7 @@ JS::ThrowCompletionOr> NodeIterator::traverse(Direction direction) auto* next_node = m_traversal_pointer->node->next_in_pre_order(m_root.ptr()); if (!next_node) return nullptr; - m_traversal_pointer->node = *next_node; + m_traversal_pointer->node = next_node; } else { // If beforeNode is true, then set it to false. m_traversal_pointer->is_before_node = false; @@ -89,12 +93,12 @@ JS::ThrowCompletionOr> NodeIterator::traverse(Direction direction) // If beforeNode is true, then set node to the first node preceding node in iterator’s iterator collection. // If there is no such node, then return null. if (m_traversal_pointer->is_before_node) { - if (m_traversal_pointer->node == m_root.ptr()) + if (m_traversal_pointer->node.ptr() == m_root.ptr()) return nullptr; auto* previous_node = m_traversal_pointer->node->previous_in_pre_order(); if (!previous_node) return nullptr; - m_traversal_pointer->node = *previous_node; + m_traversal_pointer->node = previous_node; } else { // If beforeNode is false, then set it to true. m_traversal_pointer->is_before_node = true; @@ -161,13 +165,13 @@ JS::ThrowCompletionOr NodeIterator::filter(Node& node) } // https://dom.spec.whatwg.org/#dom-nodeiterator-nextnode -JS::ThrowCompletionOr> NodeIterator::next_node() +JS::ThrowCompletionOr> NodeIterator::next_node() { return traverse(Direction::Next); } // https://dom.spec.whatwg.org/#dom-nodeiterator-previousnode -JS::ThrowCompletionOr> NodeIterator::previous_node() +JS::ThrowCompletionOr> NodeIterator::previous_node() { return traverse(Direction::Previous); } @@ -189,7 +193,7 @@ void NodeIterator::run_pre_removing_steps_with_node_pointer(Node& to_be_removed_ while (node && node->is_descendant_of(to_be_removed_node)) node = node->next_in_pre_order(root()); if (node) - pointer.node = *node; + pointer.node = node; return; } if (auto* node = to_be_removed_node.previous_in_pre_order()) { @@ -213,7 +217,7 @@ void NodeIterator::run_pre_removing_steps_with_node_pointer(Node& to_be_removed_ node = node->previous_in_pre_order(); } if (node) - pointer.node = *node; + pointer.node = node; return; } auto* node = to_be_removed_node.next_in_pre_order(root()); @@ -222,7 +226,7 @@ void NodeIterator::run_pre_removing_steps_with_node_pointer(Node& to_be_removed_ node = node->previous_in_pre_order(); } if (node) - pointer.node = *node; + pointer.node = node; } // https://dom.spec.whatwg.org/#nodeiterator-pre-removing-steps diff --git a/Userland/Libraries/LibWeb/DOM/NodeIterator.h b/Userland/Libraries/LibWeb/DOM/NodeIterator.h index a6296306941710015797473053dcfb08e32956ba..e3ce0c308ec4874da1856016047752677d66189e 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeIterator.h +++ b/Userland/Libraries/LibWeb/DOM/NodeIterator.h @@ -13,31 +13,30 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#nodeiterator class NodeIterator final : public Bindings::PlatformObject { - JS_OBJECT(NodeIterator, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(NodeIterator, Bindings::PlatformObject); public: static JS::NonnullGCPtr create(Node& root, unsigned what_to_show, JS::GCPtr); - NodeIterator(Node& root); virtual ~NodeIterator() override; - NodeIterator& impl() { return *this; } - - NonnullRefPtr root() { return m_root; } - NonnullRefPtr reference_node() { return m_reference.node; } + JS::NonnullGCPtr root() { return m_root; } + JS::NonnullGCPtr reference_node() { return m_reference.node; } bool pointer_before_reference_node() const { return m_reference.is_before_node; } unsigned what_to_show() const { return m_what_to_show; } NodeFilter* filter() { return m_filter.ptr(); } - JS::ThrowCompletionOr> next_node(); - JS::ThrowCompletionOr> previous_node(); + JS::ThrowCompletionOr> next_node(); + JS::ThrowCompletionOr> previous_node(); void detach(); void run_pre_removing_steps(Node&); private: + explicit NodeIterator(Node& root); + virtual void visit_edges(Cell::Visitor&) override; enum class Direction { @@ -45,15 +44,15 @@ private: Previous, }; - JS::ThrowCompletionOr> traverse(Direction); + JS::ThrowCompletionOr> traverse(Direction); JS::ThrowCompletionOr filter(Node&); // https://dom.spec.whatwg.org/#concept-traversal-root - NonnullRefPtr m_root; + JS::NonnullGCPtr m_root; struct NodePointer { - NonnullRefPtr node; + JS::NonnullGCPtr node; // https://dom.spec.whatwg.org/#nodeiterator-pointer-before-reference bool is_before_node { true }; @@ -72,7 +71,7 @@ private: unsigned m_what_to_show { 0 }; // https://dom.spec.whatwg.org/#concept-traversal-filter - JS::GCPtr m_filter; + JS::GCPtr m_filter; // https://dom.spec.whatwg.org/#concept-traversal-active bool m_active { false }; @@ -80,7 +79,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::DOM::NodeIterator& object) { return &object; } -using NodeIteratorWrapper = Web::DOM::NodeIterator; -} +WRAPPER_HACK(NodeIterator, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/NodeOperations.cpp b/Userland/Libraries/LibWeb/DOM/NodeOperations.cpp index d377991ad1ad47be8505d6612f1d0e96c5b20db9..0f368439437bb014a4d2feb48741c4776134a613 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeOperations.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeOperations.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -13,7 +14,7 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#converting-nodes-into-a-node -ExceptionOr> convert_nodes_to_single_node(Vector, String>> const& nodes, DOM::Document& document) +ExceptionOr> convert_nodes_to_single_node(Vector, String>> const& nodes, DOM::Document& document) { // 1. Let node be null. // 2. Replace each string in nodes with a new Text node whose data is the string and node document is document. @@ -21,18 +22,18 @@ ExceptionOr> convert_nodes_to_single_node(Vector, String> const& node) -> NonnullRefPtr { - if (node.has>()) - return node.get>(); + auto potentially_convert_string_to_text_node = [&document](Variant, String> const& node) -> JS::NonnullGCPtr { + if (node.has>()) + return *node.get>(); - return adopt_ref(*new Text(document, node.get())); + return *document.heap().allocate(document.realm(), document, node.get()); }; if (nodes.size() == 1) return potentially_convert_string_to_text_node(nodes.first()); - // This is NNRP instead of NNRP to be compatible with the return type. - NonnullRefPtr document_fragment = adopt_ref(*new DocumentFragment(document)); + // This is NNGCP instead of NNGCP to be compatible with the return type. + JS::NonnullGCPtr document_fragment = *document.heap().allocate(document.realm(), document); for (auto& unconverted_node : nodes) { auto node = potentially_convert_string_to_text_node(unconverted_node); (void)TRY(document_fragment->append_child(node)); diff --git a/Userland/Libraries/LibWeb/DOM/NodeOperations.h b/Userland/Libraries/LibWeb/DOM/NodeOperations.h index 251a320104f6c1abd4f042a9e0c0725f9e97c2de..fe9817e58e8a71fcef3d3f99d90eca277c0d7cea 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeOperations.h +++ b/Userland/Libraries/LibWeb/DOM/NodeOperations.h @@ -6,11 +6,12 @@ #pragma once -#include +#include +#include #include namespace Web::DOM { -ExceptionOr> convert_nodes_to_single_node(Vector, String>> const& nodes, DOM::Document& document); +ExceptionOr> convert_nodes_to_single_node(Vector, String>> const& nodes, DOM::Document& document); } diff --git a/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h b/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h index 59c1ef65cbeb2191acfadab6bc8df440174b36a8..20dccb37c3fc7211ca7ef634168dc896f486cb55 100644 --- a/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h +++ b/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h @@ -16,9 +16,9 @@ namespace Web::DOM { template class NonElementParentNode { public: - RefPtr get_element_by_id(FlyString const& id) const + JS::GCPtr get_element_by_id(FlyString const& id) const { - RefPtr found_element; + JS::GCPtr found_element; static_cast(this)->template for_each_in_inclusive_subtree_of_type([&](auto& element) { if (element.attribute(HTML::AttributeNames::id) == id) { found_element = &element; @@ -28,7 +28,7 @@ public: }); return found_element; } - RefPtr get_element_by_id(FlyString const& id) + JS::GCPtr get_element_by_id(FlyString const& id) { return const_cast(this)->get_element_by_id(id); } diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp index 16f65efa4197a22a7e6392b4331f6e5f55a07fca..de7fdd699a8a998e2d130eaba79fcab4c124b95a 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp @@ -15,7 +15,7 @@ namespace Web::DOM { -ExceptionOr> ParentNode::query_selector(StringView selector_text) +ExceptionOr> ParentNode::query_selector(StringView selector_text) { auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(*this), selector_text); if (!maybe_selectors.has_value()) @@ -23,12 +23,12 @@ ExceptionOr> ParentNode::query_selector(StringView selector_text auto selectors = maybe_selectors.value(); - RefPtr result; + JS::GCPtr result; // FIXME: This should be shadow-including. https://drafts.csswg.org/selectors-4/#match-a-selector-against-a-tree for_each_in_subtree_of_type([&](auto& element) { for (auto& selector : selectors) { if (SelectorEngine::matches(selector, element)) { - result = element; + result = &element; return IterationDecision::Break; } } @@ -46,12 +46,12 @@ ExceptionOr> ParentNode::query_selector_all(StringView s auto selectors = maybe_selectors.value(); - NonnullRefPtrVector elements; + Vector> elements; // FIXME: This should be shadow-including. https://drafts.csswg.org/selectors-4/#match-a-selector-against-a-tree for_each_in_subtree_of_type([&](auto& element) { for (auto& selector : selectors) { if (SelectorEngine::matches(selector, element)) { - elements.append(element); + elements.append(&element); } } return IterationDecision::Continue; @@ -60,12 +60,12 @@ ExceptionOr> ParentNode::query_selector_all(StringView s return StaticNodeList::create(move(elements)); } -RefPtr ParentNode::first_element_child() +JS::GCPtr ParentNode::first_element_child() { return first_child_of_type(); } -RefPtr ParentNode::last_element_child() +JS::GCPtr ParentNode::last_element_child() { return last_child_of_type(); } @@ -157,7 +157,7 @@ NonnullRefPtr ParentNode::get_elements_by_tag_name_ns(FlyString } // https://dom.spec.whatwg.org/#dom-parentnode-prepend -ExceptionOr ParentNode::prepend(Vector, String>> const& nodes) +ExceptionOr ParentNode::prepend(Vector, String>> const& nodes) { // 1. Let node be the result of converting nodes into a node given nodes and this’s node document. auto node = TRY(convert_nodes_to_single_node(nodes, document())); @@ -168,7 +168,7 @@ ExceptionOr ParentNode::prepend(Vector, String return {}; } -ExceptionOr ParentNode::append(Vector, String>> const& nodes) +ExceptionOr ParentNode::append(Vector, String>> const& nodes) { // 1. Let node be the result of converting nodes into a node given nodes and this’s node document. auto node = TRY(convert_nodes_to_single_node(nodes, document())); @@ -179,7 +179,7 @@ ExceptionOr ParentNode::append(Vector, String> return {}; } -ExceptionOr ParentNode::replace_children(Vector, String>> const& nodes) +ExceptionOr ParentNode::replace_children(Vector, String>> const& nodes) { // 1. Let node be the result of converting nodes into a node given nodes and this’s node document. auto node = TRY(convert_nodes_to_single_node(nodes, document())); @@ -188,7 +188,7 @@ ExceptionOr ParentNode::replace_children(Vector #include namespace Web::DOM { class ParentNode : public Node { + WEB_PLATFORM_OBJECT(ParentNode, Node); + public: template void for_each_child(F) const; template void for_each_child(F); - RefPtr first_element_child(); - RefPtr last_element_child(); + JS::GCPtr first_element_child(); + JS::GCPtr last_element_child(); u32 child_element_count() const; - ExceptionOr> query_selector(StringView); + ExceptionOr> query_selector(StringView); ExceptionOr> query_selector_all(StringView); NonnullRefPtr children(); @@ -30,11 +31,16 @@ public: NonnullRefPtr get_elements_by_tag_name(FlyString const&); NonnullRefPtr get_elements_by_tag_name_ns(FlyString const&, FlyString const&); - ExceptionOr prepend(Vector, String>> const& nodes); - ExceptionOr append(Vector, String>> const& nodes); - ExceptionOr replace_children(Vector, String>> const& nodes); + ExceptionOr prepend(Vector, String>> const& nodes); + ExceptionOr append(Vector, String>> const& nodes); + ExceptionOr replace_children(Vector, String>> const& nodes); protected: + ParentNode(JS::Realm& realm, Document& document, NodeType type) + : Node(realm, document, type) + { + } + ParentNode(Document& document, NodeType type) : Node(document, type) { @@ -59,3 +65,5 @@ inline void ParentNode::for_each_child(Callback callback) } } + +WRAPPER_HACK(ParentNode, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/Position.cpp b/Userland/Libraries/LibWeb/DOM/Position.cpp index 7790e8e1e2a250251814ee4ee40965ac12f992b7..8f256c5b18ea959b0e470f56f044ac98defd9eb9 100644 --- a/Userland/Libraries/LibWeb/DOM/Position.cpp +++ b/Userland/Libraries/LibWeb/DOM/Position.cpp @@ -13,7 +13,7 @@ namespace Web::DOM { Position::Position(Node& node, unsigned offset) - : m_node(node) + : m_node(JS::make_handle(node)) , m_offset(offset) { } diff --git a/Userland/Libraries/LibWeb/DOM/Position.h b/Userland/Libraries/LibWeb/DOM/Position.h index 45ef6768a76ed15829c1f105d7f63996e6310ee3..fd9847b8c42ec2a28cf4a771063f9eb412ffe24d 100644 --- a/Userland/Libraries/LibWeb/DOM/Position.h +++ b/Userland/Libraries/LibWeb/DOM/Position.h @@ -18,10 +18,10 @@ public: Position() = default; Position(Node&, unsigned offset); - bool is_valid() const { return m_node; } + bool is_valid() const { return m_node.ptr(); } - Node* node() { return m_node; } - Node const* node() const { return m_node; } + Node* node() { return m_node.cell(); } + Node const* node() const { return m_node.cell(); } unsigned offset() const { return m_offset; } bool offset_is_at_end_of_node() const; @@ -31,7 +31,7 @@ public: bool operator==(Position const& other) const { - return m_node == other.m_node && m_offset == other.m_offset; + return m_node.ptr() == other.m_node.ptr() && m_offset == other.m_offset; } bool operator!=(Position const& other) const @@ -42,7 +42,7 @@ public: String to_string() const; private: - RefPtr m_node; + JS::Handle m_node; unsigned m_offset { 0 }; }; diff --git a/Userland/Libraries/LibWeb/DOM/ProcessingInstruction.h b/Userland/Libraries/LibWeb/DOM/ProcessingInstruction.h index 5bc6706dafbd066c895b5f0b826b813e895b661d..a2196f9e31cd2e941124cb842fdfbcbfe125d472 100644 --- a/Userland/Libraries/LibWeb/DOM/ProcessingInstruction.h +++ b/Userland/Libraries/LibWeb/DOM/ProcessingInstruction.h @@ -12,10 +12,9 @@ namespace Web::DOM { class ProcessingInstruction final : public CharacterData { -public: - using WrapperType = Bindings::ProcessingInstructionWrapper; + WEB_PLATFORM_OBJECT(ProcessingInstruction, CharacterData); - ProcessingInstruction(Document&, String const& data, String const& target); +public: virtual ~ProcessingInstruction() override = default; virtual FlyString node_name() const override { return m_target; } @@ -23,6 +22,8 @@ public: String const& target() const { return m_target; } private: + ProcessingInstruction(Document&, String const& data, String const& target); + String m_target; }; @@ -30,3 +31,5 @@ template<> inline bool Node::fast_is() const { return node_type() == (u16)NodeType::PROCESSING_INSTRUCTION_NODE; } } + +WRAPPER_HACK(ProcessingInstruction, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/Range.cpp b/Userland/Libraries/LibWeb/DOM/Range.cpp index eb8d1bceb8bde13642f8b43cd881fb74fa23860a..d362577c3652dd26ebce1e728a2b57b13671811a 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.cpp +++ b/Userland/Libraries/LibWeb/DOM/Range.cpp @@ -32,17 +32,17 @@ JS::NonnullGCPtr Range::create(HTML::Window& window) JS::NonnullGCPtr Range::create(Document& document) { - auto& window_object = document.preferred_window_object(); + auto& window_object = document.window(); return *window_object.heap().allocate(window_object.realm(), document); } JS::NonnullGCPtr Range::create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset) { - auto& window_object = start_container.document().preferred_window_object(); + auto& window_object = start_container.document().window(); return *window_object.heap().allocate(window_object.realm(), start_container, start_offset, end_container, end_offset); } -JS::NonnullGCPtr Range::create_with_global_object(Bindings::WindowObject& window) +JS::NonnullGCPtr Range::create_with_global_object(HTML::Window& window) { return Range::create(window.impl()); } @@ -50,13 +50,13 @@ JS::NonnullGCPtr Range::create_with_global_object(Bindings::WindowObject& Range::Range(Document& document) : Range(document, 0, document, 0) { - set_prototype(&document.preferred_window_object().ensure_web_prototype("Range")); + set_prototype(&document.window().ensure_web_prototype("Range")); } Range::Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset) : AbstractRange(start_container, start_offset, end_container, end_offset) { - set_prototype(&start_container.document().preferred_window_object().ensure_web_prototype("Range")); + set_prototype(&start_container.document().window().ensure_web_prototype("Range")); live_ranges().set(this); } @@ -114,13 +114,13 @@ static RelativeBoundaryPointPosition position_of_boundary_point_relative_to_othe // 4. If nodeA is an ancestor of nodeB: if (node_a.is_ancestor_of(node_b)) { // 1. Let child be nodeB. - NonnullRefPtr child = node_b; + JS::NonnullGCPtr child = node_b; // 2. While child is not a child of nodeA, set child to its parent. while (!node_a.is_parent_of(child)) { auto* parent = child->parent(); VERIFY(parent); - child = *parent; + child = parent; } // 3. If child’s index is less than offsetA, then return after. @@ -134,13 +134,6 @@ static RelativeBoundaryPointPosition position_of_boundary_point_relative_to_othe ExceptionOr Range::set_start_or_end(Node& node, u32 offset, StartOrEnd start_or_end) { - // FIXME: If the incoming node is part of a document that's in the process of being destroyed, - // we just ignore this. This prevents us from trying to re-ref a document during its - // destruction process. This is a hack and should be replaced with some smarter form - // of lifetime management. - if (node.document().in_removed_last_ref()) - return {}; - // To set the start or end of a range to a boundary point (node, offset), run these steps: // 1. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException. @@ -158,12 +151,12 @@ ExceptionOr Range::set_start_or_end(Node& node, u32 offset, StartOrEnd sta // 1. If range’s root is not equal to node’s root, or if bp is after the range’s end, set range’s end to bp. if (&root() != &node.root() || position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_end_container, m_end_offset) == RelativeBoundaryPointPosition::After) { - m_end_container = node; + m_end_container = &node; m_end_offset = offset; } // 2. Set range’s start to bp. - m_start_container = node; + m_start_container = &node; m_start_offset = offset; } else { // -> If these steps were invoked as "set the end" @@ -171,12 +164,12 @@ ExceptionOr Range::set_start_or_end(Node& node, u32 offset, StartOrEnd sta // 1. If range’s root is not equal to node’s root, or if bp is before the range’s start, set range’s start to bp. if (&root() != &node.root() || position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset) == RelativeBoundaryPointPosition::Before) { - m_start_container = node; + m_start_container = &node; m_start_offset = offset; } // 2. Set range’s end to bp. - m_end_container = node; + m_end_container = &node; m_end_offset = offset; } @@ -268,10 +261,10 @@ ExceptionOr Range::compare_boundary_points(u16 how, Range const& source_ran if (&root() != &source_range.root()) return WrongDocumentError::create("This range is not in the same tree as the source range."); - RefPtr this_point_node; + JS::GCPtr this_point_node; u32 this_point_offset = 0; - RefPtr other_point_node; + JS::GCPtr other_point_node; u32 other_point_offset = 0; // 3. If how is: @@ -353,11 +346,11 @@ ExceptionOr Range::select(Node& node) auto index = node.index(); // 4. Set range’s start to boundary point (parent, index). - m_start_container = *parent; + m_start_container = parent; m_start_offset = index; // 5. Set range’s end to boundary point (parent, index plus 1). - m_end_container = *parent; + m_end_container = parent; m_end_offset = index + 1; return {}; @@ -395,11 +388,11 @@ ExceptionOr Range::select_node_contents(Node const& node) auto length = node.length(); // 3. Set start to the boundary point (node, 0). - m_start_container = node; + m_start_container = &node; m_start_offset = 0; // 4. Set end to the boundary point (node, length). - m_end_container = node; + m_end_container = &node; m_end_offset = length; return {}; @@ -431,7 +424,7 @@ JS::NonnullGCPtr Range::normalized() const } // https://dom.spec.whatwg.org/#dom-range-commonancestorcontainer -NonnullRefPtr Range::common_ancestor_container() const +JS::NonnullGCPtr Range::common_ancestor_container() const { // 1. Let container be start node. auto container = m_start_container; @@ -439,7 +432,7 @@ NonnullRefPtr Range::common_ancestor_container() const // 2. While container is not an inclusive ancestor of end node, let container be container’s parent. while (!container->is_inclusive_ancestor_of(m_end_container)) { VERIFY(container->parent()); - container = *container->parent(); + container = container->parent(); } // 3. Return container. @@ -557,26 +550,26 @@ String Range::to_string() const } // https://dom.spec.whatwg.org/#dom-range-extractcontents -ExceptionOr> Range::extract_contents() +ExceptionOr> Range::extract_contents() { return extract(); } // https://dom.spec.whatwg.org/#concept-range-extract -ExceptionOr> Range::extract() +ExceptionOr> Range::extract() { // 1. Let fragment be a new DocumentFragment node whose node document is range’s start node’s node document. - auto fragment = adopt_ref(*new DocumentFragment(const_cast(start_container()->document()))); + auto* fragment = heap().allocate(realm(), const_cast(start_container()->document())); // 2. If range is collapsed, then return fragment. if (collapsed()) - return fragment; + return JS::NonnullGCPtr(*fragment); // 3. Let original start node, original start offset, original end node, and original end offset // be range’s start node, start offset, end node, and end offset, respectively. - NonnullRefPtr original_start_node = m_start_container; + JS::NonnullGCPtr original_start_node = m_start_container; auto original_start_offset = m_start_offset; - NonnullRefPtr original_end_node = m_end_container; + JS::NonnullGCPtr original_end_node = m_end_container; auto original_end_offset = m_end_offset; // 4. If original start node is original end node and it is a CharacterData node, then: @@ -596,18 +589,18 @@ ExceptionOr> Range::extract() static_cast(*original_start_node).replace_data(original_start_offset, original_end_offset - original_start_offset, ""); // 5. Return fragment. - return fragment; + return JS::NonnullGCPtr(*fragment); } // 5. Let common ancestor be original start node. - NonnullRefPtr common_ancestor = original_start_node; + JS::NonnullGCPtr common_ancestor = original_start_node; // 6. While common ancestor is not an inclusive ancestor of original end node, set common ancestor to its own parent. while (!common_ancestor->is_inclusive_ancestor_of(original_end_node)) - common_ancestor = *common_ancestor->parent_node(); + common_ancestor = common_ancestor->parent_node(); // 7. Let first partially contained child be null. - RefPtr first_partially_contained_child; + JS::GCPtr first_partially_contained_child; // 8. If original start node is not an inclusive ancestor of original end node, // set first partially contained child to the first child of common ancestor that is partially contained in range. @@ -621,7 +614,7 @@ ExceptionOr> Range::extract() } // 9. Let last partially contained child be null. - RefPtr last_partially_contained_child; + JS::GCPtr last_partially_contained_child; // 10. If original end node is not an inclusive ancestor of original start node, // set last partially contained child to the last child of common ancestor that is partially contained in range. @@ -635,7 +628,7 @@ ExceptionOr> Range::extract() } // 11. Let contained children be a list of all children of common ancestor that are contained in range, in tree order. - Vector> contained_children; + Vector> contained_children; for (Node const* node = common_ancestor->first_child(); node; node = node->next_sibling()) { if (contains_node(*node)) contained_children.append(*node); @@ -647,7 +640,7 @@ ExceptionOr> Range::extract() return DOM::HierarchyRequestError::create("Contained child is a DocumentType"); } - RefPtr new_node; + JS::GCPtr new_node; size_t new_offset = 0; // 13. If original start node is an inclusive ancestor of original end node, set new node to original start node and new offset to original start offset. @@ -658,7 +651,7 @@ ExceptionOr> Range::extract() // 14. Otherwise: else { // 1. Let reference node equal original start node. - RefPtr reference_node = original_start_node; + JS::GCPtr reference_node = original_start_node; // 2. While reference node’s parent is not null and is not an inclusive ancestor of original end node, set reference node to its parent. while (reference_node->parent_node() && !reference_node->parent_node()->is_inclusive_ancestor_of(original_end_node)) @@ -746,7 +739,7 @@ ExceptionOr> Range::extract() set_end(*new_node, new_offset); // 21. Return fragment. - return fragment; + return JS::NonnullGCPtr(*fragment); } // https://dom.spec.whatwg.org/#contained @@ -779,23 +772,23 @@ bool Range::partially_contains_node(Node const& node) const } // https://dom.spec.whatwg.org/#dom-range-insertnode -ExceptionOr Range::insert_node(NonnullRefPtr node) +ExceptionOr Range::insert_node(JS::NonnullGCPtr node) { return insert(node); } // https://dom.spec.whatwg.org/#concept-range-insert -ExceptionOr Range::insert(NonnullRefPtr node) +ExceptionOr Range::insert(JS::NonnullGCPtr node) { // 1. If range’s start node is a ProcessingInstruction or Comment node, is a Text node whose parent is null, or is node, then throw a "HierarchyRequestError" DOMException. if ((is(*m_start_container) || is(*m_start_container)) || (is(*m_start_container) && !m_start_container->parent_node()) - || m_start_container == node.ptr()) { + || m_start_container.ptr() == node.ptr()) { return DOM::HierarchyRequestError::create("Range has inappropriate start node for insertion"); } // 2. Let referenceNode be null. - RefPtr reference_node; + JS::GCPtr reference_node; // 3. If range’s start node is a Text node, set referenceNode to that Text node. if (is(*m_start_container)) { @@ -807,7 +800,7 @@ ExceptionOr Range::insert(NonnullRefPtr node) } // 5. Let parent be range’s start node if referenceNode is null, and referenceNode’s parent otherwise. - RefPtr parent; + JS::GCPtr parent; if (!reference_node) parent = m_start_container; else @@ -852,7 +845,7 @@ ExceptionOr Range::insert(NonnullRefPtr node) } // https://dom.spec.whatwg.org/#dom-range-surroundcontents -ExceptionOr Range::surround_contents(NonnullRefPtr new_parent) +ExceptionOr Range::surround_contents(JS::NonnullGCPtr new_parent) { // 1. If a non-Text node is partially contained in this, then throw an "InvalidStateError" DOMException. Node* start_non_text_node = start_container(); @@ -886,26 +879,26 @@ ExceptionOr Range::surround_contents(NonnullRefPtr new_parent) } // https://dom.spec.whatwg.org/#dom-range-clonecontents -ExceptionOr> Range::clone_contents() +ExceptionOr> Range::clone_contents() { return clone_the_contents(); } // https://dom.spec.whatwg.org/#concept-range-clone -ExceptionOr> Range::clone_the_contents() +ExceptionOr> Range::clone_the_contents() { // 1. Let fragment be a new DocumentFragment node whose node document is range’s start node’s node document. - auto fragment = adopt_ref(*new DocumentFragment(const_cast(start_container()->document()))); + auto* fragment = heap().allocate(realm(), const_cast(start_container()->document())); // 2. If range is collapsed, then return fragment. if (collapsed()) - return fragment; + return JS::NonnullGCPtr(*fragment); // 3. Let original start node, original start offset, original end node, and original end offset // be range’s start node, start offset, end node, and end offset, respectively. - NonnullRefPtr original_start_node = m_start_container; + JS::NonnullGCPtr original_start_node = m_start_container; auto original_start_offset = m_start_offset; - NonnullRefPtr original_end_node = m_end_container; + JS::NonnullGCPtr original_end_node = m_end_container; auto original_end_offset = m_end_offset; // 4. If original start node is original end node and it is a CharacterData node, then: @@ -922,18 +915,18 @@ ExceptionOr> Range::clone_the_contents() fragment->append_child(clone); // 4. Return fragment. - return fragment; + return JS::NonnullGCPtr(*fragment); } // 5. Let common ancestor be original start node. - NonnullRefPtr common_ancestor = original_start_node; + JS::NonnullGCPtr common_ancestor = original_start_node; // 6. While common ancestor is not an inclusive ancestor of original end node, set common ancestor to its own parent. while (!common_ancestor->is_inclusive_ancestor_of(original_end_node)) - common_ancestor = *common_ancestor->parent_node(); + common_ancestor = common_ancestor->parent_node(); // 7. Let first partially contained child be null. - RefPtr first_partially_contained_child; + JS::GCPtr first_partially_contained_child; // 8. If original start node is not an inclusive ancestor of original end node, // set first partially contained child to the first child of common ancestor that is partially contained in range. @@ -947,7 +940,7 @@ ExceptionOr> Range::clone_the_contents() } // 9. Let last partially contained child be null. - RefPtr last_partially_contained_child; + JS::GCPtr last_partially_contained_child; // 10. If original end node is not an inclusive ancestor of original start node, // set last partially contained child to the last child of common ancestor that is partially contained in range. @@ -961,7 +954,7 @@ ExceptionOr> Range::clone_the_contents() } // 11. Let contained children be a list of all children of common ancestor that are contained in range, in tree order. - Vector> contained_children; + Vector> contained_children; for (Node const* node = common_ancestor->first_child(); node; node = node->next_sibling()) { if (contains_node(*node)) contained_children.append(*node); @@ -1044,7 +1037,7 @@ ExceptionOr> Range::clone_the_contents() } // 18. Return fragment. - return fragment; + return JS::NonnullGCPtr(*fragment); } // https://dom.spec.whatwg.org/#dom-range-deletecontents @@ -1055,9 +1048,9 @@ ExceptionOr Range::delete_contents() return {}; // 2. Let original start node, original start offset, original end node, and original end offset be this’s start node, start offset, end node, and end offset, respectively. - NonnullRefPtr original_start_node = m_start_container; + JS::NonnullGCPtr original_start_node = m_start_container; auto original_start_offset = m_start_offset; - NonnullRefPtr original_end_node = m_end_container; + JS::NonnullGCPtr original_end_node = m_end_container; auto original_end_offset = m_end_offset; // 3. If original start node is original end node and it is a CharacterData node, then replace data with node original start node, offset original start offset, @@ -1068,13 +1061,13 @@ ExceptionOr Range::delete_contents() } // 4. Let nodes to remove be a list of all the nodes that are contained in this, in tree order, omitting any node whose parent is also contained in this. - Vector> nodes_to_remove; + JS::MarkedVector nodes_to_remove(heap()); for (Node const* node = start_container(); node != end_container()->next_in_pre_order(); node = node->next_in_pre_order()) { if (contains_node(*node) && (!node->parent_node() || !contains_node(*node->parent_node()))) - nodes_to_remove.append(*node); + nodes_to_remove.append(const_cast(node)); } - RefPtr new_node; + JS::GCPtr new_node; size_t new_offset = 0; // 5. If original start node is an inclusive ancestor of original end node, set new node to original start node and new offset to original start offset. @@ -1089,7 +1082,7 @@ ExceptionOr Range::delete_contents() // 2. While reference node’s parent is not null and is not an inclusive ancestor of original end node, set reference node to its parent. while (reference_node->parent_node() && !reference_node->parent_node()->is_inclusive_ancestor_of(original_end_node)) - reference_node = *reference_node->parent_node(); + reference_node = reference_node->parent_node(); // 3. Set new node to the parent of reference node, and new offset to one plus the index of reference node. new_node = reference_node->parent_node(); diff --git a/Userland/Libraries/LibWeb/DOM/Range.h b/Userland/Libraries/LibWeb/DOM/Range.h index a63b0e4baf44d9a78f3df5440a744bf3ebe669b7..50edff1233af080d4510004fcbbab616b89abf2b 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.h +++ b/Userland/Libraries/LibWeb/DOM/Range.h @@ -13,15 +13,13 @@ namespace Web::DOM { class Range final : public AbstractRange { - JS_OBJECT(Range, AbstractRange); + WEB_PLATFORM_OBJECT(Range, AbstractRange); public: - Range& impl() { return *this; } - static JS::NonnullGCPtr create(Document&); static JS::NonnullGCPtr create(HTML::Window&); static JS::NonnullGCPtr create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset); - static JS::NonnullGCPtr create_with_global_object(Bindings::WindowObject&); + static JS::NonnullGCPtr create_with_global_object(HTML::Window&); explicit Range(Document&); Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset); @@ -53,7 +51,7 @@ public: JS::NonnullGCPtr normalized() const; JS::NonnullGCPtr clone_range() const; - NonnullRefPtr common_ancestor_container() const; + JS::NonnullGCPtr common_ancestor_container() const; // https://dom.spec.whatwg.org/#dom-range-detach void detach() const @@ -67,11 +65,11 @@ public: ExceptionOr compare_point(Node const&, u32 offset) const; ExceptionOr delete_contents(); - ExceptionOr> extract_contents(); - ExceptionOr> clone_contents(); + ExceptionOr> extract_contents(); + ExceptionOr> clone_contents(); - ExceptionOr insert_node(NonnullRefPtr); - ExceptionOr surround_contents(NonnullRefPtr new_parent); + ExceptionOr insert_node(JS::NonnullGCPtr); + ExceptionOr surround_contents(JS::NonnullGCPtr new_parent); String to_string() const; @@ -89,9 +87,9 @@ private: ExceptionOr set_start_or_end(Node& node, u32 offset, StartOrEnd start_or_end); ExceptionOr select(Node& node); - ExceptionOr> extract(); - ExceptionOr> clone_the_contents(); - ExceptionOr insert(NonnullRefPtr); + ExceptionOr> extract(); + ExceptionOr> clone_the_contents(); + ExceptionOr insert(JS::NonnullGCPtr); bool contains_node(Node const&) const; bool partially_contains_node(Node const&) const; diff --git a/Userland/Libraries/LibWeb/DOM/ShadowRoot.h b/Userland/Libraries/LibWeb/DOM/ShadowRoot.h index ea561e7b4ce241086ee39e4ca5142b571b3d201b..b01e15627766b8a964deee2d34248e0fe431085b 100644 --- a/Userland/Libraries/LibWeb/DOM/ShadowRoot.h +++ b/Userland/Libraries/LibWeb/DOM/ShadowRoot.h @@ -11,9 +11,9 @@ namespace Web::DOM { class ShadowRoot final : public DocumentFragment { -public: - ShadowRoot(Document&, Element&); + WEB_PLATFORM_OBJECT(ShadowRoot, DocumentFragment); +public: bool closed() const { return m_closed; } bool delegates_focus() const { return m_delegates_focus; } @@ -32,6 +32,8 @@ public: ExceptionOr set_inner_html(String const&); private: + ShadowRoot(Document&, Element&); + // ^Node virtual FlyString node_name() const override { return "#shadow-root"; } virtual bool is_shadow_root() const final { return true; } @@ -52,7 +54,7 @@ inline IterationDecision Node::for_each_shadow_including_descendant(Callback cal return IterationDecision::Break; for (auto* child = first_child(); child; child = child->next_sibling()) { if (child->is_element()) { - if (RefPtr shadow_root = static_cast(child)->shadow_root()) { + if (JS::GCPtr shadow_root = static_cast(child)->shadow_root()) { if (shadow_root->for_each_shadow_including_descendant(callback) == IterationDecision::Break) return IterationDecision::Break; } @@ -64,3 +66,5 @@ inline IterationDecision Node::for_each_shadow_including_descendant(Callback cal } } + +WRAPPER_HACK(ShadowRoot, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp b/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp index ec3707cdae297493d43190ac3b37d56ad95b0fce..fdcdfca9a6ad131697f0203d620ccbe1379e1ac2 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp +++ b/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp @@ -8,7 +8,12 @@ namespace Web::DOM { -StaticNodeList::StaticNodeList(NonnullRefPtrVector&& static_nodes) +NonnullRefPtr StaticNodeList::create(Vector> static_nodes) +{ + return adopt_ref(*new StaticNodeList(move(static_nodes))); +} + +StaticNodeList::StaticNodeList(Vector> static_nodes) : m_static_nodes(move(static_nodes)) { } @@ -25,7 +30,7 @@ Node const* StaticNodeList::item(u32 index) const // The item(index) method must return the indexth node in the collection. If there is no indexth node in the collection, then the method must return null. if (index >= m_static_nodes.size()) return nullptr; - return &m_static_nodes[index]; + return m_static_nodes[index].ptr(); } // https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-indices diff --git a/Userland/Libraries/LibWeb/DOM/StaticNodeList.h b/Userland/Libraries/LibWeb/DOM/StaticNodeList.h index 0ea249f685f1f9ee290415e055f90bff91ff8b29..829aca3cce5f7b1705d62be0ad913a84155a63c7 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticNodeList.h +++ b/Userland/Libraries/LibWeb/DOM/StaticNodeList.h @@ -14,10 +14,7 @@ namespace Web::DOM { class StaticNodeList : public NodeList { public: - static NonnullRefPtr create(NonnullRefPtrVector static_nodes) - { - return adopt_ref(*new StaticNodeList(move(static_nodes))); - } + static NonnullRefPtr create(Vector> static_nodes); virtual ~StaticNodeList() override = default; @@ -27,9 +24,9 @@ public: virtual bool is_supported_property_index(u32) const override; private: - StaticNodeList(NonnullRefPtrVector&& static_nodes); + StaticNodeList(Vector> static_nodes); - NonnullRefPtrVector m_static_nodes; + Vector> m_static_nodes; }; } diff --git a/Userland/Libraries/LibWeb/DOM/StaticRange.cpp b/Userland/Libraries/LibWeb/DOM/StaticRange.cpp index 6027b4195e683fff760dc63f7e06e5ced042ff35..8d825110eea84152bb35244235499cdfa08c826b 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticRange.cpp +++ b/Userland/Libraries/LibWeb/DOM/StaticRange.cpp @@ -18,13 +18,13 @@ namespace Web::DOM { StaticRange::StaticRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset) : AbstractRange(start_container, start_offset, end_container, end_offset) { - set_prototype(&start_container.document().preferred_window_object().ensure_web_prototype("StaticRange")); + set_prototype(&start_container.document().window().ensure_web_prototype("StaticRange")); } StaticRange::~StaticRange() = default; // https://dom.spec.whatwg.org/#dom-staticrange-staticrange -ExceptionOr StaticRange::create_with_global_object(Bindings::WindowObject& window_object, StaticRangeInit& init) +ExceptionOr StaticRange::create_with_global_object(HTML::Window& window_object, StaticRangeInit& init) { // 1. If init["startContainer"] or init["endContainer"] is a DocumentType or Attr node, then throw an "InvalidNodeTypeError" DOMException. if (is(*init.start_container) || is(*init.start_container)) diff --git a/Userland/Libraries/LibWeb/DOM/StaticRange.h b/Userland/Libraries/LibWeb/DOM/StaticRange.h index 7f44aefb271b778ba3686fbb2ed1bfd6f2b10de8..c6c27b0aa6ca9223c9c235767710141912bdc036 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticRange.h +++ b/Userland/Libraries/LibWeb/DOM/StaticRange.h @@ -11,25 +11,23 @@ namespace Web::DOM { -// NOTE: We must use RP instead of NNRP here, otherwise the generated code cannot default initialize this struct. +// NOTE: We must use GCP instead of NNGCP here, otherwise the generated code cannot default initialize this struct. // They will never be null, as they are marked as required and non-null in the dictionary. struct StaticRangeInit { - RefPtr start_container; + JS::GCPtr start_container; u32 start_offset { 0 }; - RefPtr end_container; + JS::GCPtr end_container; u32 end_offset { 0 }; }; class StaticRange final : public AbstractRange { - JS_OBJECT(StaticRange, JS::Object); + WEB_PLATFORM_OBJECT(StaticRange, JS::Object); public: - static ExceptionOr create_with_global_object(Bindings::WindowObject&, StaticRangeInit& init); + static ExceptionOr create_with_global_object(HTML::Window&, StaticRangeInit& init); StaticRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset); virtual ~StaticRange() override; - - StaticRange& impl() { return *this; } }; } diff --git a/Userland/Libraries/LibWeb/DOM/Text.cpp b/Userland/Libraries/LibWeb/DOM/Text.cpp index 3225e9d6b0218990b337c7d7e8aa2761f856976c..0b8262cd26483393d02320df588107e374dc53f1 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.cpp +++ b/Userland/Libraries/LibWeb/DOM/Text.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -15,27 +16,35 @@ namespace Web::DOM { Text::Text(Document& document, String const& data) : CharacterData(document, NodeType::TEXT_NODE, data) { + set_prototype(&window().ensure_web_prototype("Text")); } Text::Text(Document& document, NodeType type, String const& data) : CharacterData(document, type, data) { + set_prototype(&window().ensure_web_prototype("Text")); +} + +void Text::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_owner_input_element.ptr()); } // https://dom.spec.whatwg.org/#dom-text-text -NonnullRefPtr Text::create_with_global_object(Bindings::WindowObject& window, String const& data) +JS::NonnullGCPtr Text::create_with_global_object(HTML::Window& window, String const& data) { - return make_ref_counted(window.impl().associated_document(), data); + return *window.heap().allocate(window.realm(), window.associated_document(), data); } void Text::set_owner_input_element(Badge, HTML::HTMLInputElement& input_element) { - m_owner_input_element = input_element; + m_owner_input_element = &input_element; } // https://dom.spec.whatwg.org/#dom-text-splittext // https://dom.spec.whatwg.org/#concept-text-split -ExceptionOr> Text::split_text(size_t offset) +ExceptionOr> Text::split_text(size_t offset) { // 1. Let length be node’s length. auto length = this->length(); @@ -51,26 +60,26 @@ ExceptionOr> Text::split_text(size_t offset) auto new_data = TRY(substring_data(offset, count)); // 5. Let new node be a new Text node, with the same node document as node. Set new node’s data to new data. - auto new_node = adopt_ref(*new Text(document(), new_data)); + auto new_node = JS::NonnullGCPtr(*heap().allocate(realm(), document(), new_data)); // 6. Let parent be node’s parent. - RefPtr parent = this->parent(); + JS::GCPtr parent = this->parent(); // 7. If parent is not null, then: if (parent) { // 1. Insert new node into parent before node’s next sibling. - parent->insert_before(new_node, next_sibling()); + parent->insert_before(*new_node, next_sibling()); // 2. For each live range whose start node is node and start offset is greater than offset, set its start node to new node and decrease its start offset by offset. for (auto& range : Range::live_ranges()) { if (range->start_container() == this && range->start_offset() > offset) - range->set_start(new_node, range->start_offset() - offset); + range->set_start(*new_node, range->start_offset() - offset); } // 3. For each live range whose end node is node and end offset is greater than offset, set its end node to new node and decrease its end offset by offset. for (auto& range : Range::live_ranges()) { if (range->end_container() == this && range->end_offset() > offset) - range->set_end(new_node, range->end_offset() - offset); + range->set_end(*new_node, range->end_offset() - offset); } // 4. For each live range whose start node is parent and start offset is equal to the index of node plus 1, increase its start offset by 1. @@ -81,7 +90,7 @@ ExceptionOr> Text::split_text(size_t offset) // 5. For each live range whose end node is parent and end offset is equal to the index of node plus 1, increase its end offset by 1. for (auto& range : Range::live_ranges()) { - if (range->end_container() == parent && range->end_offset() == index() + 1) { + if (range->end_container() == parent.ptr() && range->end_offset() == index() + 1) { range->set_end(*range->end_container(), range->end_offset() + 1); } } diff --git a/Userland/Libraries/LibWeb/DOM/Text.h b/Userland/Libraries/LibWeb/DOM/Text.h index 44762c8e559283fb89cc2ff2dca6448d241f416f..aff7c91e3e9620375e93638812f6049ea406d831 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.h +++ b/Userland/Libraries/LibWeb/DOM/Text.h @@ -13,13 +13,12 @@ namespace Web::DOM { class Text : public CharacterData { -public: - using WrapperType = Bindings::TextWrapper; + WEB_PLATFORM_OBJECT(Text, CharacterData); - explicit Text(Document&, String const&); +public: virtual ~Text() override = default; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject& window, String const& data); + static JS::NonnullGCPtr create_with_global_object(HTML::Window& window, String const& data); // ^Node virtual FlyString node_name() const override { return "#text"; } @@ -28,15 +27,18 @@ public: void set_always_editable(bool b) { m_always_editable = b; } void set_owner_input_element(Badge, HTML::HTMLInputElement&); - HTML::HTMLInputElement* owner_input_element() { return m_owner_input_element; } + HTML::HTMLInputElement* owner_input_element() { return m_owner_input_element.ptr(); } - ExceptionOr> split_text(size_t offset); + ExceptionOr> split_text(size_t offset); protected: + explicit Text(Document&, String const&); Text(Document&, NodeType, String const&); + virtual void visit_edges(Cell::Visitor&) override; + private: - WeakPtr m_owner_input_element; + JS::GCPtr m_owner_input_element; bool m_always_editable { false }; }; @@ -45,3 +47,5 @@ template<> inline bool Node::fast_is() const { return is_text(); } } + +WRAPPER_HACK(Text, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp b/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp index 88f88af449e4ea586aef9be358571ad0c7e0474b..7021233b114e94a4d917bdd39152283d7fabb99a 100644 --- a/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp +++ b/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp @@ -6,11 +6,10 @@ #include #include -#include -#include #include #include #include +#include #include #include #include @@ -18,7 +17,7 @@ namespace Web::DOM { TreeWalker::TreeWalker(Node& root) - : PlatformObject(root.document().preferred_window_object().ensure_web_prototype("TreeWalker")) + : PlatformObject(root.document().window().ensure_web_prototype("TreeWalker")) , m_root(root) , m_current(root) { @@ -30,6 +29,8 @@ void TreeWalker::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_filter.ptr()); + visitor.visit(m_root.ptr()); + visitor.visit(m_current.ptr()); } // https://dom.spec.whatwg.org/#dom-document-createtreewalker @@ -37,7 +38,7 @@ JS::NonnullGCPtr TreeWalker::create(Node& root, unsigned what_to_sho { // 1. Let walker be a new TreeWalker object. // 2. Set walker’s root and walker’s current to root. - auto& window_object = root.document().preferred_window_object(); + auto& window_object = root.document().window(); auto* walker = window_object.heap().allocate(window_object.realm(), root); // 3. Set walker’s whatToShow to whatToShow. @@ -51,7 +52,7 @@ JS::NonnullGCPtr TreeWalker::create(Node& root, unsigned what_to_sho } // https://dom.spec.whatwg.org/#dom-treewalker-currentnode -NonnullRefPtr TreeWalker::current_node() const +JS::NonnullGCPtr TreeWalker::current_node() const { return *m_current; } @@ -59,14 +60,14 @@ NonnullRefPtr TreeWalker::current_node() const // https://dom.spec.whatwg.org/#dom-treewalker-currentnode void TreeWalker::set_current_node(Node& node) { - m_current = node; + m_current = &node; } // https://dom.spec.whatwg.org/#dom-treewalker-parentnode -JS::ThrowCompletionOr> TreeWalker::parent_node() +JS::ThrowCompletionOr> TreeWalker::parent_node() { // 1. Let node be this’s current. - RefPtr node = m_current; + JS::GCPtr node = m_current; // 2. While node is non-null and is not this’s root: while (node && node != m_root) { @@ -78,7 +79,7 @@ JS::ThrowCompletionOr> TreeWalker::parent_node() if (node) { auto result = TRY(filter(*node)); if (result == NodeFilter::FILTER_ACCEPT) { - m_current = *node; + m_current = node; return node; } } @@ -88,39 +89,39 @@ JS::ThrowCompletionOr> TreeWalker::parent_node() } // https://dom.spec.whatwg.org/#dom-treewalker-firstchild -JS::ThrowCompletionOr> TreeWalker::first_child() +JS::ThrowCompletionOr> TreeWalker::first_child() { return traverse_children(ChildTraversalType::First); } // https://dom.spec.whatwg.org/#dom-treewalker-lastchild -JS::ThrowCompletionOr> TreeWalker::last_child() +JS::ThrowCompletionOr> TreeWalker::last_child() { return traverse_children(ChildTraversalType::Last); } // https://dom.spec.whatwg.org/#dom-treewalker-previoussibling -JS::ThrowCompletionOr> TreeWalker::previous_sibling() +JS::ThrowCompletionOr> TreeWalker::previous_sibling() { return traverse_siblings(SiblingTraversalType::Previous); } // https://dom.spec.whatwg.org/#dom-treewalker-nextsibling -JS::ThrowCompletionOr> TreeWalker::next_sibling() +JS::ThrowCompletionOr> TreeWalker::next_sibling() { return traverse_siblings(SiblingTraversalType::Next); } // https://dom.spec.whatwg.org/#dom-treewalker-previousnode -JS::ThrowCompletionOr> TreeWalker::previous_node() +JS::ThrowCompletionOr> TreeWalker::previous_node() { // 1. Let node be this’s current. - RefPtr node = m_current; + JS::GCPtr node = m_current; // 2. While node is not this’s root: while (node != m_root) { // 1. Let sibling be node’s previous sibling. - RefPtr sibling = node->previous_sibling(); + JS::GCPtr sibling = node->previous_sibling(); // 2. While sibling is non-null: while (sibling) { @@ -141,7 +142,7 @@ JS::ThrowCompletionOr> TreeWalker::previous_node() // 4. If result is FILTER_ACCEPT, then set this’s current to node and return node. if (result == NodeFilter::FILTER_ACCEPT) { - m_current = *node; + m_current = node; return node; } @@ -158,7 +159,7 @@ JS::ThrowCompletionOr> TreeWalker::previous_node() // 5. If the return value of filtering node within this is FILTER_ACCEPT, then set this’s current to node and return node. if (TRY(filter(*node)) == NodeFilter::FILTER_ACCEPT) { - m_current = *node; + m_current = node; return node; } } @@ -167,10 +168,10 @@ JS::ThrowCompletionOr> TreeWalker::previous_node() } // https://dom.spec.whatwg.org/#dom-treewalker-nextnode -JS::ThrowCompletionOr> TreeWalker::next_node() +JS::ThrowCompletionOr> TreeWalker::next_node() { // 1. Let node be this’s current. - RefPtr node = m_current; + JS::GCPtr node = m_current; // 2. Let result be FILTER_ACCEPT. auto result = NodeFilter::FILTER_ACCEPT; @@ -187,16 +188,16 @@ JS::ThrowCompletionOr> TreeWalker::next_node() // 3. If result is FILTER_ACCEPT, then set this’s current to node and return node. if (result == NodeFilter::FILTER_ACCEPT) { - m_current = *node; + m_current = node; return node; } } // 2. Let sibling be null. - RefPtr sibling = nullptr; + JS::GCPtr sibling = nullptr; // 3. Let temporary be node. - RefPtr temporary = node; + JS::GCPtr temporary = node; // 4. While temporary is non-null: while (temporary) { @@ -222,7 +223,7 @@ JS::ThrowCompletionOr> TreeWalker::next_node() // 6. If result is FILTER_ACCEPT, then set this’s current to node and return node. if (result == NodeFilter::FILTER_ACCEPT) { - m_current = *node; + m_current = node; return node; } } @@ -266,10 +267,10 @@ JS::ThrowCompletionOr TreeWalker::filter(Node& node) } // https://dom.spec.whatwg.org/#concept-traverse-children -JS::ThrowCompletionOr> TreeWalker::traverse_children(ChildTraversalType type) +JS::ThrowCompletionOr> TreeWalker::traverse_children(ChildTraversalType type) { // 1. Let node be walker’s current. - RefPtr node = m_current; + JS::GCPtr node = m_current; // 2. Set node to node’s first child if type is first, and node’s last child if type is last. node = type == ChildTraversalType::First ? node->first_child() : node->last_child(); @@ -281,18 +282,18 @@ JS::ThrowCompletionOr> TreeWalker::traverse_children(ChildTraversal // 2. If result is FILTER_ACCEPT, then set walker’s current to node and return node. if (result == NodeFilter::FILTER_ACCEPT) { - m_current = *node; + m_current = node; return node; } // 3. If result is FILTER_SKIP, then: if (result == NodeFilter::FILTER_SKIP) { // 1. Let child be node’s first child if type is first, and node’s last child if type is last. - RefPtr child = type == ChildTraversalType::First ? node->first_child() : node->last_child(); + JS::GCPtr child = type == ChildTraversalType::First ? node->first_child() : node->last_child(); // 2. If child is non-null, then set node to child and continue. if (child) { - node = child.release_nonnull(); + node = child; continue; } } @@ -300,23 +301,23 @@ JS::ThrowCompletionOr> TreeWalker::traverse_children(ChildTraversal // 4. While node is non-null: while (node) { // 1. Let sibling be node’s next sibling if type is first, and node’s previous sibling if type is last. - RefPtr sibling = type == ChildTraversalType::First ? node->next_sibling() : node->previous_sibling(); + JS::GCPtr sibling = type == ChildTraversalType::First ? node->next_sibling() : node->previous_sibling(); // 2. If sibling is non-null, then set node to sibling and break. if (sibling) { - node = sibling.release_nonnull(); + node = sibling; break; } // 3. Let parent be node’s parent. - RefPtr parent = node->parent(); + JS::GCPtr parent = node->parent(); // 4. If parent is null, walker’s root, or walker’s current, then return null. if (!parent || parent == m_root || parent == m_current) return nullptr; // 5. Set node to parent. - node = parent.release_nonnull(); + node = parent; } } @@ -325,10 +326,10 @@ JS::ThrowCompletionOr> TreeWalker::traverse_children(ChildTraversal } // https://dom.spec.whatwg.org/#concept-traverse-siblings -JS::ThrowCompletionOr> TreeWalker::traverse_siblings(SiblingTraversalType type) +JS::ThrowCompletionOr> TreeWalker::traverse_siblings(SiblingTraversalType type) { // 1. Let node be walker’s current. - RefPtr node = m_current; + JS::GCPtr node = m_current; // 2. If node is root, then return null. if (node == m_root) @@ -337,7 +338,7 @@ JS::ThrowCompletionOr> TreeWalker::traverse_siblings(SiblingTravers // 3. While true: while (true) { // 1. Let sibling be node’s next sibling if type is next, and node’s previous sibling if type is previous. - RefPtr sibling = type == SiblingTraversalType::Next ? node->next_sibling() : node->previous_sibling(); + JS::GCPtr sibling = type == SiblingTraversalType::Next ? node->next_sibling() : node->previous_sibling(); // 2. While sibling is non-null: while (sibling) { @@ -349,7 +350,7 @@ JS::ThrowCompletionOr> TreeWalker::traverse_siblings(SiblingTravers // 3. If result is FILTER_ACCEPT, then set walker’s current to node and return node. if (result == NodeFilter::FILTER_ACCEPT) { - m_current = *node; + m_current = node; return node; } diff --git a/Userland/Libraries/LibWeb/DOM/TreeWalker.h b/Userland/Libraries/LibWeb/DOM/TreeWalker.h index 076c6511aae21a97925f2e2d1040d5b2fb2abbb5..e43f7c21f2b09ff31acb9d006572d0d566508410 100644 --- a/Userland/Libraries/LibWeb/DOM/TreeWalker.h +++ b/Userland/Libraries/LibWeb/DOM/TreeWalker.h @@ -12,61 +12,60 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#treewalker class TreeWalker final : public Bindings::PlatformObject { - JS_OBJECT(TreeWalker, JS::Object); + WEB_PLATFORM_OBJECT(TreeWalker, JS::Object); public: static JS::NonnullGCPtr create(Node& root, unsigned what_to_show, JS::GCPtr); - explicit TreeWalker(Node& root); virtual ~TreeWalker() override; - TreeWalker& impl() { return *this; } - - NonnullRefPtr current_node() const; + JS::NonnullGCPtr current_node() const; void set_current_node(Node&); - JS::ThrowCompletionOr> parent_node(); - JS::ThrowCompletionOr> first_child(); - JS::ThrowCompletionOr> last_child(); - JS::ThrowCompletionOr> previous_sibling(); - JS::ThrowCompletionOr> next_sibling(); - JS::ThrowCompletionOr> previous_node(); - JS::ThrowCompletionOr> next_node(); + JS::ThrowCompletionOr> parent_node(); + JS::ThrowCompletionOr> first_child(); + JS::ThrowCompletionOr> last_child(); + JS::ThrowCompletionOr> previous_sibling(); + JS::ThrowCompletionOr> next_sibling(); + JS::ThrowCompletionOr> previous_node(); + JS::ThrowCompletionOr> next_node(); - NonnullRefPtr root() { return m_root; } + JS::NonnullGCPtr root() { return m_root; } NodeFilter* filter() { return m_filter.ptr(); } unsigned what_to_show() const { return m_what_to_show; } private: + explicit TreeWalker(Node& root); + virtual void visit_edges(Cell::Visitor&) override; enum class ChildTraversalType { First, Last, }; - JS::ThrowCompletionOr> traverse_children(ChildTraversalType); + JS::ThrowCompletionOr> traverse_children(ChildTraversalType); enum class SiblingTraversalType { Next, Previous, }; - JS::ThrowCompletionOr> traverse_siblings(SiblingTraversalType); + JS::ThrowCompletionOr> traverse_siblings(SiblingTraversalType); JS::ThrowCompletionOr filter(Node&); // https://dom.spec.whatwg.org/#concept-traversal-root - NonnullRefPtr m_root; + JS::NonnullGCPtr m_root; // https://dom.spec.whatwg.org/#treewalker-current - NonnullRefPtr m_current; + JS::NonnullGCPtr m_current; // https://dom.spec.whatwg.org/#concept-traversal-whattoshow unsigned m_what_to_show { 0 }; // https://dom.spec.whatwg.org/#concept-traversal-filter - JS::GCPtr m_filter; + JS::GCPtr m_filter; // https://dom.spec.whatwg.org/#concept-traversal-active bool m_active { false }; @@ -74,7 +73,4 @@ private: } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::DOM::TreeWalker& object) { return &object; } -using TreeWalkerWrapper = Web::DOM::TreeWalker; -} +WRAPPER_HACK(TreeWalker, Web::DOM) diff --git a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp index d869dc717e56eff8ba63596d10cfe770a8299ae0..a92e187aa241f99b33043a88ee9cb71d0eb00a52 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp +++ b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp @@ -12,27 +12,29 @@ namespace Web::DOMParsing { // https://w3c.github.io/DOM-Parsing/#dfn-fragment-parsing-algorithm -static DOM::ExceptionOr> parse_fragment(String const& markup, DOM::Element& context_element) +static DOM::ExceptionOr> parse_fragment(String const& markup, DOM::Element& context_element) { // FIXME: Handle XML documents. + auto& realm = context_element.realm(); + auto new_children = HTML::HTMLParser::parse_html_fragment(context_element, markup); - auto fragment = make_ref_counted(context_element.document()); + auto fragment = realm.heap().allocate(realm, context_element.document()); for (auto& child : new_children) { // I don't know if this can throw here, but let's be safe. - (void)TRY(fragment->append_child(child)); + (void)TRY(fragment->append_child(*child)); } - return fragment; + return JS::NonnullGCPtr(*fragment); } // https://w3c.github.io/DOM-Parsing/#dom-innerhtml-innerhtml -DOM::ExceptionOr inner_html_setter(NonnullRefPtr context_object, String const& value) +DOM::ExceptionOr inner_html_setter(JS::NonnullGCPtr context_object, String const& value) { // 1. Let context element be the context object's host if the context object is a ShadowRoot object, or the context object otherwise. // (This is handled in Element and ShadowRoot) - NonnullRefPtr context_element = is(*context_object) ? *verify_cast(*context_object).host() : verify_cast(*context_object); + JS::NonnullGCPtr context_element = is(*context_object) ? *verify_cast(*context_object).host() : verify_cast(*context_object); // 2. Let fragment be the result of invoking the fragment parsing algorithm with the new value as markup, and with context element. auto fragment = TRY(parse_fragment(value, context_element)); diff --git a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.h b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.h index 55175e9d470a6c2150e9d39a40f2841d05b9fbfe..9689d4edcc4160db7d9637b571c18e1bc707f367 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.h +++ b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.h @@ -14,6 +14,6 @@ namespace Web::DOMParsing { // https://w3c.github.io/DOM-Parsing/#dom-innerhtml-innerhtml -DOM::ExceptionOr inner_html_setter(NonnullRefPtr context_object, String const& value); +DOM::ExceptionOr inner_html_setter(JS::NonnullGCPtr context_object, String const& value); } diff --git a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp index 71ae4e6ec924b3b73e6d9c9e09f71a55feaee91e..ed1f194493126a38cfebfc93bf13b34ee214bf04 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp +++ b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp @@ -24,10 +24,10 @@ XMLSerializer::XMLSerializer() = default; XMLSerializer::~XMLSerializer() = default; // https://w3c.github.io/DOM-Parsing/#dom-xmlserializer-serializetostring -DOM::ExceptionOr XMLSerializer::serialize_to_string(NonnullRefPtr root) +DOM::ExceptionOr XMLSerializer::serialize_to_string(JS::NonnullGCPtr root) { // The serializeToString(root) method must produce an XML serialization of root passing a value of false for the require well-formed parameter, and return the result. - return serialize_node_to_xml_string(move(root), RequireWellFormed::No); + return serialize_node_to_xml_string(root, RequireWellFormed::No); } // https://w3c.github.io/DOM-Parsing/#dfn-add @@ -103,10 +103,10 @@ static bool prefix_is_in_prefix_map(String const& prefix, HashMapvalue.contains_slow(prefix); } -DOM::ExceptionOr serialize_node_to_xml_string_impl(NonnullRefPtr root, Optional& namespace_, HashMap>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed); +DOM::ExceptionOr serialize_node_to_xml_string_impl(JS::NonnullGCPtr root, Optional& namespace_, HashMap>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed); // https://w3c.github.io/DOM-Parsing/#dfn-xml-serialization -DOM::ExceptionOr serialize_node_to_xml_string(NonnullRefPtr root, RequireWellFormed require_well_formed) +DOM::ExceptionOr serialize_node_to_xml_string(JS::NonnullGCPtr root, RequireWellFormed require_well_formed) { // 1. Let namespace be a context namespace with value null. The context namespace tracks the XML serialization algorithm's current default namespace. // The context namespace is changed when either an Element Node has a default namespace declaration, or the algorithm generates a default namespace declaration @@ -139,7 +139,7 @@ static DOM::ExceptionOr serialize_document_type(DOM::DocumentType const& static DOM::ExceptionOr serialize_processing_instruction(DOM::ProcessingInstruction const& processing_instruction, RequireWellFormed require_well_formed); // https://w3c.github.io/DOM-Parsing/#dfn-xml-serialization-algorithm -DOM::ExceptionOr serialize_node_to_xml_string_impl(NonnullRefPtr root, Optional& namespace_, HashMap>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed) +DOM::ExceptionOr serialize_node_to_xml_string_impl(JS::NonnullGCPtr root, Optional& namespace_, HashMap>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed) { // Each of the following algorithms for producing an XML serialization of a DOM node take as input a node to serialize and the following arguments: // - A context namespace namespace @@ -155,43 +155,43 @@ DOM::ExceptionOr serialize_node_to_xml_string_impl(NonnullRefPtr(*root)) { // -> Element // Run the algorithm for XML serializing an Element node node. - return serialize_element(static_ptr_cast(root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); + return serialize_element(static_cast(*root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); } if (is(*root)) { // -> Document // Run the algorithm for XML serializing a Document node node. - return serialize_document(static_ptr_cast(root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); + return serialize_document(static_cast(*root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); } if (is(*root)) { // -> Comment // Run the algorithm for XML serializing a Comment node node. - return serialize_comment(static_ptr_cast(root), require_well_formed); + return serialize_comment(static_cast(*root), require_well_formed); } if (is(*root) || is(*root)) { // -> Text // Run the algorithm for XML serializing a Text node node. - return serialize_text(static_ptr_cast(root), require_well_formed); + return serialize_text(static_cast(*root), require_well_formed); } if (is(*root)) { // -> DocumentFragment // Run the algorithm for XML serializing a DocumentFragment node node. - return serialize_document_fragment(static_ptr_cast(root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); + return serialize_document_fragment(static_cast(*root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); } if (is(*root)) { // -> DocumentType // Run the algorithm for XML serializing a DocumentType node node. - return serialize_document_type(static_ptr_cast(root), require_well_formed); + return serialize_document_type(static_cast(*root), require_well_formed); } if (is(*root)) { // -> ProcessingInstruction // Run the algorithm for XML serializing a ProcessingInstruction node node. - return serialize_processing_instruction(static_ptr_cast(root), require_well_formed); + return serialize_processing_instruction(static_cast(*root), require_well_formed); } if (is(*root)) { diff --git a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h index 1157ea47637ed1f7f04cf0e09f7aadea6fec25d0..ca0d875e55a9d7c23ea4513473d292278a5632ca 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h +++ b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h @@ -18,14 +18,14 @@ class XMLSerializer final public: using WrapperType = Bindings::XMLSerializerWrapper; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&) + static NonnullRefPtr create_with_global_object(HTML::Window&) { return adopt_ref(*new XMLSerializer()); } virtual ~XMLSerializer() override; - DOM::ExceptionOr serialize_to_string(NonnullRefPtr root); + DOM::ExceptionOr serialize_to_string(JS::NonnullGCPtr root); private: XMLSerializer(); @@ -36,6 +36,6 @@ enum class RequireWellFormed { Yes, }; -DOM::ExceptionOr serialize_node_to_xml_string(NonnullRefPtr root, RequireWellFormed require_well_formed); +DOM::ExceptionOr serialize_node_to_xml_string(JS::NonnullGCPtr root, RequireWellFormed require_well_formed); } diff --git a/Userland/Libraries/LibWeb/Encoding/TextDecoder.h b/Userland/Libraries/LibWeb/Encoding/TextDecoder.h index 36e6840efda9ad412c9aa4869ccbc5ef36246ce3..729c30fae1e9892545b5722341770a4de717aa99 100644 --- a/Userland/Libraries/LibWeb/Encoding/TextDecoder.h +++ b/Userland/Libraries/LibWeb/Encoding/TextDecoder.h @@ -33,7 +33,7 @@ public: return adopt_ref(*new TextDecoder(*decoder, move(encoding), false, false)); } - static DOM::ExceptionOr> create_with_global_object(Bindings::WindowObject&, FlyString label) + static DOM::ExceptionOr> create_with_global_object(HTML::Window&, FlyString label) { return TextDecoder::create(move(label)); } diff --git a/Userland/Libraries/LibWeb/Encoding/TextEncoder.h b/Userland/Libraries/LibWeb/Encoding/TextEncoder.h index dc395961478fe25cacebe1e67608d3a3c00e5518..aa3882d5cc619d6b913aae157617f5c1f7369055 100644 --- a/Userland/Libraries/LibWeb/Encoding/TextEncoder.h +++ b/Userland/Libraries/LibWeb/Encoding/TextEncoder.h @@ -27,7 +27,7 @@ public: return adopt_ref(*new TextEncoder()); } - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&) + static NonnullRefPtr create_with_global_object(HTML::Window&) { return TextEncoder::create(); } diff --git a/Userland/Libraries/LibWeb/Fetch/Headers.h b/Userland/Libraries/LibWeb/Fetch/Headers.h index 828bb6758bcdb29e8c9709dc432d21d8e25c7f95..05da753472237455168dbcaa03d1d02fd4115c77 100644 --- a/Userland/Libraries/LibWeb/Fetch/Headers.h +++ b/Userland/Libraries/LibWeb/Fetch/Headers.h @@ -36,7 +36,7 @@ public: static DOM::ExceptionOr> create(Optional const&); - static DOM::ExceptionOr> create_with_global_object(Bindings::WindowObject&, Optional const& init) + static DOM::ExceptionOr> create_with_global_object(HTML::Window&, Optional const& init) { return create(init); } diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp index 573330e83b26664eda09625d3ef6bfd45bb536d8..69f912e00feb72665d79d1f45543ddd084d0a8b0 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp @@ -116,6 +116,8 @@ Blob::Blob(ByteBuffer byte_buffer) { } +Blob::~Blob() = default; + // https://w3c.github.io/FileAPI/#ref-for-dom-blob-blob DOM::ExceptionOr> Blob::create(Optional> const& blob_parts, Optional const& options) { @@ -149,7 +151,7 @@ DOM::ExceptionOr> Blob::create(Optional> co return adopt_ref(*new Blob(move(byte_buffer), move(type))); } -DOM::ExceptionOr> Blob::create_with_global_object(Bindings::WindowObject&, Optional> const& blob_parts, Optional const& options) +DOM::ExceptionOr> Blob::create_with_global_object(HTML::Window&, Optional> const& blob_parts, Optional const& options) { return Blob::create(blob_parts, options); } @@ -262,9 +264,4 @@ JS::Promise* Blob::array_buffer() return promise; } -JS::Object* Blob::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - } diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.h b/Userland/Libraries/LibWeb/FileAPI/Blob.h index 1604fd6a6ebe516e2f2de3fb83b23cfa58a69cb3..0513db6eae6f7ed24cec9e6761c4bed3b491cd7c 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.h +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.h @@ -10,8 +10,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -39,8 +38,10 @@ public: using WrapperType = Bindings::BlobWrapper; Blob(ByteBuffer byte_buffer, String type); + virtual ~Blob() override; + static DOM::ExceptionOr> create(Optional> const& blob_parts = {}, Optional const& options = {}); - static DOM::ExceptionOr> create_with_global_object(Bindings::WindowObject&, Optional> const& blob_parts = {}, Optional const& options = {}); + static DOM::ExceptionOr> create_with_global_object(HTML::Window&, Optional> const& blob_parts = {}, Optional const& options = {}); // https://w3c.github.io/FileAPI/#dfn-size u64 size() const { return m_byte_buffer.size(); } @@ -52,8 +53,6 @@ public: JS::Promise* text(); JS::Promise* array_buffer(); - virtual JS::Object* create_wrapper(JS::Realm&); - ReadonlyBytes bytes() const { return m_byte_buffer.bytes(); } protected: diff --git a/Userland/Libraries/LibWeb/FileAPI/File.cpp b/Userland/Libraries/LibWeb/FileAPI/File.cpp index 4498789aefe9d497098ba0ba14d878b7c22d484d..b982869ed2e3618f143a086b53f38fbebda0df73 100644 --- a/Userland/Libraries/LibWeb/FileAPI/File.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/File.cpp @@ -56,7 +56,7 @@ DOM::ExceptionOr> File::create(Vector const& file_ return adopt_ref(*new File(move(bytes), move(name), move(type), last_modified)); } -DOM::ExceptionOr> File::create_with_global_object(Bindings::WindowObject&, Vector const& file_bits, String const& file_name, Optional const& options) +DOM::ExceptionOr> File::create_with_global_object(HTML::Window&, Vector const& file_bits, String const& file_name, Optional const& options) { return create(file_bits, file_name, options); } diff --git a/Userland/Libraries/LibWeb/FileAPI/File.h b/Userland/Libraries/LibWeb/FileAPI/File.h index 636a620b32b10074793c1900509268e4e349cabb..43a80080551c569ef0777e9a6b33c0aee9521725 100644 --- a/Userland/Libraries/LibWeb/FileAPI/File.h +++ b/Userland/Libraries/LibWeb/FileAPI/File.h @@ -21,7 +21,7 @@ public: using WrapperType = Bindings::FileWrapper; static DOM::ExceptionOr> create(Vector const& file_bits, String const& file_name, Optional const& options = {}); - static DOM::ExceptionOr> create_with_global_object(Bindings::WindowObject&, Vector const& file_bits, String const& file_name, Optional const& options = {}); + static DOM::ExceptionOr> create_with_global_object(HTML::Window&, Vector const& file_bits, String const& file_name, Optional const& options = {}); // https://w3c.github.io/FileAPI/#dfn-name String const& name() const { return m_name; } diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 1e4cfde06f5715c788d96984fadc8db04e878a82..dac3d9232124e79242122dc8e7cb533217236ae2 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -71,6 +71,7 @@ class LengthPercentage; class LengthStyleValue; class LinearGradientStyleValue; class ListStyleStyleValue; +class MediaFeatureValue; class MediaList; class MediaQuery; class MediaQueryList; @@ -447,18 +448,10 @@ class URLSearchParamsIterator; namespace Web::Bindings { class AbortControllerWrapper; -class AbortSignalWrapper; -class AttributeWrapper; class BlobWrapper; class CanvasGradientWrapper; class CanvasRenderingContext2DWrapper; -class CDATASectionWrapper; -class CharacterDataWrapper; -class CommentWrapper; class CryptoWrapper; -class DocumentFragmentWrapper; -class DocumentTypeWrapper; -class DocumentWrapper; class DOMExceptionWrapper; class DOMParserWrapper; class DOMPointWrapper; @@ -466,102 +459,23 @@ class DOMPointReadOnlyWrapper; class DOMRectListWrapper; class DOMRectReadOnlyWrapper; class DOMRectWrapper; -class ElementWrapper; -class EventTargetWrapper; class FileWrapper; class HeadersWrapper; class HeadersIteratorWrapper; class HistoryWrapper; -class HTMLAnchorElementWrapper; -class HTMLAreaElementWrapper; -class HTMLAudioElementWrapper; -class HTMLBaseElementWrapper; -class HTMLBodyElementWrapper; -class HTMLBRElementWrapper; -class HTMLButtonElementWrapper; -class HTMLCanvasElementWrapper; class HTMLCollectionWrapper; -class HTMLDataElementWrapper; -class HTMLDataListElementWrapper; -class HTMLDetailsElementWrapper; -class HTMLDialogElementWrapper; -class HTMLDirectoryElementWrapper; -class HTMLDivElementWrapper; -class HTMLDListElementWrapper; -class HTMLElementWrapper; -class HTMLEmbedElementWrapper; -class HTMLFieldSetElementWrapper; -class HTMLFontElementWrapper; -class HTMLFormElementWrapper; -class HTMLFrameElementWrapper; -class HTMLFrameSetElementWrapper; -class HTMLHeadElementWrapper; -class HTMLHeadingElementWrapper; -class HTMLHRElementWrapper; -class HTMLHtmlElementWrapper; -class HTMLIFrameElementWrapper; -class HTMLImageElementWrapper; -class HTMLInputElementWrapper; -class HTMLLabelElementWrapper; -class HTMLLegendElementWrapper; -class HTMLLIElementWrapper; -class HTMLLinkElementWrapper; -class HTMLMapElementWrapper; -class HTMLMarqueeElementWrapper; -class HTMLMediaElementWrapper; -class HTMLMenuElementWrapper; -class HTMLMetaElementWrapper; -class HTMLMeterElementWrapper; -class HTMLModElementWrapper; -class HTMLObjectElementWrapper; -class HTMLOListElementWrapper; -class HTMLOptGroupElementWrapper; -class HTMLOptionElementWrapper; class HTMLOptionsCollectionWrapper; -class HTMLOutputElementWrapper; -class HTMLParagraphElementWrapper; -class HTMLParamElementWrapper; -class HTMLPictureElementWrapper; -class HTMLPreElementWrapper; -class HTMLProgressElementWrapper; -class HTMLQuoteElementWrapper; -class HTMLScriptElementWrapper; -class HTMLSelectElementWrapper; -class HTMLSlotElementWrapper; -class HTMLSourceElementWrapper; -class HTMLSpanElementWrapper; -class HTMLStyleElementWrapper; -class HTMLTableCaptionElementWrapper; -class HTMLTableCellElementWrapper; -class HTMLTableColElementWrapper; -class HTMLTableElementWrapper; -class HTMLTableRowElementWrapper; -class HTMLTableSectionElementWrapper; -class HTMLTemplateElementWrapper; -class HTMLTextAreaElementWrapper; -class HTMLTimeElementWrapper; -class HTMLTitleElementWrapper; -class HTMLTrackElementWrapper; -class HTMLUListElementWrapper; -class HTMLUnknownElementWrapper; -class HTMLVideoElementWrapper; class IdleDeadlineWrapper; class ImageDataWrapper; class IntersectionObserverWrapper; class LocationObject; -class MediaQueryListWrapper; class MessageChannelWrapper; -class MessagePortWrapper; class MutationObserverWrapper; class MutationRecordWrapper; class NodeListWrapper; -class NodeWrapper; class OptionConstructor; class Path2DWrapper; class PerformanceTimingWrapper; -class PerformanceWrapper; -class ProcessingInstructionWrapper; -class RangeConstructor; class RangePrototype; class ResizeObserverWrapper; class ScreenWrapper; @@ -569,47 +483,20 @@ class SelectionWrapper; class StorageWrapper; class SubtleCryptoWrapper; class SVGAnimatedLengthWrapper; -class SVGCircleElementWrapper; -class SVGDefsElementWrapper; -class SVGClipPathElementWrapper; -class SVGElementWrapper; -class SVGEllipseElementWrapper; -class SVGGeometryElementWrapper; -class SVGGraphicsElementWrapper; class SVGLengthWrapper; -class SVGLineElementWrapper; -class SVGPathElementWrapper; -class SVGPolygonElementWrapper; -class SVGPolylineElementWrapper; -class SVGRectElementWrapper; -class SVGSVGElementWrapper; -class SVGTextContentElementWrapper; class TextDecoderWrapper; class TextEncoderWrapper; class TextMetricsWrapper; -class TextWrapper; -class URLConstructor; -class URLPrototype; -class URLSearchParamsConstructor; -class URLSearchParamsIteratorPrototype; class URLSearchParamsIteratorWrapper; -class URLSearchParamsPrototype; class URLSearchParamsWrapper; class URLWrapper; class WebGLRenderingContextWrapper; -class WebSocketWrapper; -class WindowObject; class WindowProxy; -class WorkerWrapper; -class WorkerGlobalScopeWrapper; class WorkerLocationWrapper; class WorkerNavigatorWrapper; class Wrappable; class Wrapper; -class XMLHttpRequestConstructor; -class XMLHttpRequestEventTargetWrapper; class XMLHttpRequestPrototype; -class XMLHttpRequestWrapper; class XMLSerializerWrapper; enum class CanPlayTypeResult; enum class CanvasFillRule; diff --git a/Userland/Libraries/LibWeb/Geometry/DOMPoint.h b/Userland/Libraries/LibWeb/Geometry/DOMPoint.h index ea75d9a36b0a68c38deb115de3e736a7fd6a0d03..ccea076ebb6cbe1a05ea444590a95af5acaf235d 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMPoint.h +++ b/Userland/Libraries/LibWeb/Geometry/DOMPoint.h @@ -15,7 +15,7 @@ class DOMPoint final : public DOMPointReadOnly { public: using WrapperType = Bindings::DOMPointWrapper; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double z = 0, double w = 0) + static NonnullRefPtr create_with_global_object(HTML::Window&, double x = 0, double y = 0, double z = 0, double w = 0) { return DOMPoint::create(x, y, z, w); } diff --git a/Userland/Libraries/LibWeb/Geometry/DOMPointReadOnly.h b/Userland/Libraries/LibWeb/Geometry/DOMPointReadOnly.h index 5b088a41eb4427fb6a6d70651bd889a4963772f5..b9587058aec75839de83a5172d082cb2c1ac9bf8 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMPointReadOnly.h +++ b/Userland/Libraries/LibWeb/Geometry/DOMPointReadOnly.h @@ -20,7 +20,7 @@ class DOMPointReadOnly public: using WrapperType = Bindings::DOMPointReadOnlyWrapper; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double z = 0, double w = 0) + static NonnullRefPtr create_with_global_object(HTML::Window&, double x = 0, double y = 0, double z = 0, double w = 0) { return DOMPointReadOnly::create(x, y, z, w); } diff --git a/Userland/Libraries/LibWeb/Geometry/DOMRect.h b/Userland/Libraries/LibWeb/Geometry/DOMRect.h index dd46bec587f7e5e5987b3baca6a714a2264dd93b..057ea1ca36dc8227c880d949ee5ec53c99f6f5fc 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMRect.h +++ b/Userland/Libraries/LibWeb/Geometry/DOMRect.h @@ -16,7 +16,7 @@ class DOMRect final public: using WrapperType = Bindings::DOMRectWrapper; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double width = 0, double height = 0) + static NonnullRefPtr create_with_global_object(HTML::Window&, double x = 0, double y = 0, double width = 0, double height = 0) { return DOMRect::create(x, y, width, height); } diff --git a/Userland/Libraries/LibWeb/Geometry/DOMRectReadOnly.h b/Userland/Libraries/LibWeb/Geometry/DOMRectReadOnly.h index 1581ef63181cc9fae269d31518a2fa193de2eb6c..148ed1044fb72633805d1c1e56fcaa62ad73555d 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMRectReadOnly.h +++ b/Userland/Libraries/LibWeb/Geometry/DOMRectReadOnly.h @@ -20,7 +20,7 @@ class DOMRectReadOnly public: using WrapperType = Bindings::DOMRectReadOnlyWrapper; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double width = 0, double height = 0) + static NonnullRefPtr create_with_global_object(HTML::Window&, double x = 0, double y = 0, double width = 0, double height = 0) { return DOMRectReadOnly::create(x, y, width, height); } diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index f9aedf856308352397b7c7ff6aceadb8795101e6..4af36b5b92efc0d35f44d183adb8aa9b0b8fd488 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -88,7 +88,7 @@ HTML::Origin determine_the_origin(BrowsingContext const& browsing_context, Optio } // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-browsing-context -NonnullRefPtr BrowsingContext::create_a_new_browsing_context(Page& page, RefPtr creator, RefPtr embedder) +NonnullRefPtr BrowsingContext::create_a_new_browsing_context(Page& page, JS::GCPtr creator, JS::GCPtr embedder) { // 1. Let browsingContext be a new browsing context. BrowsingContextContainer* container = (embedder && is(*embedder)) ? static_cast(embedder.ptr()) : nullptr; @@ -117,19 +117,17 @@ NonnullRefPtr BrowsingContext::create_a_new_browsing_context(Pa // FIXME: 7. Let agent be the result of obtaining a similar-origin window agent given origin, group, and false. - RefPtr window; + JS::GCPtr window; // 8. Let realm execution context be the result of creating a new JavaScript realm given agent and the following customizations: auto realm_execution_context = Bindings::create_a_new_javascript_realm( Bindings::main_thread_vm(), - [&](JS::Realm& realm) -> JS::GlobalObject* { + [&](JS::Realm& realm) -> JS::Object* { // - For the global object, create a new Window object. - window = HTML::Window::create(); - auto* global_object = realm.heap().allocate_without_realm(realm, *window); - VERIFY(window->wrapper() == global_object); - return global_object; + window = HTML::Window::create(realm); + return window.ptr(); }, - [](JS::Realm&) -> JS::GlobalObject* { + [](JS::Realm&) -> JS::Object* { // FIXME: - For the global this binding, use browsingContext's WindowProxy object. return nullptr; }); @@ -172,7 +170,7 @@ NonnullRefPtr BrowsingContext::create_a_new_browsing_context(Pa // FIXME: load timing info is loadTimingInfo, // FIXME: navigation id is null, // and which is ready for post-load tasks. - auto document = DOM::Document::create(); + auto document = DOM::Document::create(*window); // Non-standard document->set_window({}, *window); @@ -197,7 +195,7 @@ NonnullRefPtr BrowsingContext::create_a_new_browsing_context(Pa document->append_child(html_node); // 19. Set the active document of browsingContext to document. - browsing_context->m_active_document = document; + browsing_context->m_active_document = JS::make_handle(*document); // 20. If browsingContext's creator URL is non-null, then set document's referrer to the serialization of it. if (browsing_context->m_creator_url.has_value()) { @@ -209,7 +207,7 @@ NonnullRefPtr BrowsingContext::create_a_new_browsing_context(Pa // 22. Append a new session history entry to browsingContext's session history whose URL is about:blank and document is document. browsing_context->m_session_history.append(HTML::SessionHistoryEntry { .url = AK::URL("about:blank"), - .document = document, + .document = document.ptr(), .serialized_state = {}, .policy_container = {}, .scroll_restoration_mode = {}, @@ -277,7 +275,7 @@ bool BrowsingContext::is_focused_context() const void BrowsingContext::set_active_document(DOM::Document* document) { - if (m_active_document == document) + if (m_active_document.ptr() == document) return; m_cursor_position = {}; @@ -298,7 +296,7 @@ void BrowsingContext::set_active_document(DOM::Document* document) m_name = String::empty(); } - m_active_document = document; + m_active_document = JS::make_handle(document); if (m_active_document) { m_active_document->attach_to_browsing_context({}, *this); @@ -392,7 +390,7 @@ void BrowsingContext::scroll_to_anchor(String const& fragment) auto candidates = active_document()->get_elements_by_name(fragment); for (auto& candidate : candidates->collect_matching_elements()) { if (is(*candidate)) { - element = verify_cast(*candidate); + element = &verify_cast(*candidate); break; } } @@ -603,7 +601,7 @@ bool BrowsingContext::has_a_rendering_opportunity() const } // https://html.spec.whatwg.org/multipage/interaction.html#currently-focused-area-of-a-top-level-browsing-context -RefPtr BrowsingContext::currently_focused_area() +JS::GCPtr BrowsingContext::currently_focused_area() { // 1. If topLevelBC does not have system focus, then return null. if (!is_focused_context()) @@ -756,4 +754,14 @@ bool BrowsingContext::still_on_its_initial_about_blank_document() const && m_session_history[0].document->is_initial_about_blank(); } +DOM::Document const* BrowsingContext::active_document() const +{ + return m_active_document.cell(); +} + +DOM::Document* BrowsingContext::active_document() +{ + return m_active_document.cell(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h index f48ef6d4f5d6b1514553d42cce30dd1ff0a90719..ddcd870ea197d57015bd90055336eeee1b7f803c 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h @@ -26,7 +26,7 @@ namespace Web::HTML { class BrowsingContext : public TreeNode { public: - static NonnullRefPtr create_a_new_browsing_context(Page&, RefPtr creator, RefPtr embedder); + static NonnullRefPtr create_a_new_browsing_context(Page&, JS::GCPtr creator, JS::GCPtr embedder); ~BrowsingContext(); @@ -41,8 +41,8 @@ public: bool is_top_level() const; bool is_focused_context() const; - DOM::Document const* active_document() const { return m_active_document; } - DOM::Document* active_document() { return m_active_document; } + DOM::Document const* active_document() const; + DOM::Document* active_document(); void set_active_document(DOM::Document*); @@ -109,7 +109,7 @@ public: bool has_a_rendering_opportunity() const; - RefPtr currently_focused_area(); + JS::GCPtr currently_focused_area(); String const& name() const { return m_name; } void set_name(String const& name) { m_name = name; } @@ -143,7 +143,7 @@ private: Optional m_creator_origin; WeakPtr m_container; - RefPtr m_active_document; + JS::Handle m_active_document; Gfx::IntSize m_size; Gfx::IntPoint m_viewport_scroll_offset; diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h index 5cdc7ca49741ae93fa85cc2d8e6c7eb61686cd44..80228438acda3639f4c0fefd1540942e534af0de 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h @@ -11,8 +11,9 @@ namespace Web::HTML { class BrowsingContextContainer : public HTMLElement { + WEB_PLATFORM_OBJECT(BrowsingContextContainer, HTMLElement); + public: - BrowsingContextContainer(DOM::Document&, DOM::QualifiedName); virtual ~BrowsingContextContainer() override; BrowsingContext* nested_browsing_context() { return m_nested_browsing_context; } @@ -26,6 +27,8 @@ public: DOM::Document const* get_svg_document() const; protected: + BrowsingContextContainer(DOM::Document&, DOM::QualifiedName); + void create_new_nested_browsing_context(); void discard_nested_browsing_context(); @@ -41,3 +44,5 @@ namespace Web::DOM { template<> inline bool Node::fast_is() const { return is_browsing_context_container(); } } + +WRAPPER_HACK(BrowsingContextContainer, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h index 056620565c876c1f20c4eeeb05d8078b73c14c7a..3a6ab3cebc93ef766d23c0bc26cf65a8afe36f24 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h @@ -15,7 +15,7 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/canvas.html#canvasimagesource // NOTE: This is the Variant created by the IDL wrapper generator, and needs to be updated accordingly. -using CanvasImageSource = Variant, NonnullRefPtr>; +using CanvasImageSource = Variant, JS::Handle>; // https://html.spec.whatwg.org/multipage/canvas.html#canvasdrawimage class CanvasDrawImage { diff --git a/Userland/Libraries/LibWeb/HTML/CanvasGradient.h b/Userland/Libraries/LibWeb/HTML/CanvasGradient.h index d748ba86a7753278ffdde71042526a9f0d4d6b2e..5aa89d10cb75f70363622bea4e68d16db46c570b 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasGradient.h +++ b/Userland/Libraries/LibWeb/HTML/CanvasGradient.h @@ -16,14 +16,14 @@ class CanvasGradient final : public RefCounted , public Bindings::Wrappable { public: - using WrapperType = Bindings::CanvasGradientWrapper; - enum class Type { Linear, Radial, Conic, }; + using WrapperType = Bindings::CanvasGradientWrapper; + static NonnullRefPtr create_radial(double x0, double y0, double r0, double x1, double y1, double r1); static NonnullRefPtr create_linear(double x0, double y0, double x1, double y1); static NonnullRefPtr create_conic(double start_angle, double x, double y); diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index ef494957362dac37f7f772205a3531d1ec659201..fea84804e5fbce07bda0e158da5919f134b29892 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -25,7 +24,7 @@ namespace Web::HTML { CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement& element) - : RefCountForwarder(element) + : m_element(JS::make_handle(element)) { } @@ -33,17 +32,17 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() = default; HTMLCanvasElement& CanvasRenderingContext2D::canvas_element() { - return ref_count_target(); + return *m_element; } HTMLCanvasElement const& CanvasRenderingContext2D::canvas_element() const { - return ref_count_target(); + return *m_element; } -NonnullRefPtr CanvasRenderingContext2D::canvas_for_binding() const +JS::NonnullGCPtr CanvasRenderingContext2D::canvas_for_binding() const { - return canvas_element(); + return *m_element; } void CanvasRenderingContext2D::fill_rect(float x, float y, float width, float height) @@ -520,15 +519,15 @@ DOM::ExceptionOr check_usability_of_image(CanvasImag // 1. Switch on image: auto usability = TRY(image.visit( // HTMLOrSVGImageElement - [](HTMLImageElement const& image_element) -> DOM::ExceptionOr> { + [](JS::Handle const& image_element) -> DOM::ExceptionOr> { // FIXME: If image's current request's state is broken, then throw an "InvalidStateError" DOMException. // If image is not fully decodable, then return bad. - if (!image_element.bitmap()) + if (!image_element->bitmap()) return { CanvasImageSourceUsability::Bad }; // If image has an intrinsic width or intrinsic height (or both) equal to zero, then return bad. - if (image_element.bitmap()->width() == 0 || image_element.bitmap()->height() == 0) + if (image_element->bitmap()->width() == 0 || image_element->bitmap()->height() == 0) return { CanvasImageSourceUsability::Bad }; return Optional {}; }, @@ -538,9 +537,9 @@ DOM::ExceptionOr check_usability_of_image(CanvasImag // HTMLCanvasElement // FIXME: OffscreenCanvas - [](HTMLCanvasElement const& canvas_element) -> DOM::ExceptionOr> { + [](JS::Handle const& canvas_element) -> DOM::ExceptionOr> { // If image has either a horizontal dimension or a vertical dimension equal to zero, then throw an "InvalidStateError" DOMException. - if (canvas_element.width() == 0 || canvas_element.height() == 0) + if (canvas_element->width() == 0 || canvas_element->height() == 0) return DOM::InvalidStateError::create("Canvas width or height is zero"); return Optional {}; })); @@ -557,7 +556,7 @@ bool image_is_not_origin_clean(CanvasImageSource const& image) // An object image is not origin-clean if, switching on image's type: return image.visit( // HTMLOrSVGImageElement - [](HTMLImageElement const&) { + [](JS::Handle const&) { // FIXME: image's current request's image data is CORS-cross-origin. return false; }, @@ -567,7 +566,7 @@ bool image_is_not_origin_clean(CanvasImageSource const& image) // HTMLCanvasElement // FIXME: ImageBitmap - [](HTMLCanvasElement const&) { + [](JS::Handle const&) { // FIXME: image's bitmap's origin-clean flag is false. return false; }); diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h index 3fecfb3fadd1ea4b7dc2fb170669b6142e130185..639e6dba4ed63b90711450ae6c86c0ad79f036d4 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h @@ -34,10 +34,10 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/canvas.html#canvasimagesource // NOTE: This is the Variant created by the IDL wrapper generator, and needs to be updated accordingly. -using CanvasImageSource = Variant, NonnullRefPtr>; +using CanvasImageSource = Variant, JS::Handle>; class CanvasRenderingContext2D - : public RefCountForwarder + : public RefCounted , public Bindings::Wrappable , public CanvasPath , public CanvasState @@ -81,7 +81,7 @@ public: virtual void reset_to_default_state() override; - NonnullRefPtr canvas_for_binding() const; + JS::NonnullGCPtr canvas_for_binding() const; virtual RefPtr measure_text(String const& text) override; @@ -112,6 +112,8 @@ private: void stroke_internal(Gfx::Path const&); void fill_internal(Gfx::Path&, String const& fill_rule); + JS::Handle m_element; + // https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-origin-clean bool m_origin_clean { true }; }; diff --git a/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp b/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp index 6a1a0f9c6e6003e355c24261d862079351ead1fb..047cac83062463c7fda5836cb2c30ea39800f717 100644 --- a/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp @@ -5,22 +5,22 @@ */ #include -#include #include +#include namespace Web::HTML { -CloseEvent* CloseEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init) +CloseEvent* CloseEvent::create(HTML::Window& window_object, FlyString const& event_name, CloseEventInit const& event_init) { return window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); } -CloseEvent* CloseEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init) +CloseEvent* CloseEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, CloseEventInit const& event_init) { return create(window_object, event_name, event_init); } -CloseEvent::CloseEvent(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init) +CloseEvent::CloseEvent(HTML::Window& window_object, FlyString const& event_name, CloseEventInit const& event_init) : DOM::Event(window_object, event_name, event_init) , m_was_clean(event_init.was_clean) , m_code(event_init.code) diff --git a/Userland/Libraries/LibWeb/HTML/CloseEvent.h b/Userland/Libraries/LibWeb/HTML/CloseEvent.h index db3f1ba2b1cdb4e58a7a15019a5db2af1526a31e..0930a7b0d0c2af2704cbd978d1f317accdd8454b 100644 --- a/Userland/Libraries/LibWeb/HTML/CloseEvent.h +++ b/Userland/Libraries/LibWeb/HTML/CloseEvent.h @@ -18,18 +18,16 @@ struct CloseEventInit : public DOM::EventInit { }; class CloseEvent : public DOM::Event { - JS_OBJECT(CloseEvent, DOM::Event); + WEB_PLATFORM_OBJECT(CloseEvent, DOM::Event); public: - static CloseEvent* create(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init = {}); - static CloseEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init); + static CloseEvent* create(HTML::Window&, FlyString const& event_name, CloseEventInit const& event_init = {}); + static CloseEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, CloseEventInit const& event_init); - CloseEvent(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init); + CloseEvent(HTML::Window&, FlyString const& event_name, CloseEventInit const& event_init); virtual ~CloseEvent() override; - CloseEvent& impl() { return *this; } - bool was_clean() const { return m_was_clean; } u16 code() const { return m_code; } String reason() const { return m_reason; } diff --git a/Userland/Libraries/LibWeb/HTML/DOMParser.cpp b/Userland/Libraries/LibWeb/HTML/DOMParser.cpp index 7fc9d22c6298fbc413ed815e0a93c4f2c27446b3..1f661a4ffd91a5f6c9ce981c981178092276f144 100644 --- a/Userland/Libraries/LibWeb/HTML/DOMParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/DOMParser.cpp @@ -4,22 +4,26 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include +#include #include #include #include namespace Web::HTML { -DOMParser::DOMParser() = default; +DOMParser::DOMParser(HTML::Window& window) + : m_window(JS::make_handle(window)) +{ +} + DOMParser::~DOMParser() = default; // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring -NonnullRefPtr DOMParser::parse_from_string(String const& string, Bindings::DOMParserSupportedType type) +JS::NonnullGCPtr DOMParser::parse_from_string(String const& string, Bindings::DOMParserSupportedType type) { // 1. Let document be a new Document, whose content type is type and url is this's relevant global object's associated Document's URL. - // FIXME: Pass in this's relevant global object's associated Document's URL. - auto document = DOM::Document::create(); + auto document = DOM::Document::create(Bindings::main_thread_internal_window_object(), m_window->associated_document().url()); document->set_content_type(Bindings::idl_enum_to_string(type)); // 2. Switch on type: @@ -31,7 +35,7 @@ NonnullRefPtr DOMParser::parse_from_string(String const& string, // 2. Create an HTML parser parser, associated with document. // 3. Place string into the input stream for parser. The encoding confidence is irrelevant. // FIXME: We don't have the concept of encoding confidence yet. - auto parser = HTMLParser::create(document, string, "UTF-8"); + auto parser = HTMLParser::create(*document, string, "UTF-8"); // 4. Start parser and let it run until it has consumed all the characters just inserted into the input stream. // FIXME: This is to match the default URL. Instead, pass in this's relevant global object's associated Document's URL. @@ -41,7 +45,7 @@ NonnullRefPtr DOMParser::parse_from_string(String const& string, // 1. Create an XML parser parse, associated with document, and with XML scripting support disabled. XML::Parser parser(string, { .resolve_external_resource = resolve_xml_resource }); - XMLDocumentBuilder builder { document, XMLScriptingSupport::Disabled }; + XMLDocumentBuilder builder { *document, XMLScriptingSupport::Disabled }; // 2. Parse string using parser. auto result = parser.parse_with_listener(builder); // 3. If the previous step resulted in an XML well-formedness or XML namespace well-formedness error, then: @@ -50,10 +54,10 @@ NonnullRefPtr DOMParser::parse_from_string(String const& string, // 1. Assert: document has no child nodes. document->remove_all_children(true); // 2. Let root be the result of creating an element given document, "parsererror", and "http://www.mozilla.org/newlayout/xml/parsererror.xml". - auto root = DOM::create_element(document, "parsererror", "http://www.mozilla.org/newlayout/xml/parsererror.xml"); + auto root = DOM::create_element(*document, "parsererror", "http://www.mozilla.org/newlayout/xml/parsererror.xml"); // FIXME: 3. Optionally, add attributes or children to root to describe the nature of the parsing error. // 4. Append root to document. - document->append_child(root); + document->append_child(*root); } } diff --git a/Userland/Libraries/LibWeb/HTML/DOMParser.h b/Userland/Libraries/LibWeb/HTML/DOMParser.h index 4df6ba2d5b45496a5c245da2be00df8c1d03277f..4c1c50f70873e169676eb9aca21b78d7e468e034 100644 --- a/Userland/Libraries/LibWeb/HTML/DOMParser.h +++ b/Userland/Libraries/LibWeb/HTML/DOMParser.h @@ -23,17 +23,19 @@ class DOMParser final public: using WrapperType = Bindings::DOMParserWrapper; - static DOM::ExceptionOr> create_with_global_object(Bindings::WindowObject&) + static DOM::ExceptionOr> create_with_global_object(HTML::Window& window) { - return adopt_ref(*new DOMParser()); + return adopt_ref(*new DOMParser(window)); } virtual ~DOMParser() override; - NonnullRefPtr parse_from_string(String const&, Bindings::DOMParserSupportedType type); + JS::NonnullGCPtr parse_from_string(String const&, Bindings::DOMParserSupportedType type); private: - DOMParser(); + explicit DOMParser(HTML::Window&); + + JS::Handle m_window; }; } diff --git a/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp b/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp index 3e276996ed25e257a770b9d3427bd99ca19f21b2..6b6a0a85c316975a36b8293bad5dd50685f97a1a 100644 --- a/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp +++ b/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp @@ -6,27 +6,33 @@ #include #include -#include #include #include #include +#include namespace Web::HTML { -DOMStringMap* DOMStringMap::create(DOM::Element& element) +JS::NonnullGCPtr DOMStringMap::create(DOM::Element& element) { - auto& realm = element.document().preferred_window_object().realm(); - return realm.heap().allocate(realm, element); + auto& realm = element.document().window().realm(); + return *realm.heap().allocate(realm, element); } DOMStringMap::DOMStringMap(DOM::Element& element) - : PlatformObject(element.document().preferred_window_object().ensure_web_prototype("DOMStringMap")) + : PlatformObject(element.document().window().ensure_web_prototype("DOMStringMap")) , m_associated_element(element) { } DOMStringMap::~DOMStringMap() = default; +void DOMStringMap::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_associated_element.ptr()); +} + // https://html.spec.whatwg.org/multipage/dom.html#concept-domstringmap-pairs Vector DOMStringMap::get_name_value_pairs() const { diff --git a/Userland/Libraries/LibWeb/HTML/DOMStringMap.h b/Userland/Libraries/LibWeb/HTML/DOMStringMap.h index 902037a2dbe685cea45b8e2cda402e7fc5978075..c01294c2e9030a669744b2d943251bd135aa0749 100644 --- a/Userland/Libraries/LibWeb/HTML/DOMStringMap.h +++ b/Userland/Libraries/LibWeb/HTML/DOMStringMap.h @@ -14,16 +14,13 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/dom.html#domstringmap class DOMStringMap final : public Bindings::PlatformObject { - JS_OBJECT(DOMStringMap, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(DOMStringMap, Bindings::PlatformObject); public: - static DOMStringMap* create(DOM::Element&); - explicit DOMStringMap(DOM::Element&); + static JS::NonnullGCPtr create(DOM::Element&); virtual ~DOMStringMap() override; - DOMStringMap& impl() { return *this; } - Vector supported_property_names() const; String determine_value_of_named_property(String const&) const; @@ -34,6 +31,10 @@ public: bool delete_existing_named_property(String const&); private: + explicit DOMStringMap(DOM::Element&); + + virtual void visit_edges(Cell::Visitor&) override; + struct NameValuePair { String name; String value; @@ -42,12 +43,9 @@ private: Vector get_name_value_pairs() const; // https://html.spec.whatwg.org/multipage/dom.html#concept-domstringmap-element - NonnullRefPtr m_associated_element; + JS::NonnullGCPtr m_associated_element; }; } -namespace Web::Bindings { -inline JS::Object* wrap(JS::Realm&, Web::HTML::DOMStringMap& object) { return &object; } -using DOMStringMapWrapper = Web::HTML::DOMStringMap; -} +WRAPPER_HACK(DOMStringMap, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp b/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp index 111f96a13d28d0dcdc3194fc0da8a6e63648c5b7..7a9654c538b7e8713dd6dfd6f7c2ee24d60ddc8e 100644 --- a/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp @@ -5,22 +5,22 @@ */ #include -#include #include +#include namespace Web::HTML { -ErrorEvent* ErrorEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init) +ErrorEvent* ErrorEvent::create(HTML::Window& window_object, FlyString const& event_name, ErrorEventInit const& event_init) { return window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); } -ErrorEvent* ErrorEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init) +ErrorEvent* ErrorEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, ErrorEventInit const& event_init) { return create(window_object, event_name, event_init); } -ErrorEvent::ErrorEvent(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init) +ErrorEvent::ErrorEvent(HTML::Window& window_object, FlyString const& event_name, ErrorEventInit const& event_init) : DOM::Event(window_object, event_name) , m_message(event_init.message) , m_filename(event_init.filename) diff --git a/Userland/Libraries/LibWeb/HTML/ErrorEvent.h b/Userland/Libraries/LibWeb/HTML/ErrorEvent.h index 83b137f4979fbe70ff6fe87561327ed4af8f15d3..ed978add8112bd6f05ff92456f0853fc518a3959 100644 --- a/Userland/Libraries/LibWeb/HTML/ErrorEvent.h +++ b/Userland/Libraries/LibWeb/HTML/ErrorEvent.h @@ -21,18 +21,16 @@ struct ErrorEventInit : public DOM::EventInit { // https://html.spec.whatwg.org/multipage/webappapis.html#errorevent class ErrorEvent final : public DOM::Event { - JS_OBJECT(ErrorEvent, DOM::Event); + WEB_PLATFORM_OBJECT(ErrorEvent, DOM::Event); public: - static ErrorEvent* create(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init = {}); - static ErrorEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init); + static ErrorEvent* create(HTML::Window&, FlyString const& event_name, ErrorEventInit const& event_init = {}); + static ErrorEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, ErrorEventInit const& event_init); - ErrorEvent(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init); + ErrorEvent(HTML::Window&, FlyString const& event_name, ErrorEventInit const& event_init); virtual ~ErrorEvent() override; - ErrorEvent& impl() { return *this; } - // https://html.spec.whatwg.org/multipage/webappapis.html#dom-errorevent-message String const& message() const { return m_message; } diff --git a/Userland/Libraries/LibWeb/HTML/EventHandler.cpp b/Userland/Libraries/LibWeb/HTML/EventHandler.cpp index 8e421c3e88d55dc11d3cc0a17a222b8fe61876b9..612df300417e494c916b9be4281a924cf277ddff 100644 --- a/Userland/Libraries/LibWeb/HTML/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/HTML/EventHandler.cpp @@ -4,9 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include #include +#include namespace Web::HTML { diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index acded61637d7b5e1c455b6d3aacb53c5306b2f36..34978bc6c33db62708ff177fb0925539962a7bb0 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -141,12 +141,12 @@ void EventLoop::process() // - Any Document B whose browsing context's container document is A must be listed after A in the list. // - If there are two documents A and B whose browsing contexts are both child browsing contexts whose container documents are another Document C, then the order of A and B in the list must match the shadow-including tree order of their respective browsing context containers in C's node tree. // FIXME: NOTE: The sort order specified above is missing here! - NonnullRefPtrVector docs = documents_in_this_event_loop(); + Vector> docs = documents_in_this_event_loop(); auto for_each_fully_active_document_in_docs = [&](auto&& callback) { for (auto& document : docs) { - if (document.is_fully_active()) - callback(document); + if (document->is_fully_active()) + callback(*document); } }; @@ -215,7 +215,7 @@ void EventLoop::process() // 3. For each win of the same-loop windows for this event loop, // perform the start an idle period algorithm for win with computeDeadline. [REQUESTIDLECALLBACK] for (auto& win : same_loop_windows()) - win.start_an_idle_period(); + win->start_an_idle_period(); } // FIXME: 14. If this is a worker event loop, then: @@ -248,8 +248,8 @@ void queue_global_task(HTML::Task::Source source, JS::Object& global_object, Fun // 2. Let document be global's associated Document, if global is a Window object; otherwise null. DOM::Document* document { nullptr }; - if (is(global_object)) { - auto& window_object = verify_cast(global_object); + if (is(global_object)) { + auto& window_object = verify_cast(global_object); document = &window_object.impl().associated_document(); } @@ -320,12 +320,12 @@ void EventLoop::perform_a_microtask_checkpoint() m_performing_a_microtask_checkpoint = false; } -NonnullRefPtrVector EventLoop::documents_in_this_event_loop() const +Vector> EventLoop::documents_in_this_event_loop() const { - NonnullRefPtrVector documents; + Vector> documents; for (auto& document : m_documents) { VERIFY(document); - documents.append(*document); + documents.append(JS::make_handle(*document.ptr())); } return documents; } @@ -368,11 +368,11 @@ void EventLoop::unregister_environment_settings_object(Badge EventLoop::same_loop_windows() const +Vector> EventLoop::same_loop_windows() const { - NonnullRefPtrVector windows; + Vector> windows; for (auto& document : documents_in_this_event_loop()) - windows.append(document.window()); + windows.append(JS::make_handle(document->window())); return windows; } @@ -394,7 +394,7 @@ double EventLoop::compute_deadline() const // 1. If windowInSameLoop's map of animation frame callbacks is not empty, // or if the user agent believes that the windowInSameLoop might have pending rendering updates, // set hasPendingRenders to true. - if (window.has_animation_frame_callbacks()) + if (window->has_animation_frame_callbacks()) has_pending_renders = true; // FIXME: 2. Let timerCallbackEstimates be the result of getting the values of windowInSameLoop's map of active timers. // FIXME: 3. For each timeoutDeadline of timerCallbackEstimates, if timeoutDeadline is less than deadline, set deadline to timeoutDeadline. diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h index fbe0ec929d9c1b06738d31a97bf0caec981a7ba3..61685ae6d6dd6c0c8905fdc20b37f242ec2c9d73 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h @@ -53,9 +53,9 @@ public: void register_document(Badge, DOM::Document&); void unregister_document(Badge, DOM::Document&); - NonnullRefPtrVector documents_in_this_event_loop() const; + Vector> documents_in_this_event_loop() const; - NonnullRefPtrVector same_loop_windows() const; + Vector> same_loop_windows() const; void push_onto_backup_incumbent_settings_object_stack(Badge, EnvironmentSettingsObject& environment_settings_object); void pop_backup_incumbent_settings_object_stack(Badge); diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp index 4e9a49b385fa94664710b1fffb9c22feb4e0df7f..600b76fe6ac601b3edff4162adf90e70f98a171d 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp @@ -12,7 +12,7 @@ namespace Web::HTML { Task::Task(Source source, DOM::Document* document, Function steps) : m_source(source) , m_steps(move(steps)) - , m_document(document) + , m_document(JS::make_handle(document)) { } @@ -27,7 +27,17 @@ void Task::execute() bool Task::is_runnable() const { // A task is runnable if its document is either null or fully active. - return !m_document || m_document->is_fully_active(); + return !m_document.ptr() || m_document->is_fully_active(); +} + +DOM::Document* Task::document() +{ + return m_document.ptr(); +} + +DOM::Document const* Task::document() const +{ + return m_document.ptr(); } } diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h index 22aaa8c10a941cf52a0d702c3ea0f68e2d0c77e4..46de9950699391fde48268adc274052a0b10054e 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -38,8 +39,8 @@ public: Source source() const { return m_source; } void execute(); - DOM::Document* document() { return m_document; } - DOM::Document const* document() const { return m_document; } + DOM::Document* document(); + DOM::Document const* document() const; bool is_runnable() const; @@ -48,7 +49,7 @@ private: Source m_source { Source::Unspecified }; Function m_steps; - RefPtr m_document; + JS::Handle m_document; }; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp index 3b2533fd13695db45480ae67107bd95e91873428..8c19a47fab4c05c691cdad7547fba2b35f8eb587 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp @@ -4,13 +4,17 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLAnchorElement::HTMLAnchorElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLAnchorElement")); + activation_behavior = [this](auto const& event) { run_activation_behavior(event); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h index a936e7c02761a7b3b48b7922b84452962d8e4d74..1b1aad0536b73ce0097f6f71f7eabd009cdcf911 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h @@ -14,10 +14,9 @@ namespace Web::HTML { class HTMLAnchorElement final : public HTMLElement , public HTMLHyperlinkElementUtils { -public: - using WrapperType = Bindings::HTMLAnchorElementWrapper; + WEB_PLATFORM_OBJECT(HTMLAnchorElement, HTMLElement); - HTMLAnchorElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLAnchorElement() override; String target() const { return attribute(HTML::AttributeNames::target); } @@ -30,6 +29,8 @@ public: virtual bool is_html_anchor_element() const override { return true; } private: + HTMLAnchorElement(DOM::Document&, DOM::QualifiedName); + void run_activation_behavior(Web::DOM::Event const&); // ^DOM::Element @@ -54,3 +55,5 @@ namespace Web::DOM { template<> inline bool Node::fast_is() const { return is_html_anchor_element(); } } + +WRAPPER_HACK(HTMLAnchorElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp index ea9b6ff47d4f528812a93428fa3e012dd67d928e..c941ef98bc95e7eb88ff3c9a36646453edefe1a5 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLAreaElement::HTMLAreaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLAreaElement")); } HTMLAreaElement::~HTMLAreaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h index fecfb33af8a72b2bafdcfb6f0df8914e4bc904c8..170524ce7a8150534bb0dd88bee2008d61afe022 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h @@ -15,13 +15,14 @@ namespace Web::HTML { class HTMLAreaElement final : public HTMLElement , public HTMLHyperlinkElementUtils { -public: - using WrapperType = Bindings::HTMLAreaElementWrapper; + WEB_PLATFORM_OBJECT(HTMLAreaElement, HTMLElement); - HTMLAreaElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLAreaElement() override; private: + HTMLAreaElement(DOM::Document&, DOM::QualifiedName); + // ^DOM::Element virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -39,3 +40,5 @@ private: }; } + +WRAPPER_HACK(HTMLAreaElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.cpp index 1492fe4288e73cefd4b71f6edc2e316a7fc04746..97befd800fc4928e1da4e55630c79f730b8ca318 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLAudioElement::HTMLAudioElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLMediaElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLAudioElement")); } HTMLAudioElement::~HTMLAudioElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h index 498d43cdcf5cd4963db1b8f49cea18148f7388dd..4820124a07651bcff5928b405cd290b03c947fd7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLAudioElement final : public HTMLMediaElement { + WEB_PLATFORM_OBJECT(HTMLAudioElement, HTMLMediaElement); + public: - using WrapperType = Bindings::HTMLAudioElementWrapper; + virtual ~HTMLAudioElement() override; +private: HTMLAudioElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLAudioElement() override; }; } + +WRAPPER_HACK(HTMLAudioElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp index d83f910fa131db101f428ca3588f32af87d27b34..9cf419290aede9743dccce5bea797c9d2eed911d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -13,6 +14,7 @@ namespace Web::HTML { HTMLBRElement::HTMLBRElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLBRElement")); } HTMLBRElement::~HTMLBRElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h index 0c8b911158c6b8f4697cbf1f60e42532d5d0b521..d44f986c5af76a761944e080e414e8ff83d71f1f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h @@ -11,13 +11,17 @@ namespace Web::HTML { class HTMLBRElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLBRElementWrapper; + WEB_PLATFORM_OBJECT(HTMLBRElement, HTMLElement); - HTMLBRElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLBRElement() override; virtual RefPtr create_layout_node(NonnullRefPtr) override; + +private: + HTMLBRElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLBRElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp index afb6d0e29268216e0401595d2f61c71a2ac7fc63..66f3b44bed517334ea43b80d675b614ad54efd85 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include @@ -12,6 +13,7 @@ namespace Web::HTML { HTMLBaseElement::HTMLBaseElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLBaseElement")); } HTMLBaseElement::~HTMLBaseElement() = default; @@ -25,7 +27,7 @@ void HTMLBaseElement::inserted() // NOTE: inserted() is called after this element has been inserted into the document. auto first_base_element_with_href_in_document = document().first_base_element_with_href_in_tree_order(); - if (first_base_element_with_href_in_document == this) + if (first_base_element_with_href_in_document.ptr() == this) set_the_frozen_base_url(); } @@ -39,7 +41,7 @@ void HTMLBaseElement::parse_attribute(FlyString const& name, String const& value return; auto first_base_element_with_href_in_document = document().first_base_element_with_href_in_tree_order(); - if (first_base_element_with_href_in_document == this) + if (first_base_element_with_href_in_document.ptr() == this) set_the_frozen_base_url(); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h index 0c904246cb18917cbada7506cba61042a3cf535e..f32b9f5b6b3013c450e24f577df9c75200879f9b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h @@ -11,10 +11,9 @@ namespace Web::HTML { class HTMLBaseElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLBaseElementWrapper; + WEB_PLATFORM_OBJECT(HTMLBaseElement, HTMLElement); - HTMLBaseElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLBaseElement() override; String href() const; @@ -26,6 +25,8 @@ public: virtual void parse_attribute(FlyString const& name, String const& value) override; private: + HTMLBaseElement(DOM::Document&, DOM::QualifiedName); + virtual bool is_html_base_element() const override { return true; } // https://html.spec.whatwg.org/multipage/semantics.html#frozen-base-url @@ -41,3 +42,5 @@ namespace Web::DOM { template<> inline bool Node::fast_is() const { return is_html_base_element(); } } + +WRAPPER_HACK(HTMLBaseElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h index 1a4cf3d456c07cf5edd8c25b977d09e78db8fcd2..39bb55d61149cc17e812b9f2ebf55769b1f8f55c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h @@ -12,14 +12,19 @@ namespace Web::HTML { class HTMLBlinkElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLBlinkElement, HTMLElement); + public: - HTMLBlinkElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLBlinkElement() override; private: + HTMLBlinkElement(DOM::Document&, DOM::QualifiedName); + void blink(); NonnullRefPtr m_timer; }; } + +WRAPPER_HACK(HTMLBlinkElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp index 5d2bc8959d66f6351cac7fd1eb6c76aa51c3f87d..17b4bc7a7685148dd935bf24137360ebacc2c813 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -15,6 +16,7 @@ namespace Web::HTML { HTMLBodyElement::HTMLBodyElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLBodyElement")); } HTMLBodyElement::~HTMLBodyElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h index e916ecad46ed5354c2582cac3f650d06b6b9d21b..302fbe58a490e70e1d27f94a939d5eae3965681b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h @@ -14,16 +14,17 @@ namespace Web::HTML { class HTMLBodyElement final : public HTMLElement , public WindowEventHandlers { -public: - using WrapperType = Bindings::HTMLBodyElementWrapper; + WEB_PLATFORM_OBJECT(HTMLBodyElement, HTMLElement); - HTMLBodyElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLBodyElement() override; virtual void parse_attribute(FlyString const&, String const&) override; virtual void apply_presentational_hints(CSS::StyleProperties&) const override; private: + HTMLBodyElement(DOM::Document&, DOM::QualifiedName); + // ^HTML::GlobalEventHandlers virtual EventTarget& global_event_handlers_to_event_target(FlyString const& event_name) override; @@ -34,3 +35,5 @@ private: }; } + +WRAPPER_HACK(HTMLBodyElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp index 419f4a607c28c061f5451404b975deff65e15b30..e8c9399a46af2c499219ca75a0fa11ab22af01cb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -13,6 +14,8 @@ namespace Web::HTML { HTMLButtonElement::HTMLButtonElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLButtonElement")); + // https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour activation_behavior = [this](auto&) { // 1. If element is disabled, then return. diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h index 3c084198565a964bae6e4e277701a5919788943a..6ca9e78b1517c58fd91b0a8301ed4a4c82dd4ee9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h @@ -19,12 +19,10 @@ namespace Web::HTML { class HTMLButtonElement final : public HTMLElement , public FormAssociatedElement { + WEB_PLATFORM_OBJECT(HTMLButtonElement, HTMLElement); FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLButtonElement) public: - using WrapperType = Bindings::HTMLButtonElementWrapper; - - HTMLButtonElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLButtonElement() override; enum class TypeAttributeState { @@ -54,6 +52,11 @@ public: // ^HTMLElement // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return true; } + +private: + HTMLButtonElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLButtonElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h index 8da131068d13b9ae14dcfc153eeb8f58c78b46cf..79b9924935b039d7314ff9b86f34e76b0a024a30 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h @@ -14,11 +14,11 @@ namespace Web::HTML { class HTMLCanvasElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLCanvasElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLCanvasElementWrapper; using RenderingContext = Variant, NonnullRefPtr, Empty>; - HTMLCanvasElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLCanvasElement() override; Gfx::Bitmap const* bitmap() const { return m_bitmap; } @@ -38,6 +38,8 @@ public: void present(); private: + HTMLCanvasElement(DOM::Document&, DOM::QualifiedName); + virtual RefPtr create_layout_node(NonnullRefPtr) override; enum class HasOrCreatedContext { @@ -54,3 +56,5 @@ private: }; } + +WRAPPER_HACK(HTMLCanvasElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDListElement.cpp index b44d558d8fdb6bc6d43349e79080fca3a052e5bd..e280e16342d95f6447a59c5f693e2bcd52d498d6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDListElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLDListElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLDListElement::HTMLDListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLDListElement")); } HTMLDListElement::~HTMLDListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h index 3664d3d32a7d7fbe932cdf05f4d593e3e95520cc..d2a3d975e94a0c8b750df85769c1ccbfefcfc8bc 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDListElementWrapper; + virtual ~HTMLDListElement() override; +private: HTMLDListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDListElement() override; }; } + +WRAPPER_HACK(HTMLDListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp index 39f81e6e2c2b8c2959ada1d84bf017f04bf994af..4740335f44a55ceaaf27ee565202841bd8a929f7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLDataElement::HTMLDataElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLDataElement")); } HTMLDataElement::~HTMLDataElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h index 3270881f21d30339ce7411132b1fcaf97722f10b..7ad0fec7fd575de5a29faa799227297c210de893 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDataElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDataElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDataElementWrapper; + virtual ~HTMLDataElement() override; +private: HTMLDataElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDataElement() override; }; } + +WRAPPER_HACK(HTMLDataElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp index c12efcd6a220c8df89aeabbb6d9299e1773e1c6f..b3866d30fb849f642ee411babf92432852136575 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLDataListElement::HTMLDataListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLDataListElement")); } HTMLDataListElement::~HTMLDataListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h index d7af3b3141b95350493194acdbfdf58ed8121818..26e96a83df549818d608c4f989a34b3745ca7107 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDataListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDataListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDataListElementWrapper; + virtual ~HTMLDataListElement() override; +private: HTMLDataListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDataListElement() override; }; } + +WRAPPER_HACK(HTMLDataListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp index ce365af09815f19b76c9154a1538534d76ca02c7..f2d6ac5a777fc071e940dd990f680a6ec90a0cdb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLDetailsElement::HTMLDetailsElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLDetailsElement")); } HTMLDetailsElement::~HTMLDetailsElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h index 9929e1e712de35dcd31b677861a826a8eee80dee..499e9d03be3a90c2adbd1fdf0cd1201c0a4a9e2b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDetailsElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDetailsElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDetailsElementWrapper; + virtual ~HTMLDetailsElement() override; +private: HTMLDetailsElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDetailsElement() override; }; } + +WRAPPER_HACK(HTMLDetailsElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp index 5885e8ef082135f107bbe6d581a9aa85faf98674..9aa1666f03fff82538280a385c4ec0b4dc5b13a0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLDialogElement::HTMLDialogElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLDialogElement")); } HTMLDialogElement::~HTMLDialogElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h index 8684fb8ca6be927aced58d26328155fa6c393e1f..ad522374f61cafca37cd2cdc6ca0280eee6503ef 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDialogElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDialogElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDialogElementWrapper; + virtual ~HTMLDialogElement() override; +private: HTMLDialogElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDialogElement() override; }; } + +WRAPPER_HACK(HTMLDialogElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp index c75726db6d30b7c089ae892952f12196927547c7..743a234ba63bdc6ae4245d8ef19004ab262e9547 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLDirectoryElement::HTMLDirectoryElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLDirectoryElement")); } HTMLDirectoryElement::~HTMLDirectoryElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h index 460415684d04b56121bb7c4b5f82b86bd313eab1..7fac25e12c74606179296ab715d141bd9bfb1793 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h @@ -12,11 +12,15 @@ namespace Web::HTML { // NOTE: This element is marked as obsolete, but is still listed as required by the specification. class HTMLDirectoryElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDirectoryElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDirectoryElementWrapper; + virtual ~HTMLDirectoryElement() override; +private: HTMLDirectoryElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDirectoryElement() override; }; } + +WRAPPER_HACK(HTMLDirectoryElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp index 74f614366511832f4a5f3a9bda9b7720f85c64a7..22bc02ebc5d145119333a5b6c87f647276e12387 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLDivElement::HTMLDivElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLDivElement")); } HTMLDivElement::~HTMLDivElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h index 01a28bf2d37384e05603853733c158583b7411f8..76e154560a88d66aa915d6b31a008ae692388322 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDivElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDivElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDivElementWrapper; + virtual ~HTMLDivElement() override; +private: HTMLDivElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDivElement() override; }; } + +WRAPPER_HACK(HTMLDivElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index 592f354d46bc6c4e6a87a897453574485600997a..05350872c728954eeaa7cc8095e00e8eb24f3a5f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -30,12 +31,19 @@ namespace Web::HTML { HTMLElement::HTMLElement(DOM::Document& document, DOM::QualifiedName qualified_name) : Element(document, move(qualified_name)) - , m_dataset(JS::make_handle(DOMStringMap::create(*this))) + , m_dataset(DOMStringMap::create(*this)) { + set_prototype(&window().ensure_web_prototype("HTMLElement")); } HTMLElement::~HTMLElement() = default; +void HTMLElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_dataset.ptr()); +} + HTMLElement::ContentEditableState HTMLElement::content_editable_state() const { auto contenteditable = attribute(HTML::AttributeNames::contenteditable); @@ -200,7 +208,7 @@ void HTMLElement::parse_attribute(FlyString const& name, String const& value) } // https://html.spec.whatwg.org/multipage/interaction.html#focus-update-steps -static void run_focus_update_steps(NonnullRefPtrVector old_chain, NonnullRefPtrVector new_chain, DOM::Node& new_focus_target) +static void run_focus_update_steps(Vector> old_chain, Vector> new_chain, DOM::Node& new_focus_target) { // 1. If the last entry in old chain and the last entry in new chain are the same, // pop the last entry from old chain and the last entry from new chain and redo this step. @@ -221,33 +229,33 @@ static void run_focus_update_steps(NonnullRefPtrVector old_chain, Non // then fire an event named change at the element, // with the bubbles attribute initialized to true. - RefPtr blur_event_target; - if (is(entry)) { + JS::GCPtr blur_event_target; + if (is(*entry)) { // 2. If entry is an element, let blur event target be entry. - blur_event_target = entry; - } else if (is(entry)) { + blur_event_target = entry.ptr(); + } else if (is(*entry)) { // If entry is a Document object, let blur event target be that Document object's relevant global object. - blur_event_target = static_cast(entry).window(); + blur_event_target = &static_cast(*entry).window(); } // 3. If entry is the last entry in old chain, and entry is an Element, // and the last entry in new chain is also an Element, // then let related blur target be the last entry in new chain. // Otherwise, let related blur target be null. - RefPtr related_blur_target; + JS::GCPtr related_blur_target; if (!old_chain.is_empty() && &entry == &old_chain.last() - && is(entry) + && is(*entry) && !new_chain.is_empty() - && is(new_chain.last())) { - related_blur_target = new_chain.last(); + && is(*new_chain.last())) { + related_blur_target = new_chain.last().ptr(); } // 4. If blur event target is not null, fire a focus event named blur at blur event target, // with related blur target as the related target. if (blur_event_target) { // FIXME: Implement the "fire a focus event" spec operation. - auto blur_event = UIEvents::FocusEvent::create(verify_cast(*blur_event_target).document().preferred_window_object(), HTML::EventNames::blur); + auto blur_event = UIEvents::FocusEvent::create(verify_cast(*blur_event_target).document().window(), HTML::EventNames::blur); blur_event->set_related_target(related_blur_target); blur_event_target->dispatch_event(*blur_event); } @@ -261,50 +269,50 @@ static void run_focus_update_steps(NonnullRefPtrVector old_chain, Non for (auto& entry : new_chain.in_reverse()) { // 1. If entry is a focusable area: designate entry as the focused area of the document. // FIXME: This isn't entirely right. - if (is(entry)) - entry.document().set_focused_element(&static_cast(entry)); + if (is(*entry)) + entry->document().set_focused_element(&static_cast(*entry)); - RefPtr focus_event_target; - if (is(entry)) { + JS::GCPtr focus_event_target; + if (is(*entry)) { // 2. If entry is an element, let focus event target be entry. - focus_event_target = entry; - } else if (is(entry)) { + focus_event_target = entry.ptr(); + } else if (is(*entry)) { // If entry is a Document object, let focus event target be that Document object's relevant global object. - focus_event_target = static_cast(entry).window(); + focus_event_target = &static_cast(*entry).window(); } // 3. If entry is the last entry in new chain, and entry is an Element, // and the last entry in old chain is also an Element, // then let related focus target be the last entry in old chain. // Otherwise, let related focus target be null. - RefPtr related_focus_target; + JS::GCPtr related_focus_target; if (!new_chain.is_empty() && &entry == &new_chain.last() - && is(entry) + && is(*entry) && !old_chain.is_empty() - && is(old_chain.last())) { - related_focus_target = old_chain.last(); + && is(*old_chain.last())) { + related_focus_target = old_chain.last().ptr(); } // 4. If focus event target is not null, fire a focus event named focus at focus event target, // with related focus target as the related target. if (focus_event_target) { // FIXME: Implement the "fire a focus event" spec operation. - auto focus_event = UIEvents::FocusEvent::create(verify_cast(*focus_event_target).document().preferred_window_object(), HTML::EventNames::focus); + auto focus_event = UIEvents::FocusEvent::create(verify_cast(*focus_event_target).document().window(), HTML::EventNames::focus); focus_event->set_related_target(related_focus_target); focus_event_target->dispatch_event(*focus_event); } } } // https://html.spec.whatwg.org/multipage/interaction.html#focus-chain -static NonnullRefPtrVector focus_chain(DOM::Node* subject) +static Vector> focus_chain(DOM::Node* subject) { // FIXME: Move this somewhere more spec-friendly. if (!subject) return {}; // 1. Let output be an empty list. - NonnullRefPtrVector output; + Vector> output; // 2. Let currentObject be subject. auto* current_object = subject; @@ -312,7 +320,7 @@ static NonnullRefPtrVector focus_chain(DOM::Node* subject) // 3. While true: while (true) { // 1. Append currentObject to output. - output.append(*current_object); + output.append(JS::make_handle(*current_object)); // FIXME: 2. If currentObject is an area element's shape, then append that area element to output. @@ -369,7 +377,7 @@ static void run_focusing_steps(DOM::Node* new_focus_target, DOM::Node* fallback_ if (!new_focus_target->document().browsing_context()) return; auto& top_level_browsing_context = new_focus_target->document().browsing_context()->top_level_browsing_context(); - if (new_focus_target == top_level_browsing_context.currently_focused_area()) + if (new_focus_target == top_level_browsing_context.currently_focused_area().ptr()) return; // 6. Let old chain be the current focus chain of the top-level browsing context in which @@ -411,7 +419,7 @@ bool HTMLElement::fire_a_synthetic_pointer_event(FlyString const& type, DOM::Ele // 1. Let event be the result of creating an event using PointerEvent. // 2. Initialize event's type attribute to e. // FIXME: Actually create a PointerEvent! - auto event = UIEvents::MouseEvent::create(document().preferred_window_object(), type); + auto event = UIEvents::MouseEvent::create(document().window(), type); // 3. Initialize event's bubbles and cancelable attributes to true. event->set_bubbles(true); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.h b/Userland/Libraries/LibWeb/HTML/HTMLElement.h index 1c0376668e0ccefffb70efd1790f1bc944911bdc..a40cd1cfd18c71edff6e9c19a44fe79449c805e7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.h @@ -16,10 +16,9 @@ namespace Web::HTML { class HTMLElement : public DOM::Element , public HTML::GlobalEventHandlers { -public: - using WrapperType = Bindings::HTMLElementWrapper; + WEB_PLATFORM_OBJECT(HTMLElement, DOM::Element); - HTMLElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLElement() override; String title() const { return attribute(HTML::AttributeNames::title); } @@ -38,8 +37,8 @@ public: bool cannot_navigate() const; - DOMStringMap* dataset() { return m_dataset.cell(); } - DOMStringMap const* dataset() const { return m_dataset.cell(); } + DOMStringMap* dataset() { return m_dataset.ptr(); } + DOMStringMap const* dataset() const { return m_dataset.ptr(); } void focus(); @@ -51,8 +50,12 @@ public: virtual bool is_labelable() const { return false; } protected: + HTMLElement(DOM::Document&, DOM::QualifiedName); + virtual void parse_attribute(FlyString const& name, String const& value) override; + virtual void visit_edges(Cell::Visitor&) override; + private: virtual bool is_html_element() const final { return true; } @@ -66,7 +69,7 @@ private: }; ContentEditableState content_editable_state() const; - JS::Handle m_dataset; + JS::NonnullGCPtr m_dataset; // https://html.spec.whatwg.org/multipage/interaction.html#locked-for-focus bool m_locked_for_focus { false }; @@ -81,3 +84,5 @@ namespace Web::DOM { template<> inline bool Node::fast_is() const { return is_html_element(); } } + +WRAPPER_HACK(HTMLElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp index 75f9cd9b98408f1e1d67e4efdf1626780c309302..d6d036c1b8565e2e0f213485a4fab7026f898b50 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLEmbedElement::HTMLEmbedElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLEmbedElement")); } HTMLEmbedElement::~HTMLEmbedElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h b/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h index 4c68838800d6f343acb70e633ad12a819a181cd0..f69e14744a71271c015cb00a752c27c3a49a74f9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLEmbedElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLEmbedElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLEmbedElementWrapper; + virtual ~HTMLEmbedElement() override; +private: HTMLEmbedElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLEmbedElement() override; }; } + +WRAPPER_HACK(HTMLEmbedElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp index 2d3db560f13c7ceea7ebc14537454f1addfa23ab..fe2f968a66e9846e6d4acf225f3ed7859cb9e646 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLFieldSetElement::HTMLFieldSetElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLFieldSetElement")); } HTMLFieldSetElement::~HTMLFieldSetElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h index 1cb3a6c06c48d00524c1df3784a392b10d8624fe..146904a7de3d369aacf2bef0b28e2ea5dc4a9518 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h @@ -14,12 +14,10 @@ namespace Web::HTML { class HTMLFieldSetElement final : public HTMLElement , public FormAssociatedElement { + WEB_PLATFORM_OBJECT(HTMLFieldSetElement, HTMLElement); FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLFieldSetElement) public: - using WrapperType = Bindings::HTMLFieldSetElementWrapper; - - HTMLFieldSetElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLFieldSetElement() override; String const& type() const @@ -34,6 +32,11 @@ public: // https://html.spec.whatwg.org/multipage/forms.html#category-autocapitalize virtual bool is_auto_capitalize_inheriting() const override { return true; } + +private: + HTMLFieldSetElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLFieldSetElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFontElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFontElement.cpp index a0c139863cb4877847d5a9bc75f6bd424deaadbe..f969f03658448188889a02ccbb5190e106be370f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFontElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFontElement.cpp @@ -4,15 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include +#include namespace Web::HTML { HTMLFontElement::HTMLFontElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLFontElement")); } HTMLFontElement::~HTMLFontElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFontElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFontElement.h index 401019fde1d3f6690c6d256fc671314bf90b9bd7..7b4e2e7f21bd8ee86debf87d16786355722c7d47 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFontElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFontElement.h @@ -11,13 +11,17 @@ namespace Web::HTML { class HTMLFontElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLFontElementWrapper; + WEB_PLATFORM_OBJECT(HTMLFontElement, HTMLElement); - HTMLFontElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLFontElement() override; virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + +private: + HTMLFontElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLFontElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp index 6f1b96b9eacc00358420bde2c858a58caa52e439..b9ea743329d45405a9aff1788210f99dbe746cd8 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -25,11 +26,19 @@ namespace Web::HTML { HTMLFormElement::HTMLFormElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLFormElement")); } HTMLFormElement::~HTMLFormElement() = default; -void HTMLFormElement::submit_form(RefPtr submitter, bool from_submit_binding) +void HTMLFormElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + for (auto& element : m_associated_elements) + visitor.visit(element.ptr()); +} + +void HTMLFormElement::submit_form(JS::GCPtr submitter, bool from_submit_binding) { if (cannot_navigate()) return; @@ -58,14 +67,14 @@ void HTMLFormElement::submit_form(RefPtr submitter, bool from_submi // FIXME: If the submitter element's no-validate state is false... - RefPtr submitter_button; + JS::GCPtr submitter_button; if (submitter != this) submitter_button = submitter; SubmitEventInit event_init {}; event_init.submitter = submitter_button; - auto submit_event = SubmitEvent::create(document().preferred_window_object(), EventNames::submit, event_init); + auto submit_event = SubmitEvent::create(document().window(), EventNames::submit, event_init); submit_event->set_bubbles(true); submit_event->set_cancelable(true); bool continue_ = dispatch_event(*submit_event); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h index cd0a192a79be2af03877ff5c7a1d846f0c421412..d548bf41e982644953711d5cda9f02d7ce50abe3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h @@ -12,16 +12,15 @@ namespace Web::HTML { class HTMLFormElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLFormElementWrapper; + WEB_PLATFORM_OBJECT(HTMLFormElement, HTMLElement); - HTMLFormElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLFormElement() override; String action() const; String method() const { return attribute(HTML::AttributeNames::method); } - void submit_form(RefPtr submitter, bool from_submit_binding = false); + void submit_form(JS::GCPtr submitter, bool from_submit_binding = false); // NOTE: This is for the JS bindings. Use submit_form instead. void submit(); @@ -33,9 +32,15 @@ public: unsigned length() const; private: + HTMLFormElement(DOM::Document&, DOM::QualifiedName); + + virtual void visit_edges(Cell::Visitor&) override; + bool m_firing_submission_events { false }; - Vector> m_associated_elements; + Vector> m_associated_elements; }; } + +WRAPPER_HACK(HTMLFormElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp index 6ac1110c6b00284175d56c9f58cf1b6a2a1ba960..c5ae687c058871631ee257eb2c6b84da57bbd12e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLFrameElement::HTMLFrameElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLFrameElement")); } HTMLFrameElement::~HTMLFrameElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h index 39087a69698b274ec97ec4405cf06d6174798901..505b112213845a18393698c1e7935878865d1b7a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h @@ -12,11 +12,15 @@ namespace Web::HTML { // NOTE: This element is marked as obsolete, but is still listed as required by the specification. class HTMLFrameElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLFrameElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLFrameElementWrapper; + virtual ~HTMLFrameElement() override; +private: HTMLFrameElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLFrameElement() override; }; } + +WRAPPER_HACK(HTMLFrameElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp index bf7d86accda4e500a2f8cd36460bdc723fbdf1e7..52d06e95400da7195629a60bd72d5aaa447ae4b1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -13,6 +14,7 @@ namespace Web::HTML { HTMLFrameSetElement::HTMLFrameSetElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLFrameSetElement")); } HTMLFrameSetElement::~HTMLFrameSetElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h index 3a4088d9976eb37259c6a140cc9425646cf1edcb..8ff5a34c83e40aa592b136347de4a901b64b58ce 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h @@ -15,11 +15,13 @@ namespace Web::HTML { class HTMLFrameSetElement final : public HTMLElement , public WindowEventHandlers { + WEB_PLATFORM_OBJECT(HTMLFrameSetElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLFrameSetElementWrapper; + virtual ~HTMLFrameSetElement() override; +private: HTMLFrameSetElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLFrameSetElement() override; virtual void parse_attribute(FlyString const&, String const&) override; @@ -32,3 +34,5 @@ private: }; } + +WRAPPER_HACK(HTMLFrameSetElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.cpp index 170973715a228dc79ea1b13a5b8ff44b5ce6f979..89d19cb1e5b2c9b88a0ed51a4095ea3e59d42681 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLHRElement::HTMLHRElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLHRElement")); } HTMLHRElement::~HTMLHRElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h index 69f5649ea91eab2f1059d77cdd3de3610d24e3cf..21accb7746accba49211471425a0d55efaa49995 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLHRElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLHRElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLHRElementWrapper; + virtual ~HTMLHRElement() override; +private: HTMLHRElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLHRElement() override; }; } + +WRAPPER_HACK(HTMLHRElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp index e4533b2158122ce547e1a28d39bac66c2d3c869e..fa351267972ad8ee4914b89f4b4ea4158f059a51 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLHeadElement::HTMLHeadElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLHeadElement")); } HTMLHeadElement::~HTMLHeadElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h index e2faf9a5c65c9668537df6a057dc2ef7e5139e2e..9996aa230bdc7bcf0feba9038625f44616449838 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLHeadElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLHeadElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLHeadElementWrapper; + virtual ~HTMLHeadElement() override; +private: HTMLHeadElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLHeadElement() override; }; } + +WRAPPER_HACK(HTMLHeadElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp index 10b1c9b7d664b58485a5576a1433df948abaf732..28b276f17ad8f11bf1dec2ba6cc1a564638a143f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLHeadingElement::HTMLHeadingElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLHeadingElement")); } HTMLHeadingElement::~HTMLHeadingElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h index d5c7644a7987fd1135b1e1d542291e6202d52ae1..5deffd89854efd7bc0ef503a3591b0d06dcdcc6c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLHeadingElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLHeadingElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLHeadingElementWrapper; + virtual ~HTMLHeadingElement() override; +private: HTMLHeadingElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLHeadingElement() override; }; } + +WRAPPER_HACK(HTMLHeadingElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp index 179c4d0b9b69f7a9ceb73c88835132e44982fc62..90fe7f8c52f6a523404ad4702a87dd1d769754f1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLHtmlElement::HTMLHtmlElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLHtmlElement")); } HTMLHtmlElement::~HTMLHtmlElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h index 1222355040d99103f5e3c2714ba498ab747f717a..0f8c6b3c5fd23e8c36a6b0ae51792b70c3874593 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h @@ -11,15 +11,16 @@ namespace Web::HTML { class HTMLHtmlElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLHtmlElementWrapper; + WEB_PLATFORM_OBJECT(HTMLHtmlElement, HTMLElement); - HTMLHtmlElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLHtmlElement() override; bool should_use_body_background_properties() const; private: + HTMLHtmlElement(DOM::Document&, DOM::QualifiedName); + virtual bool is_html_html_element() const override { return true; } }; @@ -29,3 +30,5 @@ namespace Web::DOM { template<> inline bool Node::fast_is() const { return is_html_html_element(); } } + +WRAPPER_HACK(HTMLHtmlElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp index 83b6fb3c45bd36f87c22b2190e906f392ee3c973..2ee367455e55252761319e1261a16a955d217dfd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -16,6 +17,7 @@ namespace Web::HTML { HTMLIFrameElement::HTMLIFrameElement(DOM::Document& document, DOM::QualifiedName qualified_name) : BrowsingContextContainer(document, move(qualified_name)) { + set_prototype(&document.window().ensure_web_prototype("HTMLIFrameElement")); } HTMLIFrameElement::~HTMLIFrameElement() = default; @@ -92,7 +94,7 @@ void run_iframe_load_event_steps(HTML::HTMLIFrameElement& element) // FIXME: 4. Set childDocument's iframe load in progress flag. // 5. Fire an event named load at element. - element.dispatch_event(*DOM::Event::create(element.document().preferred_window_object(), HTML::EventNames::load)); + element.dispatch_event(*DOM::Event::create(element.document().window(), HTML::EventNames::load)); // FIXME: 6. Unset childDocument's iframe load in progress flag. } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h index 34149e50ed48e429a36c06a8c2f9a20765c25a55..f9728145e51ca29f2942670e5f1a2c13a9572100 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h @@ -11,15 +11,16 @@ namespace Web::HTML { class HTMLIFrameElement final : public BrowsingContextContainer { -public: - using WrapperType = Bindings::HTMLIFrameElementWrapper; + WEB_PLATFORM_OBJECT(HTMLIFrameElement, BrowsingContextContainer); - HTMLIFrameElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLIFrameElement() override; virtual RefPtr create_layout_node(NonnullRefPtr) override; private: + HTMLIFrameElement(DOM::Document&, DOM::QualifiedName); + virtual void inserted() override; virtual void removed_from(Node*) override; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -30,3 +31,5 @@ private: void run_iframe_load_event_steps(HTML::HTMLIFrameElement&); } + +WRAPPER_HACK(HTMLIFrameElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 6a2ecb60f4c402714a3270446cf49047b8f93409..4e2d0d391178c4552fcf0cf85928b11b12cb3ad2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -22,11 +23,13 @@ HTMLImageElement::HTMLImageElement(DOM::Document& document, DOM::QualifiedName q : HTMLElement(document, move(qualified_name)) , m_image_loader(*this) { + set_prototype(&window().ensure_web_prototype("HTMLImageElement")); + m_image_loader.on_load = [this] { set_needs_style_update(true); this->document().set_needs_layout(); queue_an_element_task(HTML::Task::Source::DOMManipulation, [this] { - dispatch_event(*DOM::Event::create(this->document().preferred_window_object(), EventNames::load)); + dispatch_event(*DOM::Event::create(this->document().window(), EventNames::load)); }); }; @@ -35,7 +38,7 @@ HTMLImageElement::HTMLImageElement(DOM::Document& document, DOM::QualifiedName q set_needs_style_update(true); this->document().set_needs_layout(); queue_an_element_task(HTML::Task::Source::DOMManipulation, [this] { - dispatch_event(*DOM::Event::create(this->document().preferred_window_object(), EventNames::error)); + dispatch_event(*DOM::Event::create(this->document().window(), EventNames::error)); }); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h index 046a29fd6486954f08ca6e71feb31b37449d8ef9..88026331fdb51dbd8b8bf2debb0f351f20bbbdc4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h @@ -18,12 +18,10 @@ namespace Web::HTML { class HTMLImageElement final : public HTMLElement , public FormAssociatedElement { + WEB_PLATFORM_OBJECT(HTMLImageElement, HTMLElement); FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLImageElement) public: - using WrapperType = Bindings::HTMLImageElementWrapper; - - HTMLImageElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLImageElement() override; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -43,6 +41,8 @@ public: unsigned natural_height() const; private: + HTMLImageElement(DOM::Document&, DOM::QualifiedName); + virtual void apply_presentational_hints(CSS::StyleProperties&) const override; void animate(); @@ -53,3 +53,5 @@ private: }; } + +WRAPPER_HACK(HTMLImageElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 66557d5cae722304ed1c8a7a7e27447844cc2bce..4ca7cc2f057a88f9d79e5165d256ab1388eec3f4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -24,6 +25,8 @@ HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName q : HTMLElement(document, move(qualified_name)) , m_value(String::empty()) { + set_prototype(&window().ensure_web_prototype("HTMLInputElement")); + activation_behavior = [this](auto&) { // The activation behavior for input elements are these steps: @@ -36,6 +39,13 @@ HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName q HTMLInputElement::~HTMLInputElement() = default; +void HTMLInputElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_text_node.ptr()); + visitor.visit(m_legacy_pre_activation_behavior_checked_element_in_group.ptr()); +} + RefPtr HTMLInputElement::create_layout_node(NonnullRefPtr style) { if (type_state() == TypeAttributeState::Hidden) @@ -90,17 +100,17 @@ void HTMLInputElement::run_input_activation_behavior() return; // 2. Fire an event named input at the element with the bubbles and composed attributes initialized to true. - auto input_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::input); + auto input_event = DOM::Event::create(document().window(), HTML::EventNames::input); input_event->set_bubbles(true); input_event->set_composed(true); dispatch_event(*input_event); // 3. Fire an event named change at the element with the bubbles attribute initialized to true. - auto change_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::change); + auto change_event = DOM::Event::create(document().window(), HTML::EventNames::change); change_event->set_bubbles(true); dispatch_event(*change_event); } else if (type_state() == TypeAttributeState::SubmitButton) { - RefPtr form; + JS::GCPtr form; // 1. If the element does not have a form owner, then return. if (!(form = this->form())) return; @@ -112,7 +122,7 @@ void HTMLInputElement::run_input_activation_behavior() // 3. Submit the form owner from the element. form->submit_form(this); } else { - dispatch_event(*DOM::Event::create(document().preferred_window_object(), EventNames::change)); + dispatch_event(*DOM::Event::create(document().window(), EventNames::change)); } } @@ -125,13 +135,13 @@ void HTMLInputElement::did_edit_text_node(Badge) // NOTE: This is a bit ad-hoc, but basically implements part of "4.10.5.5 Common event behaviors" // https://html.spec.whatwg.org/multipage/input.html#common-input-element-events queue_an_element_task(HTML::Task::Source::UserInteraction, [this] { - auto input_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::input); + auto input_event = DOM::Event::create(document().window(), HTML::EventNames::input); input_event->set_bubbles(true); input_event->set_composed(true); dispatch_event(*input_event); // FIXME: This should only fire when the input is "committed", whatever that means. - auto change_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::change); + auto change_event = DOM::Event::create(document().window(), HTML::EventNames::change); change_event->set_bubbles(true); dispatch_event(*change_event); }); @@ -184,13 +194,13 @@ void HTMLInputElement::create_shadow_tree_if_needed() break; } - auto shadow_root = adopt_ref(*new DOM::ShadowRoot(document(), *this)); + auto* shadow_root = heap().allocate(realm(), document(), *this); auto initial_value = m_value; if (initial_value.is_null()) initial_value = String::empty(); auto element = document().create_element(HTML::TagNames::div).release_value(); element->set_attribute(HTML::AttributeNames::style, "white-space: pre; padding-top: 1px; padding-bottom: 1px; padding-left: 2px; padding-right: 2px"); - m_text_node = adopt_ref(*new DOM::Text(document(), initial_value)); + m_text_node = heap().allocate(realm(), document(), initial_value); m_text_node->set_always_editable(true); m_text_node->set_owner_input_element({}, *this); element->append_child(*m_text_node); @@ -348,7 +358,7 @@ void HTMLInputElement::legacy_pre_activation_behavior() document().for_each_in_inclusive_subtree_of_type([&](auto& element) { if (element.checked() && element.name() == name) { - m_legacy_pre_activation_behavior_checked_element_in_group = element; + m_legacy_pre_activation_behavior_checked_element_in_group = &element; return IterationDecision::Break; } return IterationDecision::Continue; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index 543295b653a1dd3d191b6ccf806f0d6c6ce7c730..4b7f3c18491b4bde28a735e1add159d7dcce1bcd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -40,12 +40,10 @@ namespace Web::HTML { class HTMLInputElement final : public HTMLElement , public FormAssociatedElement { + WEB_PLATFORM_OBJECT(HTMLInputElement, HTMLElement); FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLInputElement) public: - using WrapperType = Bindings::HTMLInputElementWrapper; - - HTMLInputElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLInputElement() override; virtual RefPtr create_layout_node(NonnullRefPtr) override; @@ -106,12 +104,16 @@ public: virtual bool is_labelable() const override { return type_state() != TypeAttributeState::Hidden; } private: + HTMLInputElement(DOM::Document&, DOM::QualifiedName); + // ^DOM::EventTarget virtual void did_receive_focus() override; virtual void legacy_pre_activation_behavior() override; virtual void legacy_cancelled_activation_behavior() override; virtual void legacy_cancelled_activation_behavior_was_not_called() override; + virtual void visit_edges(Cell::Visitor&) override; + static TypeAttributeState parse_type_attribute(StringView); void create_shadow_tree_if_needed(); void run_input_activation_behavior(); @@ -120,7 +122,7 @@ private: // https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm String value_sanitization_algorithm(String) const; - RefPtr m_text_node; + JS::GCPtr m_text_node; bool m_checked { false }; // https://html.spec.whatwg.org/multipage/input.html#concept-input-checked-dirty-flag @@ -131,10 +133,12 @@ private: // https://html.spec.whatwg.org/multipage/input.html#the-input-element:legacy-pre-activation-behavior bool m_before_legacy_pre_activation_behavior_checked { false }; - RefPtr m_legacy_pre_activation_behavior_checked_element_in_group; + JS::GCPtr m_legacy_pre_activation_behavior_checked_element_in_group; TypeAttributeState m_type { TypeAttributeState::Text }; String m_value; }; } + +WRAPPER_HACK(HTMLInputElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.cpp index 2c166fabd4de100642fd11d48377f8d0b91e3ca4..1c85241a0aa1b4f8d3373a2f0a93692791e58583 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLLIElement::HTMLLIElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLLIElement")); } HTMLLIElement::~HTMLLIElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h index 071f1f8927c5d06d6095db77150aaf86576f98f3..4eb8572ff178dd64f9d5b03fe60f8803261459b2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLLIElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLLIElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLLIElementWrapper; + virtual ~HTMLLIElement() override; +private: HTMLLIElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLLIElement() override; }; } + +WRAPPER_HACK(HTMLLIElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp index 71f73e2b4e43a56fb71dc3d215886435d2d555d4..31398d3c9025fcbc211550e9cedb841d63fecd84 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -13,6 +14,7 @@ namespace Web::HTML { HTMLLabelElement::HTMLLabelElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLLabelElement")); } HTMLLabelElement::~HTMLLabelElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h index cae5adb9ce2cc4b74ada5f3b45ea2639710940a4..2cc266cd866c94a60673d0a27b672fbf542432aa 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h @@ -11,15 +11,19 @@ namespace Web::HTML { class HTMLLabelElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLLabelElementWrapper; + WEB_PLATFORM_OBJECT(HTMLLabelElement, HTMLElement); - HTMLLabelElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLLabelElement() override; virtual RefPtr create_layout_node(NonnullRefPtr) override; String for_() const { return attribute(HTML::AttributeNames::for_); } + +private: + HTMLLabelElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLLabelElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.cpp index 48247dba260a0f4a66ff2aa94e725981b0b35ade..7cdaae7016201b6772671fb507b92a800333cdd7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLLegendElement::HTMLLegendElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLLegendElement")); } HTMLLegendElement::~HTMLLegendElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h index 5acdbec2d15989710e29197f9aff653609b6f417..aea891af7b65012135b3f41d80acb9cfd5f603b8 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLLegendElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLLegendElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLLegendElementWrapper; + virtual ~HTMLLegendElement() override; +private: HTMLLegendElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLLegendElement() override; }; } + +WRAPPER_HACK(HTMLLegendElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp index 345011dcc5b574f2567a0359182dfc2fbc63e8fe..c2365ab4298dde4f63e6079869cc4d0ee76926e6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ namespace Web::HTML { HTMLLinkElement::HTMLLinkElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLLinkElement")); } HTMLLinkElement::~HTMLLinkElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.h index 844bba4149bcd886249d4c70209df6deea627dee..ef8055adde5971f08277760bbe3654631c2bdafb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.h @@ -16,10 +16,9 @@ namespace Web::HTML { class HTMLLinkElement final : public HTMLElement , public ResourceClient { -public: - using WrapperType = Bindings::HTMLLinkElementWrapper; + WEB_PLATFORM_OBJECT(HTMLLinkElement, HTMLElement); - HTMLLinkElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLLinkElement() override; virtual void inserted() override; @@ -32,6 +31,8 @@ public: bool load_favicon_and_use_if_window_is_active(); private: + HTMLLinkElement(DOM::Document&, DOM::QualifiedName); + void parse_attribute(FlyString const&, String const&) override; // ^ResourceClient @@ -59,3 +60,5 @@ private: }; } + +WRAPPER_HACK(HTMLLinkElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMapElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMapElement.cpp index b8c68863f6439173c8901d9c8f34232fa5eec278..e02e7374f0d891ec4a4bbbe4224c08fe02f87462 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMapElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMapElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLMapElement::HTMLMapElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLMapElement")); } HTMLMapElement::~HTMLMapElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h index bf66b802399939135441d4cf07317ea54ae612ec..84dd4211acb8e791aa3ee45d28830b38d3d8fb39 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLMapElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLMapElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLMapElementWrapper; + virtual ~HTMLMapElement() override; +private: HTMLMapElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLMapElement() override; }; } + +WRAPPER_HACK(HTMLMapElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp index c70c667b12ccc9c4606c0268db5f4109553edf2b..9c9bebbb465b31722881577528a9850fabdc09db 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLMarqueeElement::HTMLMarqueeElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLMarqueeElement")); } HTMLMarqueeElement::~HTMLMarqueeElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.h index 556dfa1fae1b45850b9de3c85404c4b4db5745d0..9183ba73f783c6ce4c0eac119b41b372d598f310 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.h @@ -12,14 +12,16 @@ namespace Web::HTML { // NOTE: This element is marked as obsolete, but is still listed as required by the specification. class HTMLMarqueeElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLMarqueeElementWrapper; + WEB_PLATFORM_OBJECT(HTMLMarqueeElement, HTMLElement); - HTMLMarqueeElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLMarqueeElement() override; private: + HTMLMarqueeElement(DOM::Document&, DOM::QualifiedName); virtual void apply_presentational_hints(CSS::StyleProperties&) const override; }; } + +WRAPPER_HACK(HTMLMarqueeElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp index 545984dae14214e7f6036f955418bb368c9a2edb..2d53b2e716b23c1ddfe5aceff1d7f8a47c45ad29 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp @@ -4,14 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include +#include namespace Web::HTML { HTMLMediaElement::HTMLMediaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLMediaElement")); } HTMLMediaElement::~HTMLMediaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h index ed5bb41b5b419568a21e19350eee69aa172a84af..331a2f53c3cc268c0103b8b615de46f0d3506a70 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h @@ -11,13 +11,17 @@ namespace Web::HTML { class HTMLMediaElement : public HTMLElement { -public: - using WrapperType = Bindings::HTMLMediaElementWrapper; + WEB_PLATFORM_OBJECT(HTMLMediaElement, HTMLElement); - HTMLMediaElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLMediaElement() override; Bindings::CanPlayTypeResult can_play_type(String const& type) const; + +protected: + HTMLMediaElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLMediaElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.cpp index 5b8405ff90a063e54426ab08bbd798057eeba6c5..65528d30785d962a6693988f24ebac4395e03465 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLMenuElement::HTMLMenuElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLMenuElement")); } HTMLMenuElement::~HTMLMenuElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h index f05e3ab935a1a9e7f3c7d550649ccc4536194c67..f1ae4a7833dcf94583ce394c1bc7fcc614185fe9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLMenuElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLMenuElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLMenuElementWrapper; + virtual ~HTMLMenuElement() override; +private: HTMLMenuElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLMenuElement() override; }; } + +WRAPPER_HACK(HTMLMenuElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp index 6812c4602291a2485b42a03a862406207ce03f72..66eaf3cc03b95c704051a7ef0807b16324f0a14c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLMetaElement::HTMLMetaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLMetaElement")); } HTMLMetaElement::~HTMLMetaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h index 0e2a7e18838945522df74d6137ff6f0b60614acf..62ac9dcdf78671b5d0e75a578b68ad83ba2a1f4a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLMetaElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLMetaElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLMetaElementWrapper; + virtual ~HTMLMetaElement() override; +private: HTMLMetaElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLMetaElement() override; }; } + +WRAPPER_HACK(HTMLMetaElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp index 0341aac4bb12916f0fb20919817f3f9bcb510a09..6d33d2e4141ed3f51caa55cc791d48b31db797d1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLMeterElement::HTMLMeterElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLMeterElement")); } HTMLMeterElement::~HTMLMeterElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h index 7877ea7f58ee705e6f1687d4dd107611bd3ae6f5..28474b4234e44220fc4bc2f26f5dd05b69717778 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h @@ -12,15 +12,19 @@ namespace Web::HTML { class HTMLMeterElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLMeterElementWrapper; + WEB_PLATFORM_OBJECT(HTMLMeterElement, HTMLElement); - HTMLMeterElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLMeterElement() override; // ^HTMLElement // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return true; } + +private: + HTMLMeterElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLMeterElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp index 4201d8b316dbcd53b55abe6cb37da232775ae627..b4d7325868fa78ef9450909b5e7255d15ad1a51b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLModElement::HTMLModElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLModElement")); } HTMLModElement::~HTMLModElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLModElement.h b/Userland/Libraries/LibWeb/HTML/HTMLModElement.h index b8126fa1c14b4fb900d0b0767862543d30aa4e18..64044da14547a65bea809dfb3d57d1f12ccf2032 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLModElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLModElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLModElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLModElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLModElementWrapper; + virtual ~HTMLModElement() override; +private: HTMLModElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLModElement() override; }; } + +WRAPPER_HACK(HTMLModElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp index 90ddc29efc801291876a79a1910efd118f54b550..a397c00a57421019a29d56a54f7beb464e9610e6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLOListElement::HTMLOListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLOListElement")); } HTMLOListElement::~HTMLOListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h index 25eb96b4861c03a8a963e530bc9beb612575ecc4..a320b94fa2dea1ac31587ab35553a0593364c803 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLOListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLOListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLOListElementWrapper; + virtual ~HTMLOListElement() override; +private: HTMLOListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLOListElement() override; }; } + +WRAPPER_HACK(HTMLOListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index baea9234266215033d1d2d7de2b6362f671a6cb8..678a058256b30337ad3510c83901110c197d576b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -19,6 +20,7 @@ namespace Web::HTML { HTMLObjectElement::HTMLObjectElement(DOM::Document& document, DOM::QualifiedName qualified_name) : BrowsingContextContainer(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLObjectElement")); } HTMLObjectElement::~HTMLObjectElement() = default; @@ -96,7 +98,7 @@ void HTMLObjectElement::queue_element_task_to_run_object_representation_steps() // 3. If that failed, fire an event named error at the element, then jump to the step below labeled fallback. if (!url.is_valid()) { - dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error)); + dispatch_event(*DOM::Event::create(document().window(), HTML::EventNames::error)); return run_object_representation_fallback_steps(); } @@ -123,7 +125,7 @@ void HTMLObjectElement::queue_element_task_to_run_object_representation_steps() void HTMLObjectElement::resource_did_fail() { // 4.7. If the load failed (e.g. there was an HTTP 404 error, there was a DNS error), fire an event named error at the element, then jump to the step below labeled fallback. - dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error)); + dispatch_event(*DOM::Event::create(document().window(), HTML::EventNames::error)); run_object_representation_fallback_steps(); } @@ -261,7 +263,7 @@ void HTMLObjectElement::run_object_representation_completed_steps(Representation // 4.11. If the object element does not represent its nested browsing context, then once the resource is completely loaded, queue an element task on the DOM manipulation task source given the object element to fire an event named load at the element. if (representation != Representation::NestedBrowsingContext) { queue_an_element_task(HTML::Task::Source::DOMManipulation, [&]() { - dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::load)); + dispatch_event(*DOM::Event::create(document().window(), HTML::EventNames::load)); }); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h index 9b8b7aa558cdee1104e2044c51be38a5e9e902f0..d0d784beab823e38ccc6ec9d1dd232cb46170d4e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h @@ -19,6 +19,7 @@ class HTMLObjectElement final : public BrowsingContextContainer , public FormAssociatedElement , public ResourceClient { + WEB_PLATFORM_OBJECT(HTMLObjectElement, BrowsingContextContainer) FORM_ASSOCIATED_ELEMENT(BrowsingContextContainer, HTMLObjectElement) enum class Representation { @@ -29,9 +30,6 @@ class HTMLObjectElement final }; public: - using WrapperType = Bindings::HTMLObjectElementWrapper; - - HTMLObjectElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLObjectElement() override; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -46,6 +44,8 @@ public: virtual bool is_listed() const override { return true; } private: + HTMLObjectElement(DOM::Document&, DOM::QualifiedName); + virtual RefPtr create_layout_node(NonnullRefPtr) override; bool has_ancestor_media_element_or_object_element_not_showing_fallback_content() const; @@ -67,3 +67,5 @@ private: }; } + +WRAPPER_HACK(HTMLObjectElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.idl index f44d2fcad07209902d4fd22e04116511745824db..ce45d467f220fd8a1826b7cea4a5d0b7e267898f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.idl @@ -1,3 +1,4 @@ +#import #import interface HTMLObjectElement : HTMLElement { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.cpp index 648d9a686c2d7136fc0304ee9c4aca5ec642d44e..2460f1fe25358d6530b0d713895b25bf22459a82 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLOptGroupElement::HTMLOptGroupElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLOptGroupElement")); } HTMLOptGroupElement::~HTMLOptGroupElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h index dc04138cb1b21653a896a3824f18713d16c83d61..87427b56981bcfbc3024702484896d1cf67f0ed0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLOptGroupElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLOptGroupElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLOptGroupElementWrapper; + virtual ~HTMLOptGroupElement() override; +private: HTMLOptGroupElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLOptGroupElement() override; }; } + +WRAPPER_HACK(HTMLOptGroupElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp index 8f4fed8b60f00428828c18b5178119b66565e4dc..06c27df4b9cf58dab5d3db45a44549f1d4869b90 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp @@ -6,11 +6,13 @@ */ #include +#include #include #include #include #include #include +#include #include namespace Web::HTML { @@ -18,6 +20,7 @@ namespace Web::HTML { HTMLOptionElement::HTMLOptionElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLOptionElement")); } HTMLOptionElement::~HTMLOptionElement() = default; @@ -138,7 +141,7 @@ int HTMLOptionElement::index() const if (auto select_element = first_ancestor_of_type()) { int index = 0; for (auto const& option_element : select_element->list_of_options()) { - if (&option_element == this) + if (option_element.ptr() == this) return index; ++index; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h index 8b83003ced51a8658ec59ebef2c8efbc47e887e0..79aade13c3eb8733982871a6ef97a3f438549105 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h @@ -12,10 +12,9 @@ namespace Web::HTML { class HTMLOptionElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLOptionElementWrapper; + WEB_PLATFORM_OBJECT(HTMLOptionElement, HTMLElement); - HTMLOptionElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLOptionElement() override; bool selected() const { return m_selected; } @@ -33,6 +32,8 @@ private: friend class Bindings::OptionConstructor; friend class HTMLSelectElement; + HTMLOptionElement(DOM::Document&, DOM::QualifiedName); + void parse_attribute(FlyString const& name, String const& value) override; void did_remove_attribute(FlyString const& name) override; @@ -46,3 +47,5 @@ private: }; } + +WRAPPER_HACK(HTMLOptionElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp index 01a7fa79e484fb0a7da189006768a5b2ff193118..b3d758922319950c71493535dbed93e40b778dc2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp @@ -20,11 +20,14 @@ HTMLOptionsCollection::HTMLOptionsCollection(DOM::ParentNode& root, Function HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement element, Optional before) { - auto resolved_element = element.visit([](auto const& e) -> NonnullRefPtr { return e; }); + auto resolved_element = element.visit( + [](auto& e) -> JS::Handle { + return JS::make_handle(static_cast(*e)); + }); - RefPtr before_element; - if (before.has_value() && before->has>()) - before_element = before->get>(); + JS::GCPtr before_element; + if (before.has_value() && before->has>()) + before_element = before->get>().ptr(); // 1. If element is an ancestor of the select element on which the HTMLOptionsCollection is rooted, then throw a "HierarchyRequestError" DOMException. if (resolved_element->is_ancestor_of(root())) @@ -39,7 +42,7 @@ DOM::ExceptionOr HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement el return {}; // 4. If before is a node, then let reference be that node. Otherwise, if before is an integer, and there is a beforeth node in the collection, let reference be that node. Otherwise, let reference be null. - RefPtr reference; + JS::GCPtr reference; if (before_element) reference = move(before_element); @@ -50,7 +53,7 @@ DOM::ExceptionOr HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement el DOM::Node* parent = reference ? reference->parent() : root().ptr(); // 6. Pre-insert element into parent node before reference. - (void)TRY(parent->pre_insert(resolved_element, reference)); + (void)TRY(parent->pre_insert(*resolved_element, reference)); return {}; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h index 105009b4ff336b2bae69315a60526f20ee729163..e27b2491e3bde453bab5e9231471254bd564099e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h @@ -12,8 +12,8 @@ namespace Web::HTML { -using HTMLOptionOrOptGroupElement = Variant, NonnullRefPtr>; -using HTMLElementOrElementIndex = Variant, i32>; +using HTMLOptionOrOptGroupElement = Variant, JS::Handle>; +using HTMLElementOrElementIndex = Variant, i32>; class HTMLOptionsCollection final : public DOM::HTMLCollection { public: diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp index e9fcc6a941cfb1a262af3894393e72681280f6f5..b5f8f5d07dee2b1cd05eb67154ce7bfee30642fc 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLOutputElement::HTMLOutputElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLOutputElement")); } HTMLOutputElement::~HTMLOutputElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h index fb3ad802d00471f920936c8cea08aeb8ae625c8c..9b75d17949249c31ca008f301e5c351b7207f0f2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h @@ -15,12 +15,10 @@ namespace Web::HTML { class HTMLOutputElement final : public HTMLElement , public FormAssociatedElement { + WEB_PLATFORM_OBJECT(HTMLOutputElement, HTMLElement); FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLOutputElement) public: - using WrapperType = Bindings::HTMLOutputElementWrapper; - - HTMLOutputElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLOutputElement() override; String const& type() const @@ -42,6 +40,11 @@ public: // ^HTMLElement // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return true; } + +private: + HTMLOutputElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLOutputElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp index 2e93713cb6bdfe5c0c46bdaf502e2669687b3302..b8dabd218ab6222a02cc5e88cd003d32aa5201dc 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLParagraphElement::HTMLParagraphElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLParagraphElement")); } HTMLParagraphElement::~HTMLParagraphElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h index 9d03daf490f6421b21dc2b98edeb6856cb571e69..1a86e50e4e5f7f97ae06c565a0a50374e00bcb41 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLParagraphElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLParagraphElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLParagraphElementWrapper; + virtual ~HTMLParagraphElement() override; +private: HTMLParagraphElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLParagraphElement() override; }; } + +WRAPPER_HACK(HTMLParagraphElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp index 93c88d92b3c800dc14f9ab3542b5968e4fd00d50..9e41a5f40244d42c0e7bac06cea5c372482aa65b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLParamElement::HTMLParamElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLParamElement")); } HTMLParamElement::~HTMLParamElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h index e13ae0a2ea6a078c74f062673e52496c899758d8..524580ed44e948a964ea1703e9977becbe998a05 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLParamElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLParamElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLParamElementWrapper; + virtual ~HTMLParamElement() override; +private: HTMLParamElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLParamElement() override; }; } + +WRAPPER_HACK(HTMLParamElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp index c6e3bbea72377202d558da1a4e1dda21d5a9b295..6dcd14db66c123c6255a3ea2f0fc23b25aae4e42 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLPictureElement::HTMLPictureElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLPictureElement")); } HTMLPictureElement::~HTMLPictureElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h index 72bf00d8be50436d4cc7d63e20ac45bdd73b9d56..37f34c3725dc5c2664260a3e5177ff6e5b68a46a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLPictureElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLPictureElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLPictureElementWrapper; + virtual ~HTMLPictureElement() override; +private: HTMLPictureElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLPictureElement() override; }; } + +WRAPPER_HACK(HTMLPictureElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp index b098384bcc94037cce0b16258980857e9f1b8add..400e9978abaa7f10e665a8ceaf2b2218c9084fce 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLPreElement::HTMLPreElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLPreElement")); } HTMLPreElement::~HTMLPreElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h index fa8f24887bdcb4701fb73e2f495b8a69a29e7dcc..9797ea25da536fa3a3ad8f0355690d2ad18a4863 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h @@ -11,14 +11,16 @@ namespace Web::HTML { class HTMLPreElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLPreElementWrapper; + WEB_PLATFORM_OBJECT(HTMLPreElement, HTMLElement); - HTMLPreElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLPreElement() override; private: + HTMLPreElement(DOM::Document&, DOM::QualifiedName); virtual void apply_presentational_hints(CSS::StyleProperties&) const override; }; } + +WRAPPER_HACK(HTMLPreElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp index 62abdd9f959cf7a026f7a8995256624a7f52aca7..d3e8bcd50089f45cc507e9901508ae0db21a80ee 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -18,6 +19,7 @@ namespace Web::HTML { HTMLProgressElement::HTMLProgressElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLProgressElement")); } HTMLProgressElement::~HTMLProgressElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h index f1af0fd1b6f3285b6875748e37da04a7e0e99fce..d1cc612ef32a9368029311756bc696d9c8ef570d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h @@ -11,10 +11,9 @@ namespace Web::HTML { class HTMLProgressElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLProgressElementWrapper; + WEB_PLATFORM_OBJECT(HTMLProgressElement, HTMLElement); - HTMLProgressElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLProgressElement() override; virtual RefPtr create_layout_node(NonnullRefPtr) override; @@ -34,9 +33,13 @@ public: bool using_system_appearance() const; private: + HTMLProgressElement(DOM::Document&, DOM::QualifiedName); + void progress_position_updated(); bool is_determinate() const { return has_attribute(HTML::AttributeNames::value); } }; } + +WRAPPER_HACK(HTMLProgressElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp index 552ecdfce77a84b19cda905b7d6ecac136d0980a..daed2603af6531b8e35565c5ab887adc17963afd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLQuoteElement::HTMLQuoteElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLQuoteElement")); } HTMLQuoteElement::~HTMLQuoteElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h index ea25c54144f939e7da167342c6fe426edf94a04b..7a38ce478c76869b2fc1e0e2acb44ae635f106aa 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLQuoteElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLQuoteElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLQuoteElementWrapper; + virtual ~HTMLQuoteElement() override; +private: HTMLQuoteElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLQuoteElement() override; }; } + +WRAPPER_HACK(HTMLQuoteElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp index fee2ba9df53e4219762a074ecd0b5a0b01fb8617..3b6f000e0f77f77343bac19f72e88ad238fbeaf6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -22,10 +23,18 @@ namespace Web::HTML { HTMLScriptElement::HTMLScriptElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLScriptElement")); } HTMLScriptElement::~HTMLScriptElement() = default; +void HTMLScriptElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_parser_document.ptr()); + visitor.visit(m_preparation_time_document.ptr()); +} + void HTMLScriptElement::begin_delaying_document_load_event(DOM::Document& document) { // https://html.spec.whatwg.org/multipage/scripting.html#concept-script-script @@ -37,7 +46,7 @@ void HTMLScriptElement::begin_delaying_document_load_event(DOM::Document& docume void HTMLScriptElement::execute_script() { // 1. Let document be scriptElement's node document. - NonnullRefPtr node_document = document(); + JS::NonnullGCPtr node_document = document(); // 2. If scriptElement's preparation-time document is not equal to document, then return. if (m_preparation_time_document.ptr() != node_document.ptr()) { @@ -48,7 +57,7 @@ void HTMLScriptElement::execute_script() // 3. If the script's script is null for scriptElement, then fire an event named error at scriptElement, and return. if (!m_script) { dbgln("HTMLScriptElement: Refusing to run script because the script's script is null."); - dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error)); + dispatch_event(*DOM::Event::create(document().window(), HTML::EventNames::error)); return; } @@ -95,7 +104,7 @@ void HTMLScriptElement::execute_script() // 7. If scriptElement is from an external file, then fire an event named load at scriptElement. if (m_from_an_external_file) - dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::load)); + dispatch_event(*DOM::Event::create(document().window(), HTML::EventNames::load)); } // https://mimesniff.spec.whatwg.org/#javascript-mime-type-essence-match @@ -115,7 +124,7 @@ void HTMLScriptElement::prepare_script() } // 2. Let parser document be the element's parser document. - RefPtr parser_document = m_parser_document.ptr(); + JS::GCPtr parser_document = m_parser_document.ptr(); // 3. Set the element's parser document to null. m_parser_document = nullptr; @@ -173,7 +182,7 @@ void HTMLScriptElement::prepare_script() // 9. If parser document is non-null, then set the element's parser document back to parser document and set the element's "non-blocking" flag to false. if (parser_document) { - m_parser_document = *parser_document; + m_parser_document = parser_document; m_non_blocking = false; } @@ -181,7 +190,7 @@ void HTMLScriptElement::prepare_script() m_already_started = true; // 11. Set the element's preparation-time document to its node document. - m_preparation_time_document = document(); + m_preparation_time_document = &document(); // 12. If parser document is non-null, and parser document is not equal to the element's preparation-time document, then return. if (parser_document && parser_document.ptr() != m_preparation_time_document.ptr()) { @@ -259,7 +268,7 @@ void HTMLScriptElement::prepare_script() if (src.is_empty()) { dbgln("HTMLScriptElement: Refusing to run script because the src attribute is empty."); queue_an_element_task(HTML::Task::Source::Unspecified, [this] { - dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error)); + dispatch_event(*DOM::Event::create(document().window(), HTML::EventNames::error)); }); return; } @@ -272,7 +281,7 @@ void HTMLScriptElement::prepare_script() if (!url.is_valid()) { dbgln("HTMLScriptElement: Refusing to run script because the src URL '{}' is invalid.", url); queue_an_element_task(HTML::Task::Source::Unspecified, [this] { - dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error)); + dispatch_event(*DOM::Event::create(document().window(), HTML::EventNames::error)); }); return; } @@ -374,13 +383,13 @@ void HTMLScriptElement::prepare_script() // 1. If the element is not now the first element in the list of scripts // that will execute in order as soon as possible to which it was added above, // then mark the element as ready but return without executing the script yet. - if (this != &m_preparation_time_document->scripts_to_execute_as_soon_as_possible().first()) + if (this != m_preparation_time_document->scripts_to_execute_as_soon_as_possible().first().ptr()) return; for (;;) { // 2. Execution: Execute the script block corresponding to the first script element // in this list of scripts that will execute in order as soon as possible. - m_preparation_time_document->scripts_to_execute_as_soon_as_possible().first().execute_script(); + m_preparation_time_document->scripts_to_execute_as_soon_as_possible().first()->execute_script(); // 3. Remove the first element from this list of scripts that will execute in order // as soon as possible. @@ -389,7 +398,7 @@ void HTMLScriptElement::prepare_script() // 4. If this list of scripts that will execute in order as soon as possible is still // not empty and the first entry has already been marked as ready, then jump back // to the step labeled execution. - if (!m_preparation_time_document->scripts_to_execute_as_soon_as_possible().is_empty() && m_preparation_time_document->scripts_to_execute_as_soon_as_possible().first().m_script_ready) + if (!m_preparation_time_document->scripts_to_execute_as_soon_as_possible().is_empty() && m_preparation_time_document->scripts_to_execute_as_soon_as_possible().first()->m_script_ready) continue; break; @@ -409,7 +418,7 @@ void HTMLScriptElement::prepare_script() when_the_script_is_ready([this] { execute_script(); m_preparation_time_document->scripts_to_execute_as_soon_as_possible().remove_first_matching([&](auto& entry) { - return entry == this; + return entry.ptr() == this; }); }); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h index fbaa5eab518f786b7414eb140b0557237ebb30c8..0ff4f977a6177fc3280bae45285a02d4c0777bbe 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h @@ -14,10 +14,9 @@ namespace Web::HTML { class HTMLScriptElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLScriptElementWrapper; + WEB_PLATFORM_OBJECT(HTMLScriptElement, HTMLElement); - HTMLScriptElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLScriptElement() override; bool is_non_blocking() const { return m_non_blocking; } @@ -25,7 +24,7 @@ public: bool failed_to_load() const { return m_failed_to_load; } template T> - void set_parser_document(Badge, DOM::Document& document) { m_parser_document = document; } + void set_parser_document(Badge, DOM::Document& document) { m_parser_document = &document; } template T> void set_non_blocking(Badge, bool b) { m_non_blocking = b; } @@ -51,13 +50,17 @@ public: void set_source_line_number(Badge, size_t source_line_number) { m_source_line_number = source_line_number; } private: + HTMLScriptElement(DOM::Document&, DOM::QualifiedName); + + virtual void visit_edges(Cell::Visitor&) override; + void prepare_script(); void script_became_ready(); void when_the_script_is_ready(Function); void begin_delaying_document_load_event(DOM::Document&); - WeakPtr m_parser_document; - WeakPtr m_preparation_time_document; + JS::GCPtr m_parser_document; + JS::GCPtr m_preparation_time_document; bool m_non_blocking { false }; bool m_already_started { false }; bool m_from_an_external_file { false }; @@ -82,3 +85,5 @@ private: }; } + +WRAPPER_HACK(HTMLScriptElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp index 94333e018dfb59f7219fabd18e4c043fb2c990a4..25027acd4d2da37cad9f79cc1e3f06ae2a8d9ecc 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp @@ -5,16 +5,19 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include #include +#include namespace Web::HTML { HTMLSelectElement::HTMLSelectElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLSelectElement")); } HTMLSelectElement::~HTMLSelectElement() = default; @@ -42,19 +45,19 @@ DOM::ExceptionOr HTMLSelectElement::add(HTMLOptionOrOptGroupElement elemen } // https://html.spec.whatwg.org/multipage/form-elements.html#concept-select-option-list -NonnullRefPtrVector HTMLSelectElement::list_of_options() const +Vector> HTMLSelectElement::list_of_options() const { // The list of options for a select element consists of all the option element children of the select element, // and all the option element children of all the optgroup element children of the select element, in tree order. - NonnullRefPtrVector list; + Vector> list; for_each_child_of_type([&](HTMLOptionElement const& option_element) { - list.append(option_element); + list.append(JS::make_handle(const_cast(option_element))); }); for_each_child_of_type([&](HTMLOptGroupElement const& optgroup_element) { optgroup_element.for_each_child_of_type([&](HTMLOptionElement const& option_element) { - list.append(option_element); + list.append(JS::make_handle(const_cast(option_element))); }); }); @@ -69,7 +72,7 @@ int HTMLSelectElement::selected_index() const int index = 0; for (auto const& option_element : list_of_options()) { - if (option_element.selected()) + if (option_element->selected()) return index; ++index; } @@ -83,14 +86,14 @@ void HTMLSelectElement::set_selected_index(int index) // if any, must have its selectedness set to true and its dirtiness set to true. auto options = list_of_options(); for (auto& option : options) - option.m_selected = false; + option->m_selected = false; if (index < 0 || index >= static_cast(options.size())) return; auto& selected_option = options[index]; - selected_option.m_selected = true; - selected_option.m_dirty = true; + selected_option->m_selected = true; + selected_option->m_dirty = true; } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h index cbb19ec9ba9a01d1713b2a400df8761b10e9ab58..86b42eb07ecf1edaa0321d098f5551d59ce4ae3b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h @@ -17,12 +17,10 @@ namespace Web::HTML { class HTMLSelectElement final : public HTMLElement , public FormAssociatedElement { + WEB_PLATFORM_OBJECT(HTMLSelectElement, HTMLElement); FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLSelectElement) public: - using WrapperType = Bindings::HTMLSelectElementWrapper; - - HTMLSelectElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLSelectElement() override; RefPtr const& options(); @@ -32,7 +30,7 @@ public: int selected_index() const; void set_selected_index(int); - NonnullRefPtrVector list_of_options() const; + Vector> list_of_options() const; // ^EventTarget // https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute:the-select-element @@ -56,7 +54,11 @@ public: virtual bool is_labelable() const override { return true; } private: + HTMLSelectElement(DOM::Document&, DOM::QualifiedName); + RefPtr m_options; }; } + +WRAPPER_HACK(HTMLSelectElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp index e3c72331df09a2024e1298950863e190d9bb5905..36d316516c3426d0d27517958aa7a23a624011d2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLSlotElement::HTMLSlotElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLSlotElement")); } HTMLSlotElement::~HTMLSlotElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h index c0564dc02ff2d54d72220f598510780979eb2298..795ad0755863c78026ec1a19f5b4b97f22f6b2b3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLSlotElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLSlotElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLSlotElementWrapper; + virtual ~HTMLSlotElement() override; +private: HTMLSlotElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLSlotElement() override; }; } + +WRAPPER_HACK(HTMLSlotElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp index f682bf46e075a236c08ea4f83ba2df53bfbf67e5..38c3172e567dbbdeca196285b584c38a15ae270f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLSourceElement::HTMLSourceElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLSourceElement")); } HTMLSourceElement::~HTMLSourceElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h index 196a6041e73ffcd102d08cd3c9ef5bdd7ef06b3c..65df7a40046b6dc37758012de2f05edff5f3f8a2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLSourceElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLSourceElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLSourceElementWrapper; + virtual ~HTMLSourceElement() override; +private: HTMLSourceElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLSourceElement() override; }; } + +WRAPPER_HACK(HTMLSourceElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp index 1fb05693d41374f547592b95b51a9f92cc69d87e..8f3c0177f46eca30db09088639a7811d1ebb0c62 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLSpanElement::HTMLSpanElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLSpanElement")); } HTMLSpanElement::~HTMLSpanElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h index aa7b7a1d72654fca36ba4034654d55014cbcf318..3b67123ced076844002b8693b9d07df24cb9f816 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLSpanElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLSpanElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLSpanElementWrapper; + virtual ~HTMLSpanElement() override; +private: HTMLSpanElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLSpanElement() override; }; } + +WRAPPER_HACK(HTMLSpanElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp index f7655da00d9152df431451ccfb8ead3e2b1d5809..1013e8b2bf93fe5692b9681ffff8b357ca8d0829 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -14,10 +15,17 @@ namespace Web::HTML { HTMLStyleElement::HTMLStyleElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLStyleElement")); } HTMLStyleElement::~HTMLStyleElement() = default; +void HTMLStyleElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_associated_css_style_sheet.ptr()); +} + void HTMLStyleElement::children_changed() { @@ -104,11 +112,11 @@ void HTMLStyleElement::update_a_style_block() // 1. Let element be the style element. // 2. If element has an associated CSS style sheet, remove the CSS style sheet in question. - if (m_associated_css_style_sheet.cell()) { + if (m_associated_css_style_sheet) { remove_a_css_style_sheet(document(), *m_associated_css_style_sheet); // FIXME: This should probably be handled by StyleSheet::set_owner_node(). - m_associated_css_style_sheet = {}; + m_associated_css_style_sheet = nullptr; } // 3. If element is not connected, then return. @@ -129,7 +137,7 @@ void HTMLStyleElement::update_a_style_block() return; // FIXME: This should probably be handled by StyleSheet::set_owner_node(). - m_associated_css_style_sheet = JS::make_handle(sheet); + m_associated_css_style_sheet = sheet; // 6. Create a CSS style sheet with the following properties... create_a_css_style_sheet( @@ -150,14 +158,14 @@ void HTMLStyleElement::update_a_style_block() CSS::CSSStyleSheet* HTMLStyleElement::sheet() { // The sheet attribute must return the associated CSS style sheet for the node or null if there is no associated CSS style sheet. - return m_associated_css_style_sheet.cell(); + return m_associated_css_style_sheet; } // https://www.w3.org/TR/cssom/#dom-linkstyle-sheet CSS::CSSStyleSheet const* HTMLStyleElement::sheet() const { // The sheet attribute must return the associated CSS style sheet for the node or null if there is no associated CSS style sheet. - return m_associated_css_style_sheet.cell(); + return m_associated_css_style_sheet; } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.h b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.h index e12d1dd3ec470c84bb38a6299dfbf812f104f519..9e1bfd268f351057ec30f27a08f8dfeee5f0099e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.h @@ -12,10 +12,9 @@ namespace Web::HTML { class HTMLStyleElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLStyleElementWrapper; + WEB_PLATFORM_OBJECT(HTMLStyleElement, HTMLElement); - HTMLStyleElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLStyleElement() override; virtual void children_changed() override; @@ -28,8 +27,14 @@ public: CSS::CSSStyleSheet const* sheet() const; private: + HTMLStyleElement(DOM::Document&, DOM::QualifiedName); + + virtual void visit_edges(Cell::Visitor&) override; + // https://www.w3.org/TR/cssom/#associated-css-style-sheet - JS::Handle m_associated_css_style_sheet; + JS::GCPtr m_associated_css_style_sheet; }; } + +WRAPPER_HACK(HTMLStyleElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp index 542de9fda5a103ccf358494a2f2b85dee275bc5b..27b7a0d80d928ccd54165afe48327ce5ffdee772 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLTableCaptionElement::HTMLTableCaptionElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTableCaptionElement")); } HTMLTableCaptionElement::~HTMLTableCaptionElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h index c813366dd89b693164bc06e9a8ef5a07c4a5790b..0761306f7ebfd19ea4522476b82ae8d5b3305bd4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTableCaptionElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTableCaptionElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTableCaptionElementWrapper; + virtual ~HTMLTableCaptionElement() override; +private: HTMLTableCaptionElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTableCaptionElement() override; }; } + +WRAPPER_HACK(HTMLTableCaptionElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp index 936512dc974e9780d1af126d0c9a71637dc9a4ad..9f97fa7540932f390a14c5a41d0ac25a99ab74c1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp @@ -4,15 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include +#include namespace Web::HTML { HTMLTableCellElement::HTMLTableCellElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTableCellElement")); } HTMLTableCellElement::~HTMLTableCellElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h index 1393e344d4088e34be9a0f2ee9bb09d532378c6c..d6fd5104dcec4f91bc043a66809c1d5ef0265feb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h @@ -11,10 +11,9 @@ namespace Web::HTML { class HTMLTableCellElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLTableCellElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTableCellElement, HTMLElement); - HTMLTableCellElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTableCellElement() override; unsigned col_span() const; @@ -24,7 +23,10 @@ public: void set_row_span(unsigned); private: + HTMLTableCellElement(DOM::Document&, DOM::QualifiedName); virtual void apply_presentational_hints(CSS::StyleProperties&) const override; }; } + +WRAPPER_HACK(HTMLTableCellElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.cpp index 97dfc3f6df1ba2e37d83f0d69c8ef643904f8d1e..f48bbbb9bcacc267f07c522c70b9246cda6233f5 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLTableColElement::HTMLTableColElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTableColElement")); } HTMLTableColElement::~HTMLTableColElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h index ee60076a199428497be7987ed8abb96b3a8a9660..21e397f14b4e1a462d7040d8f210d5cd4fe5ee6b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTableColElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTableColElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTableColElementWrapper; + virtual ~HTMLTableColElement() override; +private: HTMLTableColElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTableColElement() override; }; } + +WRAPPER_HACK(HTMLTableColElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp index 447005b95d98822a0049fbe3caae43a964bd4e9b..e3da69c0d367bfdd5143c3ff2d5a5030088d33b7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -19,6 +21,7 @@ namespace Web::HTML { HTMLTableElement::HTMLTableElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTableElement")); } HTMLTableElement::~HTMLTableElement() = default; @@ -45,7 +48,7 @@ void HTMLTableElement::apply_presentational_hints(CSS::StyleProperties& style) c }); } -RefPtr HTMLTableElement::caption() +JS::GCPtr HTMLTableElement::caption() { return first_child_of_type(); } @@ -62,7 +65,7 @@ void HTMLTableElement::set_caption(HTMLTableCaptionElement* caption) pre_insert(*caption, first_child()); } -NonnullRefPtr HTMLTableElement::create_caption() +JS::NonnullGCPtr HTMLTableElement::create_caption() { auto maybe_caption = caption(); if (maybe_caption) { @@ -71,7 +74,7 @@ NonnullRefPtr HTMLTableElement::create_caption() auto caption = DOM::create_element(document(), TagNames::caption, Namespace::HTML); pre_insert(caption, first_child()); - return static_ptr_cast(caption); + return static_cast(*caption); } void HTMLTableElement::delete_caption() @@ -82,7 +85,7 @@ void HTMLTableElement::delete_caption() } } -RefPtr HTMLTableElement::t_head() +JS::GCPtr HTMLTableElement::t_head() { for (auto* child = first_child(); child; child = child->next_sibling()) { if (is(*child)) { @@ -130,7 +133,7 @@ DOM::ExceptionOr HTMLTableElement::set_t_head(HTMLTableSectionElement* the return {}; } -NonnullRefPtr HTMLTableElement::create_t_head() +JS::NonnullGCPtr HTMLTableElement::create_t_head() { auto maybe_thead = t_head(); if (maybe_thead) @@ -158,7 +161,7 @@ NonnullRefPtr HTMLTableElement::create_t_head() pre_insert(thead, child_to_append_after); - return static_ptr_cast(thead); + return static_cast(*thead); } void HTMLTableElement::delete_t_head() @@ -169,7 +172,7 @@ void HTMLTableElement::delete_t_head() } } -RefPtr HTMLTableElement::t_foot() +JS::GCPtr HTMLTableElement::t_foot() { for (auto* child = first_child(); child; child = child->next_sibling()) { if (is(*child)) { @@ -200,7 +203,7 @@ DOM::ExceptionOr HTMLTableElement::set_t_foot(HTMLTableSectionElement* tfo return {}; } -NonnullRefPtr HTMLTableElement::create_t_foot() +JS::NonnullGCPtr HTMLTableElement::create_t_foot() { auto maybe_tfoot = t_foot(); if (maybe_tfoot) @@ -208,7 +211,7 @@ NonnullRefPtr HTMLTableElement::create_t_foot() auto tfoot = DOM::create_element(document(), TagNames::tfoot, Namespace::HTML); append_child(tfoot); - return static_ptr_cast(tfoot); + return static_cast(*tfoot); } void HTMLTableElement::delete_t_foot() @@ -226,7 +229,7 @@ NonnullRefPtr HTMLTableElement::t_bodies() }); } -NonnullRefPtr HTMLTableElement::create_t_body() +JS::NonnullGCPtr HTMLTableElement::create_t_body() { auto tbody = DOM::create_element(document(), TagNames::tbody, Namespace::HTML); @@ -247,7 +250,7 @@ NonnullRefPtr HTMLTableElement::create_t_body() pre_insert(tbody, child_to_append_after); - return static_ptr_cast(tbody); + return static_cast(*tbody); } NonnullRefPtr HTMLTableElement::rows() @@ -278,7 +281,7 @@ NonnullRefPtr HTMLTableElement::rows() }); } -DOM::ExceptionOr> HTMLTableElement::insert_row(long index) +DOM::ExceptionOr> HTMLTableElement::insert_row(long index) { auto rows = this->rows(); auto rows_length = rows->length(); @@ -286,7 +289,7 @@ DOM::ExceptionOr> HTMLTableElement::insert_ro if (index < -1 || index > (long)rows_length) { return DOM::IndexSizeError::create("Index is negative or greater than the number of rows"); } - auto tr = static_ptr_cast(DOM::create_element(document(), TagNames::tr, Namespace::HTML)); + auto& tr = static_cast(*DOM::create_element(document(), TagNames::tr, Namespace::HTML)); if (rows_length == 0 && !has_child_of_type()) { auto tbody = DOM::create_element(document(), TagNames::tbody, Namespace::HTML); tbody->append_child(tr); @@ -300,7 +303,7 @@ DOM::ExceptionOr> HTMLTableElement::insert_ro } else { rows->item(index)->parent_element()->insert_before(tr, rows->item(index)); } - return tr; + return JS::NonnullGCPtr(tr); } // https://html.spec.whatwg.org/multipage/tables.html#dom-table-deleterow diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h index cd166087db680c038ec4ecc00ea4418ab0d99133..1b6840d88e49b7716113e46d1a5b9f53f6613e7e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h @@ -15,36 +15,39 @@ namespace Web::HTML { class HTMLTableElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLTableElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTableElement, HTMLElement); - HTMLTableElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTableElement() override; - RefPtr caption(); + JS::GCPtr caption(); void set_caption(HTMLTableCaptionElement*); - NonnullRefPtr create_caption(); + JS::NonnullGCPtr create_caption(); void delete_caption(); - RefPtr t_head(); + JS::GCPtr t_head(); DOM::ExceptionOr set_t_head(HTMLTableSectionElement* thead); - NonnullRefPtr create_t_head(); + JS::NonnullGCPtr create_t_head(); void delete_t_head(); - RefPtr t_foot(); + JS::GCPtr t_foot(); DOM::ExceptionOr set_t_foot(HTMLTableSectionElement* tfoot); - NonnullRefPtr create_t_foot(); + JS::NonnullGCPtr create_t_foot(); void delete_t_foot(); NonnullRefPtr t_bodies(); - NonnullRefPtr create_t_body(); + JS::NonnullGCPtr create_t_body(); NonnullRefPtr rows(); - DOM::ExceptionOr> insert_row(long index); + DOM::ExceptionOr> insert_row(long index); DOM::ExceptionOr delete_row(long index); private: + HTMLTableElement(DOM::Document&, DOM::QualifiedName); + virtual void apply_presentational_hints(CSS::StyleProperties&) const override; }; } + +WRAPPER_HACK(HTMLTableElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp index 107d8073596aa2d96ebf081d40b6f263ed3f23cd..307cc5cc8c1938e2895d74f825f84e1c85fc4add 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp @@ -4,17 +4,20 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include #include #include +#include namespace Web::HTML { HTMLTableRowElement::HTMLTableRowElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTableRowElement")); } HTMLTableRowElement::~HTMLTableRowElement() = default; @@ -52,7 +55,7 @@ int HTMLTableRowElement::row_index() const return -1; auto rows = rows_collection->collect_matching_elements(); for (size_t i = 0; i < rows.size(); ++i) { - if (rows[i].ptr() == this) + if (rows[i] == this) return i; } return -1; @@ -77,7 +80,7 @@ int HTMLTableRowElement::section_row_index() const return -1; auto rows = rows_collection->collect_matching_elements(); for (size_t i = 0; i < rows.size(); ++i) { - if (rows[i].ptr() == this) + if (rows[i] == this) return i; } return -1; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h index 065244ec7a069c654c4746fe873d3b834750b5f2..03b6cb1eb2e52682eab7ebdfbf73b7eaff6f8267 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h @@ -11,16 +11,20 @@ namespace Web::HTML { class HTMLTableRowElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLTableRowElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTableRowElement, HTMLElement); - HTMLTableRowElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTableRowElement() override; NonnullRefPtr cells() const; int row_index() const; int section_row_index() const; + +private: + HTMLTableRowElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLTableRowElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp index 326dffa95d107eb644d20a4657fd801943c0bd57..6e66c9d33cf2b607825e55898ab0a0e916169bf6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp @@ -5,10 +5,12 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include #include +#include #include namespace Web::HTML { @@ -16,6 +18,7 @@ namespace Web::HTML { HTMLTableSectionElement::HTMLTableSectionElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTableSectionElement")); } HTMLTableSectionElement::~HTMLTableSectionElement() = default; @@ -34,7 +37,7 @@ NonnullRefPtr HTMLTableSectionElement::rows() const } // https://html.spec.whatwg.org/multipage/tables.html#dom-tbody-insertrow -DOM::ExceptionOr> HTMLTableSectionElement::insert_row(long index) +DOM::ExceptionOr> HTMLTableSectionElement::insert_row(long index) { auto rows_collection = rows(); auto rows_collection_size = static_cast(rows_collection->length()); @@ -44,17 +47,17 @@ DOM::ExceptionOr> HTMLTableSectionElement::in return DOM::IndexSizeError::create("Index is negative or greater than the number of rows"); // 2. Let table row be the result of creating an element given this element's node document, tr, and the HTML namespace. - auto table_row = static_ptr_cast(DOM::create_element(document(), TagNames::tr, Namespace::HTML)); + auto& table_row = static_cast(*DOM::create_element(document(), TagNames::tr, Namespace::HTML)); // 3. If index is −1 or equal to the number of items in the rows collection, then append table row to this element. if (index == -1 || index == rows_collection_size) append_child(table_row); // 4. Otherwise, insert table row as a child of this element, immediately before the index-th tr element in the rows collection. else - table_row->insert_before(*this, rows_collection->item(index)); + table_row.insert_before(*this, rows_collection->item(index)); // 5. Return table row. - return table_row; + return JS::NonnullGCPtr(table_row); } // https://html.spec.whatwg.org/multipage/tables.html#dom-tbody-deleterow diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h index 98642fdde34b972740134dc08eaea12b51452808..112a92a9ffbb43458119d6e0d439df01eb6e7e93 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h @@ -12,15 +12,19 @@ namespace Web::HTML { class HTMLTableSectionElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLTableSectionElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTableSectionElement, HTMLElement); - HTMLTableSectionElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTableSectionElement() override; NonnullRefPtr rows() const; - DOM::ExceptionOr> insert_row(long index); + DOM::ExceptionOr> insert_row(long index); DOM::ExceptionOr delete_row(long index); + +private: + HTMLTableSectionElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLTableSectionElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp index 2b6a9a6a1a3174690e713ed13418a8fceb8af325..b32e5a8dd938a6c381ae395e46b4890662bde88d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include #include @@ -12,17 +14,25 @@ namespace Web::HTML { HTMLTemplateElement::HTMLTemplateElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { - m_content = adopt_ref(*new DOM::DocumentFragment(appropriate_template_contents_owner_document(document))); + set_prototype(&window().ensure_web_prototype("HTMLTemplateElement")); + + m_content = heap().allocate(realm(), appropriate_template_contents_owner_document(document)); m_content->set_host(this); } HTMLTemplateElement::~HTMLTemplateElement() = default; +void HTMLTemplateElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_content.ptr()); +} + DOM::Document& HTMLTemplateElement::appropriate_template_contents_owner_document(DOM::Document& document) { if (!document.created_for_appropriate_template_contents()) { if (!document.associated_inert_template_document()) { - auto new_document = DOM::Document::create(); + auto new_document = DOM::Document::create(Bindings::main_thread_internal_window_object()); new_document->set_created_for_appropriate_template_contents(true); new_document->set_document_type(document.document_type()); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.h index b00dc90bf7a122d215ac4ae46a7027cd8a86cc53..9c1c2e712e3f0397c531c82131ef8b52df92a4b0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.h @@ -12,24 +12,26 @@ namespace Web::HTML { class HTMLTemplateElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLTemplateElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTemplateElement, HTMLElement); - HTMLTemplateElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTemplateElement() override; - NonnullRefPtr content() { return *m_content; } - NonnullRefPtr const content() const { return *m_content; } + JS::NonnullGCPtr content() { return *m_content; } + JS::NonnullGCPtr const content() const { return *m_content; } virtual void adopted_from(DOM::Document&) override; virtual void cloned(Node& copy, bool clone_children) override; private: + HTMLTemplateElement(DOM::Document&, DOM::QualifiedName); + virtual bool is_html_template_element() const final { return true; } + virtual void visit_edges(Cell::Visitor&) override; DOM::Document& appropriate_template_contents_owner_document(DOM::Document&); - RefPtr m_content; + JS::GCPtr m_content; }; } @@ -38,3 +40,5 @@ namespace Web::DOM { template<> inline bool Node::fast_is() const { return is_html_template_element(); } } + +WRAPPER_HACK(HTMLTemplateElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp index e9c0db91d44705580e842c671414d6024feb8f2f..70ea1f21d098767979fe760df3ec550cd49e65f3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLTextAreaElement::HTMLTextAreaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTextAreaElement")); } HTMLTextAreaElement::~HTMLTextAreaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h index f8705b2551780352643c0364f11a1136082069df..f0d64e82b9a93334328fcf33d8d824eeea974915 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h @@ -15,12 +15,10 @@ namespace Web::HTML { class HTMLTextAreaElement final : public HTMLElement , public FormAssociatedElement { + WEB_PLATFORM_OBJECT(HTMLTextAreaElement, HTMLElement); FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLTextAreaElement) public: - using WrapperType = Bindings::HTMLTextAreaElementWrapper; - - HTMLTextAreaElement(DOM::Document&, DOM::QualifiedName); virtual ~HTMLTextAreaElement() override; String const& type() const @@ -49,6 +47,11 @@ public: // ^HTMLElement // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return true; } + +private: + HTMLTextAreaElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLTextAreaElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.cpp index c40869599f01baf277ed9fd3f6c2f38005268193..94647997409593246101695e8412c1faac0095c2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLTimeElement::HTMLTimeElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTextAreaElement")); } HTMLTimeElement::~HTMLTimeElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h index 762b495a8ed266199112ccb018f99b45db721eb8..494f42d1aff7cce78eb07e4f1810b7cf9f57e94d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTimeElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTimeElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTimeElementWrapper; + virtual ~HTMLTimeElement() override; +private: HTMLTimeElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTimeElement() override; }; } + +WRAPPER_HACK(HTMLTimeElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp index 0942f0d6d1092944ecb556418211b547e7c2e06a..e5568632788a57371f2e79a72fd7f085711dfedd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -13,6 +14,7 @@ namespace Web::HTML { HTMLTitleElement::HTMLTitleElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTitleElement")); } HTMLTitleElement::~HTMLTitleElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.h index 564401792b913ed928e828c1593486fa96052e99..7b4bc137505e4cdbeca44068d8786ed072776abb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.h @@ -11,14 +11,17 @@ namespace Web::HTML { class HTMLTitleElement final : public HTMLElement { -public: - using WrapperType = Bindings::HTMLTitleElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTitleElement, HTMLElement); - HTMLTitleElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTitleElement() override; private: + HTMLTitleElement(DOM::Document&, DOM::QualifiedName); + virtual void children_changed() override; }; } + +WRAPPER_HACK(HTMLTitleElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp index 944dbdbb0953ba4146e567e5d014a0d9f5b94f68..eadfacaf69c24276dc56a4191d4376ebc82b7fcd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLTrackElement::HTMLTrackElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLTrackElement")); } HTMLTrackElement::~HTMLTrackElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h index 2996f6a120a76caad7b7498b84cd2550e80850de..f3655e2dfe74d27a0c06567bde3af1204b5e8c04 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTrackElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTrackElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTrackElementWrapper; + virtual ~HTMLTrackElement() override; +private: HTMLTrackElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTrackElement() override; }; } + +WRAPPER_HACK(HTMLTrackElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp index 80c68a724f539ed40aa77b831ae491dbc2474312..71eb3820a96455c08936cf8be43d9cb0136985c4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLUListElement::HTMLUListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLUListElement")); } HTMLUListElement::~HTMLUListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h index d2838c75762ce992dbcb780e1aa484847a73b9f7..fa7f609bd0dce7102b39a1629a9a3059d1d1f965 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLUListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLUListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLUListElementWrapper; + virtual ~HTMLUListElement() override; +private: HTMLUListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLUListElement() override; }; } + +WRAPPER_HACK(HTMLUListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp index 1274e0a9bf760584de11fc759e1355df9e4a9f70..b5df91ad7ddcecce0e89f51ae1477a925c09052c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLUnknownElement::HTMLUnknownElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLUnknownElement")); } HTMLUnknownElement::~HTMLUnknownElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h index 6d36dbbc1de9a70f8a34467608c358f7b1f49096..dc5e518a03080475054435e00879cee7312d25f0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLUnknownElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLUnknownElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLUnknownElementWrapper; + virtual ~HTMLUnknownElement() override; +private: HTMLUnknownElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLUnknownElement() override; }; } + +WRAPPER_HACK(HTMLUnknownElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp index eb34e7c8c076e9858261119fdfda3954f38290ee..76b3941e27b46c2990a982c676a3a29f90119943 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp @@ -4,13 +4,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include namespace Web::HTML { HTMLVideoElement::HTMLVideoElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLMediaElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype("HTMLVideoElement")); } HTMLVideoElement::~HTMLVideoElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h index de4e292113e74f1b21de9cdcc928bc8cd968854c..e16de819c35dd03982a2a21363bc16623bc37400 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLVideoElement final : public HTMLMediaElement { + WEB_PLATFORM_OBJECT(HTMLVideoElement, HTMLMediaElement); + public: - using WrapperType = Bindings::HTMLVideoElementWrapper; + virtual ~HTMLVideoElement() override; +private: HTMLVideoElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLVideoElement() override; }; } + +WRAPPER_HACK(HTMLVideoElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp b/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp index cb877324f9be5b0f7e211039093ae24a31a7a454..8c74020b78aec5b62b7009f5fc59fb4acc59f6be 100644 --- a/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp +++ b/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp @@ -10,13 +10,13 @@ namespace Web::HTML { -MessageChannel::MessageChannel() +MessageChannel::MessageChannel(HTML::Window& window) { // 1. Set this's port 1 to a new MessagePort in this's relevant Realm. - m_port1 = MessagePort::create(); + m_port1 = JS::make_handle(*MessagePort::create(window)); // 2. Set this's port 2 to a new MessagePort in this's relevant Realm. - m_port2 = MessagePort::create(); + m_port2 = JS::make_handle(*MessagePort::create(window)); // 3. Entangle this's port 1 and this's port 2. m_port1->entangle_with(*m_port2); @@ -24,4 +24,24 @@ MessageChannel::MessageChannel() MessageChannel::~MessageChannel() = default; +MessagePort* MessageChannel::port1() +{ + return m_port1; +} + +MessagePort* MessageChannel::port2() +{ + return m_port2; +} + +MessagePort const* MessageChannel::port1() const +{ + return m_port1; +} + +MessagePort const* MessageChannel::port2() const +{ + return m_port2; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/MessageChannel.h b/Userland/Libraries/LibWeb/HTML/MessageChannel.h index 1d212db93345d8a6f31a36db059542fe9dd203e0..7ac38e3912d031661b4e5d9067510038bdb59fe1 100644 --- a/Userland/Libraries/LibWeb/HTML/MessageChannel.h +++ b/Userland/Libraries/LibWeb/HTML/MessageChannel.h @@ -24,24 +24,24 @@ public: using RefCounted::ref; using RefCounted::unref; - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&) + static NonnullRefPtr create_with_global_object(HTML::Window& window) { - return adopt_ref(*new MessageChannel()); + return adopt_ref(*new MessageChannel(window)); } virtual ~MessageChannel() override; - MessagePort* port1() { return m_port1; } - MessagePort const* port1() const { return m_port1; } + MessagePort* port1(); + MessagePort const* port1() const; - MessagePort* port2() { return m_port2; } - MessagePort const* port2() const { return m_port2; } + MessagePort* port2(); + MessagePort const* port2() const; private: - MessageChannel(); + explicit MessageChannel(HTML::Window&); - RefPtr m_port1; - RefPtr m_port2; + JS::Handle m_port1; + JS::Handle m_port2; }; } diff --git a/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp b/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp index 8fa050904d8a3df583e8cf6225fd18519c6f9764..b993d22a66c19d32804038736ace27bf91814d44 100644 --- a/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp @@ -5,22 +5,22 @@ */ #include -#include #include +#include namespace Web::HTML { -MessageEvent* MessageEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init) +MessageEvent* MessageEvent::create(HTML::Window& window_object, FlyString const& event_name, MessageEventInit const& event_init) { return window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); } -MessageEvent* MessageEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init) +MessageEvent* MessageEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, MessageEventInit const& event_init) { return create(window_object, event_name, event_init); } -MessageEvent::MessageEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init) +MessageEvent::MessageEvent(HTML::Window& window_object, FlyString const& event_name, MessageEventInit const& event_init) : DOM::Event(window_object, event_name, event_init) , m_data(event_init.data) , m_origin(event_init.origin) diff --git a/Userland/Libraries/LibWeb/HTML/MessageEvent.h b/Userland/Libraries/LibWeb/HTML/MessageEvent.h index 5671f8bd01efe3915c91d4b46b7761ab0e420830..6d7d180d93a17895f63490e1fb9e4f5a9a4f1af1 100644 --- a/Userland/Libraries/LibWeb/HTML/MessageEvent.h +++ b/Userland/Libraries/LibWeb/HTML/MessageEvent.h @@ -18,17 +18,15 @@ struct MessageEventInit : public DOM::EventInit { }; class MessageEvent : public DOM::Event { - JS_OBJECT(MessageEvent, DOM::Event); + WEB_PLATFORM_OBJECT(MessageEvent, DOM::Event); public: - static MessageEvent* create(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init = {}); - static MessageEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init); + static MessageEvent* create(HTML::Window&, FlyString const& event_name, MessageEventInit const& event_init = {}); + static MessageEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, MessageEventInit const& event_init); - MessageEvent(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init); + MessageEvent(HTML::Window&, FlyString const& event_name, MessageEventInit const& event_init); virtual ~MessageEvent() override; - MessageEvent& impl() { return *this; } - JS::Value data() const { return m_data; } String const& origin() const { return m_origin; } String const& last_event_id() const { return m_last_event_id; } diff --git a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp index b6938d6909153ab65a7624456d8dd959d6ffa4d5..9e4bb94101009b6fb0a0c9c29fb4864f65e2eaee 100644 --- a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp +++ b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include #include @@ -14,13 +14,25 @@ namespace Web::HTML { -MessagePort::MessagePort() - : DOM::EventTarget() +JS::NonnullGCPtr MessagePort::create(HTML::Window& window) { + return *window.heap().allocate(window.realm(), window); +} + +MessagePort::MessagePort(HTML::Window& window) + : DOM::EventTarget(window.realm()) +{ + set_prototype(&window.ensure_web_prototype("MessagePort")); } MessagePort::~MessagePort() = default; +void MessagePort::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_remote_port.ptr()); +} + void MessagePort::disentangle() { m_remote_port->m_remote_port = nullptr; @@ -30,7 +42,7 @@ void MessagePort::disentangle() // https://html.spec.whatwg.org/multipage/web-messaging.html#entangle void MessagePort::entangle_with(MessagePort& remote_port) { - if (m_remote_port == &remote_port) + if (m_remote_port.ptr() == &remote_port) return; // 1. If one of the ports is already entangled, then disentangle it and the port that it was entangled with. @@ -41,7 +53,7 @@ void MessagePort::entangle_with(MessagePort& remote_port) // 2. Associate the two ports to be entangled, so that they form the two parts of a new channel. // (There is no MessageChannel object that represents this channel.) - remote_port.m_remote_port = *this; + remote_port.m_remote_port = this; m_remote_port = &remote_port; } @@ -76,19 +88,14 @@ void MessagePort::post_message(JS::Value message) // FIXME: This is an ad-hoc hack implementation instead, since we don't currently // have serialization and deserialization of messages. - main_thread_event_loop().task_queue().add(HTML::Task::create(HTML::Task::Source::PostedMessage, nullptr, [strong_port = NonnullRefPtr { *target_port }, message]() mutable { + main_thread_event_loop().task_queue().add(HTML::Task::create(HTML::Task::Source::PostedMessage, nullptr, [strong_port = JS::make_handle(*target_port), message]() mutable { MessageEventInit event_init {}; event_init.data = message; event_init.origin = ""; - strong_port->dispatch_event(*MessageEvent::create(verify_cast(strong_port->wrapper()->global_object()), HTML::EventNames::message, event_init)); + strong_port->dispatch_event(*MessageEvent::create(verify_cast(strong_port->realm().global_object()), HTML::EventNames::message, event_init)); })); } -JS::Object* MessagePort::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - void MessagePort::start() { // FIXME: Message ports are supposed to be disabled by default. diff --git a/Userland/Libraries/LibWeb/HTML/MessagePort.h b/Userland/Libraries/LibWeb/HTML/MessagePort.h index 3cebac0aa29db96f6c81657a01748c5b091644df..9380b6f9a5c309fed0a7fd38cb384074edcaad29 100644 --- a/Userland/Libraries/LibWeb/HTML/MessagePort.h +++ b/Userland/Libraries/LibWeb/HTML/MessagePort.h @@ -19,29 +19,14 @@ namespace Web::HTML { E(onmessageerror, HTML::EventNames::messageerror) // https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports -class MessagePort final - : public RefCounted - , public Weakable - , public DOM::EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::MessagePortWrapper; - - using RefCounted::ref; - using RefCounted::unref; +class MessagePort final : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget); - static NonnullRefPtr create() - { - return adopt_ref(*new MessagePort()); - } +public: + static JS::NonnullGCPtr create(HTML::Window&); virtual ~MessagePort() override; - // ^EventTarget - virtual void ref_event_target() override { ref(); } - virtual void unref_event_target() override { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; - // https://html.spec.whatwg.org/multipage/web-messaging.html#entangle void entangle_with(MessagePort&); @@ -60,13 +45,15 @@ public: #undef __ENUMERATE private: - MessagePort(); + explicit MessagePort(HTML::Window&); + + virtual void visit_edges(Cell::Visitor&) override; bool is_entangled() const { return m_remote_port; } void disentangle(); // The HTML spec implies(!) that this is MessagePort.[[RemotePort]] - WeakPtr m_remote_port; + JS::GCPtr m_remote_port; // https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped bool m_has_been_shipped { false }; @@ -76,3 +63,5 @@ private: }; } + +WRAPPER_HACK(MessagePort, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp index 95d1e6a922d6beba362e52b9954f15438882858a..450be24913c0b8360f010acedf14494e88374b9d 100644 --- a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp @@ -5,22 +5,22 @@ */ #include -#include #include +#include namespace Web::HTML { -PageTransitionEvent* PageTransitionEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init) +PageTransitionEvent* PageTransitionEvent::create(HTML::Window& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init) { return window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); } -PageTransitionEvent* PageTransitionEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init) +PageTransitionEvent* PageTransitionEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init) { return create(window_object, event_name, event_init); } -PageTransitionEvent::PageTransitionEvent(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init) +PageTransitionEvent::PageTransitionEvent(HTML::Window& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init) : DOM::Event(window_object, event_name, event_init) , m_persisted(event_init.persisted) { diff --git a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h index febd7ccb2babfd8e3e380c67f1a01258c8219e2a..ed5ece0f2d384284c272a060451b93a77d6cef35 100644 --- a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h +++ b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h @@ -15,18 +15,16 @@ struct PageTransitionEventInit : public DOM::EventInit { }; class PageTransitionEvent final : public DOM::Event { - JS_OBJECT(PageTransitionEvent, DOM::Event); + WEB_PLATFORM_OBJECT(PageTransitionEvent, DOM::Event); public: - static PageTransitionEvent* create(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init); - static PageTransitionEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init); + static PageTransitionEvent* create(HTML::Window&, FlyString const& event_name, PageTransitionEventInit const& event_init); + static PageTransitionEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, PageTransitionEventInit const& event_init); - PageTransitionEvent(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init); + PageTransitionEvent(HTML::Window&, FlyString const& event_name, PageTransitionEventInit const& event_init); virtual ~PageTransitionEvent() override; - PageTransitionEvent& impl() { return *this; } - bool persisted() const { return m_persisted; } private: diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp index 9348c8ea7a724ee528f0f2bb288a0d2fe8034355..919070a59598c46ec00192bd4f490c6763e9caa1 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp @@ -96,7 +96,7 @@ Optional extract_character_encoding_from_meta_element(String const& return TextCodec::get_standardized_encoding(encoding); } -RefPtr prescan_get_attribute(DOM::Document& document, ByteBuffer const& input, size_t& position) +JS::GCPtr prescan_get_attribute(DOM::Document& document, ByteBuffer const& input, size_t& position) { if (!prescan_skip_whitespace_and_slashes(input, position)) return {}; @@ -111,7 +111,7 @@ RefPtr prescan_get_attribute(DOM::Document& document, ByteBuffer } else if (input[position] == '\t' || input[position] == '\n' || input[position] == '\f' || input[position] == '\r' || input[position] == ' ') goto spaces; else if (input[position] == '/' || input[position] == '>') - return DOM::Attribute::create(document, attribute_name.to_string(), ""); + return *DOM::Attribute::create(document, attribute_name.to_string(), ""); else attribute_name.append_as_lowercase(input[position]); ++position; diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h index 6cb9fc7e31bab8d97af29813c8c0315b15c7f67e..0bda305d1692648b8a2e7e5c2504c1cf55b18868 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h @@ -16,7 +16,7 @@ bool prescan_should_abort(ByteBuffer const& input, size_t const& position); bool prescan_is_whitespace_or_slash(u8 const& byte); bool prescan_skip_whitespace_and_slashes(ByteBuffer const& input, size_t& position); Optional extract_character_encoding_from_meta_element(String const&); -RefPtr prescan_get_attribute(DOM::Document&, ByteBuffer const& input, size_t& position); +JS::GCPtr prescan_get_attribute(DOM::Document&, ByteBuffer const& input, size_t& position); Optional run_prescan_byte_stream_algorithm(DOM::Document&, ByteBuffer const& input); String run_encoding_sniffing_algorithm(DOM::Document&, ByteBuffer const& input); diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index ee78f35d5d27adc0d31775c4537b6889eeae9a68..e37e78b68433520b1a8ac28e4988b0464209220c 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -120,7 +121,7 @@ static bool is_html_integration_point(DOM::Element const& element) HTMLParser::HTMLParser(DOM::Document& document, StringView input, String const& encoding) : m_tokenizer(input, encoding) - , m_document(document) + , m_document(JS::make_handle(document)) { m_tokenizer.set_parser({}, *this); m_document->set_parser({}, *this); @@ -131,7 +132,7 @@ HTMLParser::HTMLParser(DOM::Document& document, StringView input, String const& } HTMLParser::HTMLParser(DOM::Document& document) - : m_document(document) + : m_document(JS::make_handle(document)) { m_document->set_parser({}, *this); m_tokenizer.set_parser({}, *this); @@ -220,23 +221,23 @@ void HTMLParser::the_end() // 1. Spin the event loop until the first script in the list of scripts that will execute when the document has finished parsing // has its "ready to be parser-executed" flag set and the parser's Document has no style sheet that is blocking scripts. main_thread_event_loop().spin_until([&] { - return m_document->scripts_to_execute_when_parsing_has_finished().first().is_ready_to_be_parser_executed() + return m_document->scripts_to_execute_when_parsing_has_finished().first()->is_ready_to_be_parser_executed() && !m_document->has_a_style_sheet_that_is_blocking_scripts(); }); // 2. Execute the first script in the list of scripts that will execute when the document has finished parsing. - m_document->scripts_to_execute_when_parsing_has_finished().first().execute_script(); + m_document->scripts_to_execute_when_parsing_has_finished().first()->execute_script(); // 3. Remove the first script element from the list of scripts that will execute when the document has finished parsing (i.e. shift out the first entry in the list). (void)m_document->scripts_to_execute_when_parsing_has_finished().take_first(); } // 6. Queue a global task on the DOM manipulation task source given the Document's relevant global object to run the following substeps: - old_queue_global_task_with_document(HTML::Task::Source::DOMManipulation, m_document, [document = m_document]() mutable { + old_queue_global_task_with_document(HTML::Task::Source::DOMManipulation, *m_document, [document = m_document]() mutable { // FIXME: 1. Set the Document's load timing info's DOM content loaded event start time to the current high resolution time given the Document's relevant global object. // 2. Fire an event named DOMContentLoaded at the Document object, with its bubbles attribute initialized to true. - auto content_loaded_event = DOM::Event::create(document->preferred_window_object(), HTML::EventNames::DOMContentLoaded); + auto content_loaded_event = DOM::Event::create(document->window(), HTML::EventNames::DOMContentLoaded); content_loaded_event->set_bubbles(true); document->dispatch_event(*content_loaded_event); @@ -259,7 +260,7 @@ void HTMLParser::the_end() }); // 9. Queue a global task on the DOM manipulation task source given the Document's relevant global object to run the following steps: - old_queue_global_task_with_document(HTML::Task::Source::DOMManipulation, m_document, [document = m_document]() mutable { + old_queue_global_task_with_document(HTML::Task::Source::DOMManipulation, *m_document, [document = m_document]() mutable { // 1. Update the current document readiness to "complete". document->update_readiness(HTML::DocumentReadyState::Complete); @@ -268,14 +269,14 @@ void HTMLParser::the_end() return; // 3. Let window be the Document's relevant global object. - NonnullRefPtr window = document->window(); + JS::NonnullGCPtr window = document->window(); // FIXME: 4. Set the Document's load timing info's load event start time to the current high resolution time given window. // 5. Fire an event named load at window, with legacy target override flag set. // FIXME: The legacy target override flag is currently set by a virtual override of dispatch_event() // We should reorganize this so that the flag appears explicitly here instead. - window->dispatch_event(*DOM::Event::create(document->preferred_window_object(), HTML::EventNames::load)); + window->dispatch_event(*DOM::Event::create(document->window(), HTML::EventNames::load)); // FIXME: 6. Invoke WebDriver BiDi load complete with the Document's browsing context, and a new WebDriver BiDi navigation status whose id is the Document object's navigation id, status is "complete", and url is the Document object's URL. @@ -442,17 +443,17 @@ void HTMLParser::handle_initial(HTMLToken& token) } if (token.is_comment()) { - auto comment = adopt_ref(*new DOM::Comment(document(), token.comment())); - document().append_child(move(comment)); + auto comment = realm().heap().allocate(realm(), document(), token.comment()); + document().append_child(*comment); return; } if (token.is_doctype()) { - auto doctype = adopt_ref(*new DOM::DocumentType(document())); + auto doctype = realm().heap().allocate(realm(), document()); doctype->set_name(token.doctype_data().name); doctype->set_public_id(token.doctype_data().public_identifier); doctype->set_system_id(token.doctype_data().system_identifier); - document().append_child(move(doctype)); + document().append_child(*doctype); document().set_quirks_mode(which_quirks_mode(token)); m_insertion_mode = InsertionMode::BeforeHTML; return; @@ -472,8 +473,8 @@ void HTMLParser::handle_before_html(HTMLToken& token) } if (token.is_comment()) { - auto comment = adopt_ref(*new DOM::Comment(document(), token.comment())); - document().append_child(move(comment)); + auto comment = realm().heap().allocate(realm(), document(), token.comment()); + document().append_child(*comment); return; } @@ -483,7 +484,7 @@ void HTMLParser::handle_before_html(HTMLToken& token) if (token.is_start_tag() && token.tag_name() == HTML::TagNames::html) { auto element = create_element_for(token, Namespace::HTML, document()); - document().append_child(element); + document().append_child(*element); m_stack_of_open_elements.push(move(element)); m_insertion_mode = InsertionMode::BeforeHead; return; @@ -500,7 +501,7 @@ void HTMLParser::handle_before_html(HTMLToken& token) AnythingElse: auto element = create_element(document(), HTML::TagNames::html, Namespace::HTML); - document().append_child(element); + document().append_child(*element); m_stack_of_open_elements.push(element); // FIXME: If the Document is being loaded as part of navigation of a browsing context, then: run the application cache selection algorithm with no manifest, passing it the Document object. m_insertion_mode = InsertionMode::BeforeHead; @@ -523,11 +524,11 @@ DOM::Element& HTMLParser::adjusted_current_node() DOM::Element& HTMLParser::node_before_current_node() { - return m_stack_of_open_elements.elements().at(m_stack_of_open_elements.elements().size() - 2); + return *m_stack_of_open_elements.elements().at(m_stack_of_open_elements.elements().size() - 2); } // https://html.spec.whatwg.org/multipage/parsing.html#appropriate-place-for-inserting-a-node -HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_inserting_node(RefPtr override_target) +HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_inserting_node(JS::GCPtr override_target) { auto& target = override_target ? *override_target.ptr() : current_node(); HTMLParser::AdjustedInsertionLocation adjusted_insertion_location; @@ -546,7 +547,7 @@ HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_ins // then: let adjusted insertion location be inside last template's template contents, after its last child (if any), and abort these steps. // NOTE: This returns the template content, so no need to check the parent is a template. - return { verify_cast(last_template.element)->content(), nullptr }; + return { verify_cast(*last_template.element).content().ptr(), nullptr }; } // 4. If there is no last table, then let adjusted insertion location be inside the first element in the stack of open elements (the html element), // after its last child (if any), and abort these steps. (fragment case) @@ -554,17 +555,17 @@ HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_ins VERIFY(m_parsing_fragment); // Guaranteed not to be a template element (it will be the html element), // so no need to check the parent is a template. - return { m_stack_of_open_elements.elements().first(), nullptr }; + return { *m_stack_of_open_elements.elements().first(), nullptr }; } // 5. If last table has a parent node, then let adjusted insertion location be inside last table's parent node, immediately before last table, and abort these steps. if (last_table.element->parent_node()) { - adjusted_insertion_location = { last_table.element->parent_node(), last_table.element }; + adjusted_insertion_location = { last_table.element->parent_node(), last_table.element.ptr() }; } else { // 6. Let previous element be the element immediately above last table in the stack of open elements. auto previous_element = m_stack_of_open_elements.element_immediately_above(*last_table.element); // 7. Let adjusted insertion location be inside previous element, after its last child (if any). - adjusted_insertion_location = { previous_element, nullptr }; + adjusted_insertion_location = { previous_element.ptr(), nullptr }; } } else { // `-> Otherwise @@ -573,18 +574,18 @@ HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_ins } if (is(*adjusted_insertion_location.parent)) - return { verify_cast(*adjusted_insertion_location.parent).content(), nullptr }; + return { verify_cast(*adjusted_insertion_location.parent).content().ptr(), nullptr }; return adjusted_insertion_location; } -NonnullRefPtr HTMLParser::create_element_for(HTMLToken const& token, FlyString const& namespace_, DOM::Node const& intended_parent) +JS::NonnullGCPtr HTMLParser::create_element_for(HTMLToken const& token, FlyString const& namespace_, DOM::Node const& intended_parent) { // FIXME: 1. If the active speculative HTML parser is not null, then return the result of creating a speculative mock element given given namespace, the tag name of the given token, and the attributes of the given token. // FIXME: 2. Otherwise, optionally create a speculative mock element given given namespace, the tag name of the given token, and the attributes of the given token. // 3. Let document be intended parent's node document. - NonnullRefPtr document = intended_parent.document(); + JS::NonnullGCPtr document = intended_parent.document(); // 4. Let local name be the tag name of the token. auto local_name = token.tag_name(); @@ -600,7 +601,7 @@ NonnullRefPtr HTMLParser::create_element_for(HTMLToken const& toke // 9. Let element be the result of creating an element given document, localName, given namespace, null, and is. // FIXME: If will execute script is true, set the synchronous custom elements flag; otherwise, leave it unset. // FIXME: Pass in `null` and `is`. - auto element = create_element(document, local_name, namespace_); + auto element = create_element(*document, local_name, namespace_); // 10. Append each attribute in the given token to element. // FIXME: This isn't the exact `append` the spec is talking about. @@ -629,11 +630,11 @@ NonnullRefPtr HTMLParser::create_element_for(HTMLToken const& toke auto& html_element = form_associated_element->form_associated_element_to_html_element(); - if (m_form_element + if (m_form_element.ptr() && !m_stack_of_open_elements.contains(HTML::TagNames::template_) && (!form_associated_element->is_listed() || !html_element.has_attribute(HTML::AttributeNames::form)) && &intended_parent.root() == &m_form_element->root()) { - form_associated_element->set_form(m_form_element); + form_associated_element->set_form(m_form_element.ptr()); form_associated_element->set_parser_inserted({}); } } @@ -643,14 +644,14 @@ NonnullRefPtr HTMLParser::create_element_for(HTMLToken const& toke } // https://html.spec.whatwg.org/multipage/parsing.html#insert-a-foreign-element -NonnullRefPtr HTMLParser::insert_foreign_element(HTMLToken const& token, FlyString const& namespace_) +JS::NonnullGCPtr HTMLParser::insert_foreign_element(HTMLToken const& token, FlyString const& namespace_) { auto adjusted_insertion_location = find_appropriate_place_for_inserting_node(); // NOTE: adjusted_insertion_location.parent will be non-null, however, it uses RP to be able to default-initialize HTMLParser::AdjustedInsertionLocation. auto element = create_element_for(token, namespace_, *adjusted_insertion_location.parent); - auto pre_insertion_validity = adjusted_insertion_location.parent->ensure_pre_insertion_validity(element, adjusted_insertion_location.insert_before_sibling); + auto pre_insertion_validity = adjusted_insertion_location.parent->ensure_pre_insertion_validity(*element, adjusted_insertion_location.insert_before_sibling); // NOTE: If it's not possible to insert the element at the adjusted insertion location, the element is simply dropped. if (!pre_insertion_validity.is_exception()) { @@ -658,7 +659,7 @@ NonnullRefPtr HTMLParser::insert_foreign_element(HTMLToken const& // FIXME: push a new element queue onto element's relevant agent's custom element reactions stack. } - adjusted_insertion_location.parent->insert_before(element, adjusted_insertion_location.insert_before_sibling); + adjusted_insertion_location.parent->insert_before(*element, adjusted_insertion_location.insert_before_sibling); if (!m_parsing_fragment) { // FIXME: pop the element queue from element's relevant agent's custom element reactions stack, and invoke custom element reactions in that queue. @@ -669,7 +670,7 @@ NonnullRefPtr HTMLParser::insert_foreign_element(HTMLToken const& return element; } -NonnullRefPtr HTMLParser::insert_html_element(HTMLToken const& token) +JS::NonnullGCPtr HTMLParser::insert_html_element(HTMLToken const& token) { return insert_foreign_element(token, Namespace::HTML); } @@ -697,7 +698,7 @@ void HTMLParser::handle_before_head(HTMLToken& token) if (token.is_start_tag() && token.tag_name() == HTML::TagNames::head) { auto element = insert_html_element(token); - m_head_element = verify_cast(*element); + m_head_element = JS::make_handle(verify_cast(*element)); m_insertion_mode = InsertionMode::InHead; return; } @@ -712,7 +713,7 @@ void HTMLParser::handle_before_head(HTMLToken& token) } AnythingElse: - m_head_element = verify_cast(*insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::head))); + m_head_element = JS::make_handle(verify_cast(*insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::head)))); m_insertion_mode = InsertionMode::InHead; process_using_the_rules_for(InsertionMode::InHead, token); return; @@ -721,7 +722,7 @@ AnythingElse: void HTMLParser::insert_comment(HTMLToken& token) { auto adjusted_insertion_location = find_appropriate_place_for_inserting_node(); - adjusted_insertion_location.parent->insert_before(adopt_ref(*new DOM::Comment(document(), token.comment())), adjusted_insertion_location.insert_before_sibling); + adjusted_insertion_location.parent->insert_before(*realm().heap().allocate(realm(), document(), token.comment()), adjusted_insertion_location.insert_before_sibling); } void HTMLParser::handle_in_head(HTMLToken& token) @@ -754,7 +755,7 @@ void HTMLParser::handle_in_head(HTMLToken& token) } if (token.is_start_tag() && token.tag_name() == HTML::TagNames::meta) { - auto element = insert_html_element(token); + (void)insert_html_element(token); (void)m_stack_of_open_elements.pop(); token.acknowledge_self_closing_flag_if_set(); return; @@ -795,7 +796,7 @@ void HTMLParser::handle_in_head(HTMLToken& token) TODO(); } - adjusted_insertion_location.parent->insert_before(element, adjusted_insertion_location.insert_before_sibling, false); + adjusted_insertion_location.parent->insert_before(*element, adjusted_insertion_location.insert_before_sibling, false); m_stack_of_open_elements.push(element); m_tokenizer.switch_to({}, HTMLTokenizer::State::ScriptData); m_original_insertion_mode = m_insertion_mode; @@ -907,8 +908,8 @@ DOM::Text* HTMLParser::find_character_insertion_node() return nullptr; if (adjusted_insertion_location.parent->last_child() && adjusted_insertion_location.parent->last_child()->is_text()) return verify_cast(adjusted_insertion_location.parent->last_child()); - auto new_text_node = adopt_ref(*new DOM::Text(document(), "")); - adjusted_insertion_location.parent->append_child(new_text_node); + auto new_text_node = realm().heap().allocate(realm(), document(), ""); + adjusted_insertion_location.parent->append_child(*new_text_node); return new_text_node; } @@ -924,17 +925,17 @@ void HTMLParser::flush_character_insertions() void HTMLParser::insert_character(u32 data) { auto node = find_character_insertion_node(); - if (node == m_character_insertion_node) { + if (node == m_character_insertion_node.ptr()) { m_character_insertion_builder.append(Utf32View { &data, 1 }); return; } - if (!m_character_insertion_node) { - m_character_insertion_node = node; + if (!m_character_insertion_node.ptr()) { + m_character_insertion_node = JS::make_handle(node); m_character_insertion_builder.append(Utf32View { &data, 1 }); return; } flush_character_insertions(); - m_character_insertion_node = node; + m_character_insertion_node = JS::make_handle(node); m_character_insertion_builder.append(Utf32View { &data, 1 }); } @@ -978,7 +979,7 @@ void HTMLParser::handle_after_head(HTMLToken& token) m_stack_of_open_elements.push(*m_head_element); process_using_the_rules_for(InsertionMode::InHead, token); m_stack_of_open_elements.elements().remove_first_matching([&](auto& entry) { - return entry.ptr() == m_head_element; + return entry.ptr() == m_head_element.ptr(); }); return; } @@ -1033,7 +1034,7 @@ void HTMLParser::handle_after_body(HTMLToken& token) if (token.is_comment()) { auto& insertion_location = m_stack_of_open_elements.first(); - insertion_location.append_child(adopt_ref(*new DOM::Comment(document(), token.comment()))); + insertion_location.append_child(*realm().heap().allocate(realm(), document(), token.comment())); return; } @@ -1069,8 +1070,8 @@ void HTMLParser::handle_after_body(HTMLToken& token) void HTMLParser::handle_after_after_body(HTMLToken& token) { if (token.is_comment()) { - auto comment = adopt_ref(*new DOM::Comment(document(), token.comment())); - document().append_child(move(comment)); + auto comment = realm().heap().allocate(realm(), document(), token.comment()); + document().append_child(*comment); return; } @@ -1136,7 +1137,7 @@ Create: auto new_element = insert_html_element(HTMLToken::make_start_tag(entry->element->local_name())); // 9. Replace the entry for entry in the list with an entry for new element. - m_list_of_active_formatting_elements.entries().at(index).element = new_element; + m_list_of_active_formatting_elements.entries().at(index).element = JS::make_handle(new_element.ptr()); // 10. If the entry for new element in the list of active formatting elements is not the last entry in the list, return to the step labeled advance. if (index != m_list_of_active_formatting_elements.entries().size() - 1) @@ -1204,7 +1205,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a // 7. Let furthest block be the topmost node in the stack of open elements that is lower in the stack than formatting element, // and is an element in the special category. There might not be one. - RefPtr furthest_block = m_stack_of_open_elements.topmost_special_node_below(*formatting_element); + JS::GCPtr furthest_block = m_stack_of_open_elements.topmost_special_node_below(*formatting_element); // 8. If there is no furthest block if (!furthest_block) { @@ -1252,7 +1253,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a node_above_node = m_stack_of_open_elements.element_immediately_above(*node); // 3. If node is formatting element, then break. - if (node == formatting_element) + if (node.ptr() == formatting_element) break; // 4. If inner loop counter is greater than 3 and node is in the list of active formatting elements, @@ -1307,10 +1308,10 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a // 16. Take all of the child nodes of furthest block and append them to the element created in the last step. for (auto& child : furthest_block->children_as_vector()) - element->append_child(furthest_block->remove_child(child).release_value()); + element->append_child(furthest_block->remove_child(*child).release_value()); // 17. Append that new element to furthest block. - furthest_block->append_child(element); + furthest_block->append_child(*element); // 18. Remove formatting element from the list of active formatting elements, // and insert the new element into the list of active formatting elements at the position of the aforementioned bookmark. @@ -1477,7 +1478,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) if (token.is_start_tag() && token.tag_name() == HTML::TagNames::body) { log_parse_error(); if (m_stack_of_open_elements.elements().size() == 1 - || m_stack_of_open_elements.elements().at(1).local_name() != HTML::TagNames::body + || m_stack_of_open_elements.elements().at(1)->local_name() != HTML::TagNames::body || m_stack_of_open_elements.contains(HTML::TagNames::template_)) { VERIFY(m_parsing_fragment); return; @@ -1485,8 +1486,8 @@ void HTMLParser::handle_in_body(HTMLToken& token) m_frameset_ok = false; auto& body_element = m_stack_of_open_elements.elements().at(1); token.for_each_attribute([&](auto& attribute) { - if (!body_element.has_attribute(attribute.local_name)) - body_element.set_attribute(attribute.local_name, attribute.value); + if (!body_element->has_attribute(attribute.local_name)) + body_element->set_attribute(attribute.local_name, attribute.value); return IterationDecision::Continue; }); return; @@ -1496,7 +1497,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) log_parse_error(); if (m_stack_of_open_elements.elements().size() == 1 - || m_stack_of_open_elements.elements().at(1).local_name() != HTML::TagNames::body) { + || m_stack_of_open_elements.elements().at(1)->local_name() != HTML::TagNames::body) { VERIFY(m_parsing_fragment); return; } @@ -1514,7 +1515,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) } for (auto& node : m_stack_of_open_elements.elements()) { - if (!node.local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr, HTML::TagNames::body, HTML::TagNames::html)) { + if (!node->local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr, HTML::TagNames::body, HTML::TagNames::html)) { log_parse_error(); break; } @@ -1531,7 +1532,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) } for (auto& node : m_stack_of_open_elements.elements()) { - if (!node.local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr, HTML::TagNames::body, HTML::TagNames::html)) { + if (!node->local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr, HTML::TagNames::body, HTML::TagNames::html)) { log_parse_error(); break; } @@ -1548,7 +1549,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) } for (auto& node : m_stack_of_open_elements.elements()) { - if (!node.local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr, HTML::TagNames::body, HTML::TagNames::html)) { + if (!node->local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr, HTML::TagNames::body, HTML::TagNames::html)) { log_parse_error(); break; } @@ -1598,7 +1599,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) } if (token.is_start_tag() && token.tag_name() == HTML::TagNames::form) { - if (m_form_element && !m_stack_of_open_elements.contains(HTML::TagNames::template_)) { + if (m_form_element.ptr() && !m_stack_of_open_elements.contains(HTML::TagNames::template_)) { log_parse_error(); return; } @@ -1606,7 +1607,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) close_a_p_element(); auto element = insert_html_element(token); if (!m_stack_of_open_elements.contains(HTML::TagNames::template_)) - m_form_element = verify_cast(*element); + m_form_element = JS::make_handle(verify_cast(*element)); return; } @@ -1614,7 +1615,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) m_frameset_ok = false; for (ssize_t i = m_stack_of_open_elements.elements().size() - 1; i >= 0; --i) { - RefPtr node = m_stack_of_open_elements.elements()[i]; + JS::GCPtr node = m_stack_of_open_elements.elements()[i].ptr(); if (node->local_name() == HTML::TagNames::li) { generate_implied_end_tags(HTML::TagNames::li); @@ -1639,7 +1640,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) if (token.is_start_tag() && token.tag_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt)) { m_frameset_ok = false; for (ssize_t i = m_stack_of_open_elements.elements().size() - 1; i >= 0; --i) { - RefPtr node = m_stack_of_open_elements.elements()[i]; + JS::GCPtr node = m_stack_of_open_elements.elements()[i].ptr(); if (node->local_name() == HTML::TagNames::dd) { generate_implied_end_tags(HTML::TagNames::dd); if (current_node().local_name() != HTML::TagNames::dd) { @@ -1704,13 +1705,13 @@ void HTMLParser::handle_in_body(HTMLToken& token) if (token.is_end_tag() && token.tag_name() == HTML::TagNames::form) { if (!m_stack_of_open_elements.contains(HTML::TagNames::template_)) { auto node = m_form_element; - m_form_element = nullptr; + m_form_element = {}; if (!node || !m_stack_of_open_elements.has_in_scope(*node)) { log_parse_error(); return; } generate_implied_end_tags(); - if (¤t_node() != node) { + if (¤t_node() != node.ptr()) { log_parse_error(); } m_stack_of_open_elements.elements().remove_first_matching([&](auto& entry) { return entry.ptr() == node.ptr(); }); @@ -2049,15 +2050,15 @@ void HTMLParser::handle_in_body(HTMLToken& token) if (token.is_end_tag()) { AnyOtherEndTag: - RefPtr node; + JS::GCPtr node; for (ssize_t i = m_stack_of_open_elements.elements().size() - 1; i >= 0; --i) { - node = m_stack_of_open_elements.elements()[i]; + node = m_stack_of_open_elements.elements()[i].ptr(); if (node->local_name() == token.tag_name()) { generate_implied_end_tags(token.tag_name()); - if (node != current_node()) { + if (node.ptr() != ¤t_node()) { log_parse_error(); } - while (¤t_node() != node) { + while (¤t_node() != node.ptr()) { (void)m_stack_of_open_elements.pop(); } (void)m_stack_of_open_elements.pop(); @@ -2225,7 +2226,7 @@ void HTMLParser::handle_text(HTMLToken& token) // Make sure the