diff --git a/Documentation/Browser/AddNewIDLFile.md b/Documentation/Browser/AddNewIDLFile.md index 3147d361daf..7a59a345005 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 3cb9904719c..fe6edc907c6 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 92cbc751eac..435d7c6364e 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 775ff6d7739..ea2f9ae745f 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 b880ba1db5f..6a1210a9c59 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 19c962d0e9f..a385b74d6cf 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 1f764e6d233..00000000000 --- 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 5ebd48575ea..00000000000 --- 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 7ad5afadf1c..d4b2b9783c3 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 772daf0f248..d7f5be791a8 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 c8969d438e6..a8f459bb1b9 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 774fbfed70a..d625e19dceb 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 c7bb3ef3432..f6e27a511a6 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 52ed45fe8da..f803260011a 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 03c8954b8af..a9e230b89aa 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 88a473e7713..d3825618b6b 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 8a1b13e22f3..9448536055b 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 533ef5b9a39..8db25da83f0 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 32eb17d619c..3f5242ba222 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 62b58e9cb84..00000000000 --- 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 69bad2cc084..00000000000 --- 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 c4b7930f13f..8c0a9984c29 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 b334f152657..8c65fa9388c 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 dc4b4ff81c3..a866933dd4b 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 ef33827f171..909bd5e93b9 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 c9b530b425e..00000000000 --- 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 86cc00a6d44..ac4013b6d31 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 ae967d4d128..4865ba607aa 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 9d99573be7b..8f16471bc4e 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 04fffa57cda..f943bef8b1c 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 42f8c560aca..880fe3dead6 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 9f5efd78fdc..bc5e052b8ba 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 86b39899c9b..0ddb87938d6 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 29c2d1d1c52..47e1f8e8654 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 cd10d454018..9cb51a68acc 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 58d040a5ee2..f033d958770 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 f6b3f69086a..1d5d00aafa2 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 5967add8fcb..344d46b6a4e 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 e852b1ff446..707eab39649 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 a72b786b345..3616906120d 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 52c25953bbc..bb6ee1eb853 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 ac2cb26a38c..5c289c91f76 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 245a80bb84a..cb72a58e366 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 2c502a7e52f..a09a3dd5aa5 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 b3c8fcf351b..ab1e30dafbd 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 7b82ba62ce6..6394ec5338e 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 8aa7bf293c0..674383f4039 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 9f94bcc1d4d..76cab74c06c 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 e5b4644463e..1cb49c536a3 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 ac8a3e24716..6679125e8e4 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 47d829a36c6..15bb1463e17 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 27f2ced9cce..07292800a9c 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 1828e30f628..5d210155f7e 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 7712a13f3fa..fd6ca3685d6 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 602ca34768a..860f142115c 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 31e0dcac7b9..1cabc601f95 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 dbcea1fa353..7003b702b3e 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 4ffe4b91067..25a272c9397 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 74caf270132..bbcf17a2646 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 71f88439bb7..a302425c933 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 ed16e9d7120..6bd7b37606f 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 e934b9fd50f..e217559dc44 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 dd3cf53e556..dae4505fe68 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 088756d81af..004e665da86 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 061214295b9..d52749ce0ca 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 285e853bfd0..f1bd2021176 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 42ec7256024..b4458e72566 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 ea6de94951b..ce0e1abd9e2 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 ae5d5208897..894d0cdf857 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 5c5d2ff466b..3304962b9d2 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 c61fd648746..bcb3f470f9a 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 32e26d54a6a..18fa197ef0a 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 4e92ee301e7..76640bcf27b 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 dc616ecc671..bb597309e5d 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 dc28fb3d111..a4cf9b42698 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 3166e87a67d..572a8d453d0 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 { +class AbortSignal final : public EventTarget { + WEB_PLATFORM_OBJECT(AbortSignal, EventTarget); + public: - using WrapperType = Bindings::AbortSignalWrapper; - - using RefCounted::ref; - using RefCounted::unref; - - static NonnullRefPtr create() - { - return adopt_ref(*new AbortSignal()); - } - - static NonnullRefPtr create_with_global_object(Bindings::WindowObject&) - { - return AbortSignal::create(); - } + 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 357a0da71fb..28e45ba65ea 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 e0dded63728..ae97dc54be4 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 da29d7cdc06..122e3d1ce3d 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 1431d3083b5..4f9787fb0b5 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 bce61e89c34..5203875e96b 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 bf57d3fad05..a5b18c0cc07 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 ab1e1342716..929d4774904 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 5765ee3f3da..481ed6bf690 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 4493e41afb5..ca7b48ae1d6 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 9e79dd58699..b442edc0b2a 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 9696a311378..9f4c37ef3d6 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 1d5aefb56e7..0cf777aa74f 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 5111b346be3..50cfd7b63a2 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 29c53a1b59e..8ad08a11a1c 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 a5a9b5d5d55..87a3b744a8d 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 d3f113e1090..8240a300a97 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 2216cc2f463..afe7045c959 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 136cd83e1bb..9315e459eb2 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 4b3575920f3..439d9a36064 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 890caffbc34..658a5457cee 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 e53ace8fd82..dd180b8f4a0 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; - } - - m_in_removed_last_ref = false; - m_deletion_has_begun = true; - HTML::main_thread_event_loop().unregister_document({}, *this); +} - delete this; +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()); + + 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()); + + 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; } -Bindings::WindowObject& Document::preferred_window_object() const +CSS::StyleSheetList& Document::style_sheets() { - if (m_window && m_window->wrapper()) - return const_cast(*m_window->wrapper()); - return Bindings::main_thread_internal_window_object(); + if (!m_style_sheets) + m_style_sheets = CSS::StyleSheetList::create(*this); + return *m_style_sheets; +} + +CSS::StyleSheetList const& Document::style_sheets() const +{ + return const_cast(this)->style_sheets(); } } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index ccd0cd411f1..d0d90e87e71 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 67dc77eea22..58ceeb3f3c8 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 715e9c8bbf1..496ce67f9af 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 { + WEB_PLATFORM_OBJECT(DocumentFragment, ParentNode); + public: - using WrapperType = Bindings::DocumentFragmentWrapper; + static JS::NonnullGCPtr create_with_global_object(HTML::Window& window); - static NonnullRefPtr create_with_global_object(Bindings::WindowObject& 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 60043ea00c0..44771d859ef 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 ac8a17294fd..72cf923e7bb 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 1f03de4657a..e3b34b5fd6e 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 89816ef0eae..f540813aa13 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 { + WEB_PLATFORM_OBJECT(DocumentType, Node); + public: - using WrapperType = Bindings::DocumentTypeWrapper; + static JS::NonnullGCPtr create(Document&); - static NonnullRefPtr create(Document& document) - { - return adopt_ref(*new DocumentType(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 89fe06ce282..665bf4b40e1 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 7da6d5b849a..45aa9411e10 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 e1d7329db7a..350ab64d2fa 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 879b1e004b4..3c9ac81cbb1 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 5ccba65e31d..024fa0104f6 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 51e8533025c..d4cb3edd348 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 5112681d928..19a9bb9da37 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 09431927870..26db70fa00c 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 c20e87f79fb..58eb036cce7 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 9d94fb91290..cbd785643e5 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 c4f4bb7c63b..9f95e300944 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 ea1ceaa883e..eae346bf070 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 5c4c75f582b..6fd55576e46 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 f3723534626..451ed609801 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 544f3bc244b..5f191460941 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 1fe1c70a31e..4c35b9e2b02 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 e600ac58d9d..7a7e9e8114b 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 961220fda67..b222d9eaa41 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 ded0a0ec718..78fdbdb9c60 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 bcc41bc824d..3a80acc7489 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 d03d3402900..7cc33a63b68 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 b3825ccee82..fc08dac50d7 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 d0e7354d69c..f4d4b90120d 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 { +class Node : public EventTarget { + WEB_PLATFORM_OBJECT(Node, EventTarget); + public: - using WrapperType = Bindings::NodeWrapper; - - using TreeNode::ref; - using TreeNode::unref; - 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 d1dbec91369..5f02bb1cb5f 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 89b7aa13540..5ecf0286504 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 a0421dc179b..f57e7777dbc 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 a6296306941..e3ce0c308ec 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 d377991ad1a..0f368439437 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 251a320104f..fe9817e58e8 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 59c1ef65cbe..20dccb37c3f 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 16f65efa419..de7fdd699a8 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 7790e8e1e2a..8f256c5b18e 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 45ef6768a76..fd9847b8c42 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 5bc6706dafb..a2196f9e31c 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 eb8d1bceb8b..d362577c365 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 a63b0e4baf4..50edff1233a 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 ea561e7b4ce..b01e1562776 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 ec3707cdae2..fdcdfca9a6a 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 0ea249f685f..829aca3cce5 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 6027b4195e6..8d825110eea 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 7f44aefb271..c6c27b0aa6c 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 3225e9d6b02..0b8262cd264 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 44762c8e559..aff7c91e3e9 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 88f88af449e..7021233b114 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 076c6511aae..e43f7c21f2b 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 d869dc717e5..a92e187aa24 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 55175e9d470..9689d4edcc4 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 71ae4e6ec92..ed1f1944931 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 1157ea47637..ca0d875e55a 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 36e6840efda..729c30fae1e 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 dc395961478..aa3882d5cc6 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 828bb6758bc..05da7534722 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 573330e83b2..69f912e00fe 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 1604fd6a6eb..0513db6eae6 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 4498789aefe..b982869ed2e 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 636a620b32b..43a80080551 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 1e4cfde06f5..dac3d923212 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 ea75d9a36b0..ccea076ebb6 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 5b088a41eb4..b9587058aec 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 dd46bec587f..057ea1ca36d 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 1581ef63181..148ed1044fb 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 f9aedf85630..4af36b5b92e 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 f48ef6d4f5d..ddcd870ea19 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 5cdc7ca4974..80228438acd 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 056620565c8..3a6ab3cebc9 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 d748ba86a77..5aa89d10cb7 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 ef494957362..fea84804e5f 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 3fecfb3fadd..639e6dba4ed 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 6a1a0f9c6e6..047cac83062 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 db3f1ba2b1c..0930a7b0d0c 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 7fc9d22c629..1f661a4ffd9 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 4df6ba2d5b4..4c1c50f7087 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 3e276996ed2..6b6a0a85c31 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 902037a2dbe..c01294c2e90 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 111f96a13d2..7a9654c538b 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 83b137f4979..ed978add811 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 8e421c3e88d..612df300417 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 acded61637d..34978bc6c33 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 fbe0ec929d9..61685ae6d6d 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 4e9a49b385f..600b76fe6ac 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 22aaa8c10a9..46de9950699 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 3b2533fd136..8c19a47fab4 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 a936e7c0276..1b1aad0536b 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 ea9b6ff47d4..c941ef98bc9 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 fecfb33af8a..170524ce7a8 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 1492fe4288e..97befd800fc 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 498d43cdcf5..4820124a076 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 { -public: - using WrapperType = Bindings::HTMLAudioElementWrapper; + WEB_PLATFORM_OBJECT(HTMLAudioElement, HTMLMediaElement); - HTMLAudioElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLAudioElement() override; + +private: + HTMLAudioElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLAudioElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp index d83f910fa13..9cf419290ae 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 0c8b911158c..d44f986c5af 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 afb6d0e2926..66f3b44bed5 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 0c904246cb1..f32b9f5b6b3 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 1a4cf3d456c..39bb55d6114 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 5d2bc8959d6..17b4bc7a768 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 e916ecad46e..302fbe58a49 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 419f4a607c2..e8c9399a46a 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 3c084198565..6ca9e78b151 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 8da131068d1..79b9924935b 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 b44d558d8fd..e280e16342d 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 3664d3d32a7..d2a3d975e94 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 { -public: - using WrapperType = Bindings::HTMLDListElementWrapper; + WEB_PLATFORM_OBJECT(HTMLDListElement, HTMLElement); - HTMLDListElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLDListElement() override; + +private: + HTMLDListElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLDListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp index 39f81e6e2c2..4740335f44a 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 3270881f21d..7ad0fec7fd5 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 { -public: - using WrapperType = Bindings::HTMLDataElementWrapper; + WEB_PLATFORM_OBJECT(HTMLDataElement, HTMLElement); - HTMLDataElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLDataElement() override; + +private: + HTMLDataElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLDataElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp index c12efcd6a22..b3866d30fb8 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 d7af3b3141b..26e96a83df5 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 { -public: - using WrapperType = Bindings::HTMLDataListElementWrapper; + WEB_PLATFORM_OBJECT(HTMLDataListElement, HTMLElement); - HTMLDataListElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLDataListElement() override; + +private: + HTMLDataListElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLDataListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp index ce365af0981..f2d6ac5a777 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 9929e1e712d..499e9d03be3 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 { -public: - using WrapperType = Bindings::HTMLDetailsElementWrapper; + WEB_PLATFORM_OBJECT(HTMLDetailsElement, HTMLElement); - HTMLDetailsElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLDetailsElement() override; + +private: + HTMLDetailsElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLDetailsElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp index 5885e8ef082..9aa1666f03f 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 8684fb8ca6b..ad522374f61 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 { -public: - using WrapperType = Bindings::HTMLDialogElementWrapper; + WEB_PLATFORM_OBJECT(HTMLDialogElement, HTMLElement); - HTMLDialogElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLDialogElement() override; + +private: + HTMLDialogElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLDialogElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp index c75726db6d3..743a234ba63 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 460415684d0..7fac25e12c7 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 { -public: - using WrapperType = Bindings::HTMLDirectoryElementWrapper; + WEB_PLATFORM_OBJECT(HTMLDirectoryElement, HTMLElement); - HTMLDirectoryElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLDirectoryElement() override; + +private: + HTMLDirectoryElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLDirectoryElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp index 74f61436651..22bc02ebc5d 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 01a28bf2d37..76e154560a8 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 { -public: - using WrapperType = Bindings::HTMLDivElementWrapper; + WEB_PLATFORM_OBJECT(HTMLDivElement, HTMLElement); - HTMLDivElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLDivElement() override; + +private: + HTMLDivElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLDivElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index 592f354d46b..05350872c72 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 1c0376668e0..a40cd1cfd18 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 75f9cd9b984..d6d036c1b85 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 4c68838800d..f69e14744a7 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 { -public: - using WrapperType = Bindings::HTMLEmbedElementWrapper; + WEB_PLATFORM_OBJECT(HTMLEmbedElement, HTMLElement); - HTMLEmbedElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLEmbedElement() override; + +private: + HTMLEmbedElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLEmbedElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp index 2d3db560f13..fe2f968a66e 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 1cb3a6c06c4..146904a7de3 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 a0c139863cb..f969f036584 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 401019fde1d..7b4e2e7f21b 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 6f1b96b9eac..b9ea743329d 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 cd0a192a79b..d548bf41e98 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 6ac1110c6b0..c5ae687c058 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 39087a69698..505b1122138 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 { -public: - using WrapperType = Bindings::HTMLFrameElementWrapper; + WEB_PLATFORM_OBJECT(HTMLFrameElement, HTMLElement); - HTMLFrameElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLFrameElement() override; + +private: + HTMLFrameElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLFrameElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp index bf7d86accda..52d06e95400 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 3a4088d9976..8ff5a34c83e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h @@ -15,12 +15,14 @@ namespace Web::HTML { class HTMLFrameSetElement final : public HTMLElement , public WindowEventHandlers { -public: - using WrapperType = Bindings::HTMLFrameSetElementWrapper; + WEB_PLATFORM_OBJECT(HTMLFrameSetElement, HTMLElement); - HTMLFrameSetElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLFrameSetElement() override; +private: + HTMLFrameSetElement(DOM::Document&, DOM::QualifiedName); + virtual void parse_attribute(FlyString const&, String const&) override; private: @@ -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 170973715a2..89d19cb1e5b 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 69f5649ea91..21accb7746a 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 { -public: - using WrapperType = Bindings::HTMLHRElementWrapper; + WEB_PLATFORM_OBJECT(HTMLHRElement, HTMLElement); - HTMLHRElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLHRElement() override; + +private: + HTMLHRElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLHRElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp index e4533b21581..fa351267972 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 e2faf9a5c65..9996aa230bd 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 { -public: - using WrapperType = Bindings::HTMLHeadElementWrapper; + WEB_PLATFORM_OBJECT(HTMLHeadElement, HTMLElement); - HTMLHeadElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLHeadElement() override; + +private: + HTMLHeadElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLHeadElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp index 10b1c9b7d66..28b276f17ad 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 d5c7644a798..5deffd89854 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 { -public: - using WrapperType = Bindings::HTMLHeadingElementWrapper; + WEB_PLATFORM_OBJECT(HTMLHeadingElement, HTMLElement); - HTMLHeadingElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLHeadingElement() override; + +private: + HTMLHeadingElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLHeadingElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp index 179c4d0b9b6..90fe7f8c52f 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 1222355040d..0f8c6b3c5fd 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 83b6fb3c45b..2ee367455e5 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 34149e50ed4..f9728145e51 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 6a2ecb60f4c..4e2d0d39117 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 046a29fd648..88026331fdb 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 66557d5cae7..4ca7cc2f057 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 543295b653a..4b7f3c18491 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 2c166fabd4d..1c85241a0aa 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 071f1f8927c..4eb8572ff17 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 { -public: - using WrapperType = Bindings::HTMLLIElementWrapper; + WEB_PLATFORM_OBJECT(HTMLLIElement, HTMLElement); - HTMLLIElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLLIElement() override; + +private: + HTMLLIElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLLIElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp index 71f73e2b4e4..31398d3c902 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 cae5adb9ce2..2cc266cd866 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 48247dba260..7cdaae70162 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 5acdbec2d15..aea891af7b6 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 { -public: - using WrapperType = Bindings::HTMLLegendElementWrapper; + WEB_PLATFORM_OBJECT(HTMLLegendElement, HTMLElement); - HTMLLegendElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLLegendElement() override; + +private: + HTMLLegendElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLLegendElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp index 345011dcc5b..c2365ab4298 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 844bba4149b..ef8055adde5 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 b8c68863f64..e02e7374f0d 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 bf66b802399..84dd4211acb 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 { -public: - using WrapperType = Bindings::HTMLMapElementWrapper; + WEB_PLATFORM_OBJECT(HTMLMapElement, HTMLElement); - HTMLMapElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLMapElement() override; + +private: + HTMLMapElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLMapElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp index c70c667b12c..9c9bebbb465 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 556dfa1fae1..9183ba73f78 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 545984dae14..2d53b2e716b 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 ed5bb41b5b4..331a2f53c3c 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 5b8405ff90a..65528d30785 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 f05e3ab935a..f1ae4a7833d 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 { -public: - using WrapperType = Bindings::HTMLMenuElementWrapper; + WEB_PLATFORM_OBJECT(HTMLMenuElement, HTMLElement); - HTMLMenuElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLMenuElement() override; + +private: + HTMLMenuElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLMenuElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp index 6812c460229..66eaf3cc03b 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 0e2a7e18838..62ac9dcdf78 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 { -public: - using WrapperType = Bindings::HTMLMetaElementWrapper; + WEB_PLATFORM_OBJECT(HTMLMetaElement, HTMLElement); - HTMLMetaElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLMetaElement() override; + +private: + HTMLMetaElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLMetaElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp index 0341aac4bb1..6d33d2e4141 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 7877ea7f58e..28474b4234e 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 4201d8b316d..b4d7325868f 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 b8126fa1c14..64044da1454 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 { -public: - using WrapperType = Bindings::HTMLModElementWrapper; + WEB_PLATFORM_OBJECT(HTMLModElement, HTMLElement); - HTMLModElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLModElement() override; + +private: + HTMLModElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLModElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp index 90ddc29efc8..a397c00a574 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 25eb96b4861..a320b94fa2d 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 { -public: - using WrapperType = Bindings::HTMLOListElementWrapper; + WEB_PLATFORM_OBJECT(HTMLOListElement, HTMLElement); - HTMLOListElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLOListElement() override; + +private: + HTMLOListElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLOListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index baea9234266..678a058256b 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 9b8b7aa558c..d0d784beab8 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 f44d2fcad07..ce45d467f22 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 648d9a686c2..2460f1fe253 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 dc04138cb1b..87427b56981 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 { -public: - using WrapperType = Bindings::HTMLOptGroupElementWrapper; + WEB_PLATFORM_OBJECT(HTMLOptGroupElement, HTMLElement); - HTMLOptGroupElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLOptGroupElement() override; + +private: + HTMLOptGroupElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLOptGroupElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp index 8f4fed8b60f..06c27df4b9c 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 8b83003ced5..79aade13c3e 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 01a7fa79e48..b3d75892231 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 105009b4ff3..e27b2491e3b 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 e9fcc6a941c..b5f8f5d07de 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 fb3ad802d00..9b75d179492 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 2e93713cb6b..b8dabd218ab 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 9d03daf490f..1a86e50e4e5 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 { -public: - using WrapperType = Bindings::HTMLParagraphElementWrapper; + WEB_PLATFORM_OBJECT(HTMLParagraphElement, HTMLElement); - HTMLParagraphElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLParagraphElement() override; + +private: + HTMLParagraphElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLParagraphElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp index 93c88d92b3c..9e41a5f4024 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 e13ae0a2ea6..524580ed44e 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 { -public: - using WrapperType = Bindings::HTMLParamElementWrapper; + WEB_PLATFORM_OBJECT(HTMLParamElement, HTMLElement); - HTMLParamElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLParamElement() override; + +private: + HTMLParamElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLParamElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp index c6e3bbea723..6dcd14db66c 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 72bf00d8be5..37f34c3725d 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 { -public: - using WrapperType = Bindings::HTMLPictureElementWrapper; + WEB_PLATFORM_OBJECT(HTMLPictureElement, HTMLElement); - HTMLPictureElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLPictureElement() override; + +private: + HTMLPictureElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLPictureElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp index b098384bcc9..400e9978aba 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 fa8f24887bd..9797ea25da5 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 62abdd9f959..d3e8bcd5008 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 f1af0fd1b6f..d1cc612ef32 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 552ecdfce77..daed2603af6 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 ea25c54144f..7a38ce478c7 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 { -public: - using WrapperType = Bindings::HTMLQuoteElementWrapper; + WEB_PLATFORM_OBJECT(HTMLQuoteElement, HTMLElement); - HTMLQuoteElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLQuoteElement() override; + +private: + HTMLQuoteElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLQuoteElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp index fee2ba9df53..3b6f000e0f7 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 fbaa5eab518..0ff4f977a61 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 94333e018df..25027acd4d2 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 cbb19ec9ba9..86b42eb07ec 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 e3c72331df0..36d316516c3 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 c0564dc02ff..795ad075586 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 { -public: - using WrapperType = Bindings::HTMLSlotElementWrapper; + WEB_PLATFORM_OBJECT(HTMLSlotElement, HTMLElement); - HTMLSlotElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLSlotElement() override; + +private: + HTMLSlotElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLSlotElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp index f682bf46e07..38c3172e567 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 196a6041e73..65df7a40046 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 { -public: - using WrapperType = Bindings::HTMLSourceElementWrapper; + WEB_PLATFORM_OBJECT(HTMLSourceElement, HTMLElement); - HTMLSourceElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLSourceElement() override; + +private: + HTMLSourceElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLSourceElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp index 1fb05693d41..8f3c0177f46 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 aa7b7a1d726..3b67123ced0 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 { -public: - using WrapperType = Bindings::HTMLSpanElementWrapper; + WEB_PLATFORM_OBJECT(HTMLSpanElement, HTMLElement); - HTMLSpanElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLSpanElement() override; + +private: + HTMLSpanElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLSpanElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp index f7655da00d9..1013e8b2bf9 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 e12d1dd3ec4..9e1bfd268f3 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 542de9fda5a..27b7a0d80d9 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 c813366dd89..0761306f7eb 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 { -public: - using WrapperType = Bindings::HTMLTableCaptionElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTableCaptionElement, HTMLElement); - HTMLTableCaptionElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTableCaptionElement() override; + +private: + HTMLTableCaptionElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLTableCaptionElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp index 936512dc974..9f97fa75409 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 1393e344d40..d6fd5104dce 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 97dfc3f6df1..f48bbbb9bca 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 ee60076a199..21e397f14b4 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 { -public: - using WrapperType = Bindings::HTMLTableColElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTableColElement, HTMLElement); - HTMLTableColElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTableColElement() override; + +private: + HTMLTableColElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLTableColElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp index 447005b95d9..e3da69c0d36 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 cd166087db6..1b6840d88e4 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 107d8073596..307cc5cc8c1 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 065244ec7a0..03b6cb1eb2e 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 326dffa95d1..6e66c9d33cf 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 98642fdde34..112a92a9ffb 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 2b6a9a6a1a3..b32e5a8dd93 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 b00dc90bf7a..9c1c2e712e3 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 e9c0db91d44..70ea1f21d09 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 f8705b25517..f0d64e82b9a 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 c40869599f0..94647997409 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 762b495a8ed..494f42d1aff 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 { -public: - using WrapperType = Bindings::HTMLTimeElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTimeElement, HTMLElement); - HTMLTimeElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTimeElement() override; + +private: + HTMLTimeElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLTimeElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp index 0942f0d6d10..e5568632788 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 564401792b9..7b4bc137505 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 944dbdbb095..eadfacaf69c 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 2996f6a120a..f3655e2dfe7 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 { -public: - using WrapperType = Bindings::HTMLTrackElementWrapper; + WEB_PLATFORM_OBJECT(HTMLTrackElement, HTMLElement); - HTMLTrackElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLTrackElement() override; + +private: + HTMLTrackElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLTrackElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp index 80c68a724f5..71eb3820a96 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 d2838c75762..fa7f609bd0d 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 { -public: - using WrapperType = Bindings::HTMLUListElementWrapper; + WEB_PLATFORM_OBJECT(HTMLUListElement, HTMLElement); - HTMLUListElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLUListElement() override; + +private: + HTMLUListElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLUListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp index 1274e0a9bf7..b5df91ad7dd 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 6d36dbbc1de..dc5e518a030 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 { -public: - using WrapperType = Bindings::HTMLUnknownElementWrapper; + WEB_PLATFORM_OBJECT(HTMLUnknownElement, HTMLElement); - HTMLUnknownElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLUnknownElement() override; + +private: + HTMLUnknownElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLUnknownElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp index eb34e7c8c07..76b3941e27b 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 de4e292113e..e16de819c35 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 { -public: - using WrapperType = Bindings::HTMLVideoElementWrapper; + WEB_PLATFORM_OBJECT(HTMLVideoElement, HTMLMediaElement); - HTMLVideoElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~HTMLVideoElement() override; + +private: + HTMLVideoElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(HTMLVideoElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp b/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp index cb877324f9b..8c74020b78a 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 1d212db9334..7ac38e3912d 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 8fa050904d8..b993d22a66c 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 5671f8bd01e..6d7d180d93a 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 b6938d69091..9e4bb941010 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 3cebac0aa29..9380b6f9a5c 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 { +class MessagePort final : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget); + public: - using WrapperType = Bindings::MessagePortWrapper; - - using RefCounted::ref; - using RefCounted::unref; - - static NonnullRefPtr create() - { - return adopt_ref(*new MessagePort()); - } + 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 95d1e6a922d..450be24913c 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 febd7ccb2ba..ed5ece0f2d3 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 9348c8ea7a7..919070a5959 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 6cb9fc7e31b..0bda305d169 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 ee78f35d5d2..e37e78b6843 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