diff options
author | Andreas Kling <kling@serenityos.org> | 2022-08-28 13:42:07 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-09-06 00:27:09 +0200 |
commit | 6f433c86564c24d47d520cb5bdcc2209d724ac96 (patch) | |
tree | 886a2f727782e466e99c61c628637872c1b7403f | |
parent | bb547ce1c4251e3689287eac845593398a379ca5 (diff) | |
download | serenity-6f433c86564c24d47d520cb5bdcc2209d724ac96.zip |
LibWeb+LibJS: Make the EventTarget hierarchy (incl. DOM) GC-allocated
This is a monster patch that turns all EventTargets into GC-allocated
PlatformObjects. Their C++ wrapper classes are removed, and the LibJS
garbage collector is now responsible for their lifetimes.
There's a fair amount of hacks and band-aids in this patch, and we'll
have a lot of cleanup to do after this.
445 files changed, 4759 insertions, 4230 deletions
diff --git a/Documentation/Browser/AddNewIDLFile.md b/Documentation/Browser/AddNewIDLFile.md index 3147d361da..7a59a34500 100644 --- a/Documentation/Browser/AddNewIDLFile.md +++ b/Documentation/Browser/AddNewIDLFile.md @@ -38,10 +38,5 @@ interface CSSRule { - It must inherit from `public RefCounted<HTMLDetailsElement>` 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 3cb9904719..fe6edc907c 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<NonnullRefPtr<@parameter.type.name@>> @cpp_name@; + Optional<JS::NonnullGCPtr<@parameter.type.name@>> @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::TypeError>(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 "<unknown>"; - }; -} -)~~~"); - } - 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 <LibWeb/Bindings/@wrapper_class@.h> #endif #include <LibWeb/Bindings/ExceptionOrUtils.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> )~~~"); 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<WindowObject&>(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")) + : Wrapper(verify_cast<HTML::Window>(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<WindowObject&>(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")); + set_prototype(&verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")); } )~~~"); } @@ -2902,11 +2916,8 @@ void generate_constructor_implementation(IDL::Interface const& interface) #if __has_include(<LibWeb/Bindings/@wrapper_class@.h>) #include <LibWeb/Bindings/@wrapper_class@.h> #endif -#include <LibWeb/Bindings/EventTargetWrapperFactory.h> #include <LibWeb/Bindings/ExceptionOrUtils.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #if __has_include(<LibWeb/Crypto/@name@.h>) # include <LibWeb/Crypto/@name@.h> #elif __has_include(<LibWeb/CSS/@name@.h>) @@ -3007,7 +3018,7 @@ JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject auto& vm = this->vm(); [[maybe_unused]] auto& realm = *vm.current_realm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); )~~~"); if (!constructor.parameters.is_empty()) { @@ -3039,7 +3050,7 @@ JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject void @constructor_class@::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(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 "<unknown>"; + }; +} +)~~~"); + } + generator.append(R"~~~( } // namespace Web::Bindings )~~~"); @@ -3208,10 +3257,8 @@ void generate_prototype_implementation(IDL::Interface const& interface) #endif #include <LibWeb/Bindings/ExceptionOrUtils.h> #include <LibWeb/Bindings/LocationObject.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Bindings/WorkerLocationWrapper.h> #include <LibWeb/Bindings/WorkerNavigatorWrapper.h> -#include <LibWeb/Bindings/WorkerWrapper.h> #include <LibWeb/DOM/Element.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/IDLEventListener.h> @@ -3266,7 +3313,7 @@ namespace Web::Bindings { )~~~"); } else if (!interface.parent_name.is_empty()) { generator.append(R"~~~( - : Object(static_cast<WindowObject&>(realm.global_object()).ensure_web_prototype<@prototype_base_class@>("@parent_name@")) + : Object(verify_cast<HTML::Window>(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<WindowObject>(this_object)) { - return &static_cast<WindowObject*>(this_object)->impl(); + if (is<HTML::Window>(this_object)) { + return &static_cast<HTML::Window*>(this_object)->impl(); } )~~~"); } @@ -3686,7 +3733,7 @@ void generate_iterator_implementation(IDL::Interface const& interface) #include <LibWeb/Bindings/@wrapper_class@.h> #endif #include <LibWeb/Bindings/IDLAbstractOperations.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> )~~~"); @@ -3720,7 +3767,7 @@ namespace Web::Bindings { } @wrapper_class@::@wrapper_class@(JS::Realm& realm, @fully_qualified_name@& impl) - : Wrapper(static_cast<WindowObject&>(realm.global_object()).ensure_web_prototype<@prototype_class@>("@name@")) + : Wrapper(verify_cast<HTML::Window>(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 <LibJS/Runtime/TypedArray.h> #include <LibWeb/Bindings/@prototype_class@.h> #include <LibWeb/Bindings/ExceptionOrUtils.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #if __has_include(<LibWeb/@possible_include_path@.h>) # include <LibWeb/@possible_include_path@.h> diff --git a/Userland/Libraries/LibJS/Heap/Heap.h b/Userland/Libraries/LibJS/Heap/Heap.h index 92cbc751ea..435d7c6364 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.h +++ b/Userland/Libraries/LibJS/Heap/Heap.h @@ -20,7 +20,6 @@ #include <LibJS/Heap/CellAllocator.h> #include <LibJS/Heap/Handle.h> #include <LibJS/Heap/MarkedVector.h> -#include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/WeakContainer.h> namespace JS { diff --git a/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp index 775ff6d773..ea2f9ae745 100644 --- a/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/AudioConstructor.cpp @@ -6,9 +6,8 @@ #include <LibWeb/Bindings/AudioConstructor.h> #include <LibWeb/Bindings/HTMLAudioElementPrototype.h> -#include <LibWeb/Bindings/HTMLAudioElementWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> #include <LibWeb/DOM/ElementFactory.h> +#include <LibWeb/HTML/Scripting/Environments.h> #include <LibWeb/HTML/Window.h> #include <LibWeb/Namespace.h> @@ -22,7 +21,7 @@ AudioConstructor::AudioConstructor(JS::Realm& realm) void AudioConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<HTMLAudioElementPrototype>("HTMLAudioElement"), 0); @@ -38,10 +37,9 @@ JS::ThrowCompletionOr<JS::Value> AudioConstructor::call() JS::ThrowCompletionOr<JS::Object*> 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<WindowObject&>(HTML::current_global_object()); + auto& window = verify_cast<HTML::Window>(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<JS::Object*> 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 b880ba1db5..6a1210a9c5 100644 --- a/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.cpp @@ -17,14 +17,14 @@ #include <LibWeb/Bindings/DOMExceptionWrapper.h> #include <LibWeb/Bindings/LocationObject.h> #include <LibWeb/Bindings/MainThreadVM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/HTML/Scripting/Environments.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { // 7.2.3.1 CrossOriginProperties ( O ), https://html.spec.whatwg.org/multipage/browsers.html#crossoriginproperties-(-o-) -Vector<CrossOriginProperty> cross_origin_properties(Variant<LocationObject const*, WindowObject const*> const& object) +Vector<CrossOriginProperty> cross_origin_properties(Variant<LocationObject const*, HTML::Window const*> const& object) { // 1. Assert: O is a Location or Window object. @@ -37,7 +37,7 @@ Vector<CrossOriginProperty> cross_origin_properties(Variant<LocationObject const }; }, // 3. Return « { [[Property]]: "window", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "self", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "location", [[NeedsGet]]: true, [[NeedsSet]]: true }, { [[Property]]: "close" }, { [[Property]]: "closed", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "focus" }, { [[Property]]: "blur" }, { [[Property]]: "frames", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "length", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "top", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "opener", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "parent", [[NeedsGet]]: true, [[NeedsSet]]: false }, { [[Property]]: "postMessage" } ». - [](WindowObject const*) -> Vector<CrossOriginProperty> { + [](HTML::Window const*) -> Vector<CrossOriginProperty> { 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<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<LocationObject*, WindowObject*> const& object, JS::PropertyKey const& property_key) +Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<LocationObject*, HTML::Window*> 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<JS::Object const*>(o); }); - auto const object_const_variant = object.visit([](auto* o) { return Variant<LocationObject const*, WindowObject const*> { o }; }); + auto const object_const_variant = object.visit([](auto* o) { return Variant<LocationObject const*, HTML::Window const*> { 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<bool> 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<JS::Value> cross_origin_own_property_keys(Variant<LocationObject const*, WindowObject const*> const& object) +JS::MarkedVector<JS::Value> cross_origin_own_property_keys(Variant<LocationObject const*, HTML::Window const*> 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 19c962d0e9..a385b74d6c 100644 --- a/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.h +++ b/Userland/Libraries/LibWeb/Bindings/CrossOriginAbstractOperations.h @@ -9,6 +9,7 @@ #include <AK/Forward.h> #include <AK/Traits.h> #include <LibJS/Forward.h> +#include <LibJS/Runtime/PropertyKey.h> #include <LibWeb/Forward.h> namespace Web::Bindings { @@ -27,14 +28,14 @@ struct CrossOriginKey { using CrossOriginPropertyDescriptorMap = HashMap<CrossOriginKey, JS::PropertyDescriptor>; -Vector<CrossOriginProperty> cross_origin_properties(Variant<LocationObject const*, WindowObject const*> const&); +Vector<CrossOriginProperty> cross_origin_properties(Variant<LocationObject const*, HTML::Window const*> const&); bool is_cross_origin_accessible_window_property_name(JS::PropertyKey const&); JS::ThrowCompletionOr<JS::PropertyDescriptor> cross_origin_property_fallback(JS::VM&, JS::PropertyKey const&); bool is_platform_object_same_origin(JS::Object const&); -Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<LocationObject*, WindowObject*> const&, JS::PropertyKey const&); +Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<LocationObject*, HTML::Window*> const&, JS::PropertyKey const&); JS::ThrowCompletionOr<JS::Value> cross_origin_get(JS::VM&, JS::Object const&, JS::PropertyKey const&, JS::Value receiver); JS::ThrowCompletionOr<bool> cross_origin_set(JS::VM&, JS::Object&, JS::PropertyKey const&, JS::Value, JS::Value receiver); -JS::MarkedVector<JS::Value> cross_origin_own_property_keys(Variant<LocationObject const*, WindowObject const*> const&); +JS::MarkedVector<JS::Value> cross_origin_own_property_keys(Variant<LocationObject const*, HTML::Window const*> const&); } diff --git a/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.cpp deleted file mode 100644 index 1f764e6d23..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <LibWeb/Bindings/EventTargetWrapperFactory.h> -#include <LibWeb/DOM/EventTarget.h> - -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 5ebd48575e..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventTargetWrapperFactory.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <LibJS/Forward.h> -#include <LibWeb/Forward.h> - -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 7ad5afadf1..d4b2b9783c 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<JS::Va { auto& function_object = callback.callback; - JS::MarkedVector<JS::Value> arguments_list { function_object->vm().heap() }; + JS::MarkedVector<JS::Value> arguments_list { function_object.vm().heap() }; (arguments_list.append(forward<Args>(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 772daf0f24..d7f5be791a 100644 --- a/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp @@ -5,10 +5,9 @@ */ #include <LibWeb/Bindings/HTMLImageElementPrototype.h> -#include <LibWeb/Bindings/HTMLImageElementWrapper.h> #include <LibWeb/Bindings/ImageConstructor.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> #include <LibWeb/DOM/ElementFactory.h> +#include <LibWeb/HTML/Scripting/Environments.h> #include <LibWeb/HTML/Window.h> #include <LibWeb/Namespace.h> @@ -22,7 +21,7 @@ ImageConstructor::ImageConstructor(JS::Realm& realm) void ImageConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<HTMLImageElementPrototype>("HTMLImageElement"), 0); @@ -38,11 +37,10 @@ JS::ThrowCompletionOr<JS::Value> ImageConstructor::call() JS::ThrowCompletionOr<JS::Object*> 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<WindowObject&>(HTML::current_global_object()); - auto& document = window.impl().associated_document(); + auto& window = verify_cast<HTML::Window>(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<JS::Object*> 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 c8969d438e..a8f459bb1b 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 774fbfed70..d625e19dce 100644 --- a/Userland/Libraries/LibWeb/Bindings/LocationConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/LocationConstructor.cpp @@ -7,7 +7,7 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibWeb/Bindings/LocationConstructor.h> #include <LibWeb/Bindings/LocationPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { @@ -31,7 +31,7 @@ JS::ThrowCompletionOr<JS::Object*> LocationConstructor::construct(FunctionObject void LocationConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<LocationPrototype>("Location"), 0); diff --git a/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp b/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp index c7bb3ef343..f6e27a511a 100644 --- a/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/LocationObject.cpp @@ -15,7 +15,6 @@ #include <LibWeb/Bindings/DOMExceptionWrapper.h> #include <LibWeb/Bindings/LocationObject.h> #include <LibWeb/Bindings/LocationPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/Window.h> @@ -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<WindowObject&>(realm.global_object()).ensure_web_prototype<LocationPrototype>("Location")) + : Object(verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<LocationPrototype>("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<WindowObject>(HTML::relevant_global_object(*this)).impl().browsing_context(); + auto* browsing_context = verify_cast<HTML::Window>(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<WindowObject&>(HTML::current_global_object()); + auto& window = verify_cast<HTML::Window>(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<WindowObject&>(HTML::current_global_object()); + auto& window = verify_cast<HTML::Window>(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<WindowObject&>(HTML::current_global_object()); + auto& window = verify_cast<HTML::Window>(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 52ed45fe8d..f803260011 100644 --- a/Userland/Libraries/LibWeb/Bindings/LocationPrototype.h +++ b/Userland/Libraries/LibWeb/Bindings/LocationPrototype.h @@ -9,8 +9,8 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/VM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Forward.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { diff --git a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp index 03c8954b8a..a9e230b89a 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<Bindings::WindowObject>(*global.cell()); + auto& window = verify_cast<HTML::Window>(*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<WebEngineCustomData>(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<Bindings::WindowObject>(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<WebEngineCustomData>(*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<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM& vm, Function<JS::GlobalObject*(JS::Realm&)> create_global_object, Function<JS::GlobalObject*(JS::Realm&)> create_global_this_value) +NonnullOwnPtr<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM& vm, Function<JS::Object*(JS::Realm&)> create_global_object, Function<JS::Object*(JS::Realm&)> 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 88a473e771..d3825618b6 100644 --- a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h +++ b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h @@ -11,9 +11,9 @@ #include <LibJS/Forward.h> #include <LibJS/Runtime/JobCallback.h> #include <LibJS/Runtime/VM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/MutationObserver.h> #include <LibWeb/HTML/EventLoop/EventLoop.h> +#include <LibWeb/HTML/Window.h> 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<Bindings::WindowObject> internal_window_object; + JS::Handle<HTML::Window> 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<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM&, Function<JS::GlobalObject*(JS::Realm&)> create_global_object, Function<JS::GlobalObject*(JS::Realm&)> create_global_this_value); +NonnullOwnPtr<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM&, Function<JS::Object*(JS::Realm&)> create_global_object, Function<JS::Object*(JS::Realm&)> create_global_this_value); } diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp index 8a1b13e22f..9448536055 100644 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp @@ -7,7 +7,7 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibWeb/Bindings/NavigatorConstructor.h> #include <LibWeb/Bindings/NavigatorPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { @@ -31,7 +31,7 @@ JS::ThrowCompletionOr<JS::Object*> NavigatorConstructor::construct(FunctionObjec void NavigatorConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<NavigatorPrototype>("Navigator"), 0); diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp b/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp index 533ef5b9a3..8db25da83f 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<WindowObject&>(realm.global_object()).ensure_web_prototype<NavigatorPrototype>("Navigator")) + : Object(verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<NavigatorPrototype>("Navigator")) { } diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h b/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h index 32eb17d619..3f5242ba22 100644 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h +++ b/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h @@ -9,8 +9,8 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/VM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Forward.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { diff --git a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp deleted file mode 100644 index 62b58e9cb8..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * Copyright (c) 2020, Luke Wilde <lukew@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <LibWeb/Bindings/AttributeWrapper.h> -#include <LibWeb/Bindings/CharacterDataWrapper.h> -#include <LibWeb/Bindings/CommentWrapper.h> -#include <LibWeb/Bindings/DocumentFragmentWrapper.h> -#include <LibWeb/Bindings/DocumentTypeWrapper.h> -#include <LibWeb/Bindings/DocumentWrapper.h> -#include <LibWeb/Bindings/HTMLAnchorElementWrapper.h> -#include <LibWeb/Bindings/HTMLAreaElementWrapper.h> -#include <LibWeb/Bindings/HTMLAudioElementWrapper.h> -#include <LibWeb/Bindings/HTMLBRElementWrapper.h> -#include <LibWeb/Bindings/HTMLBaseElementWrapper.h> -#include <LibWeb/Bindings/HTMLBodyElementWrapper.h> -#include <LibWeb/Bindings/HTMLButtonElementWrapper.h> -#include <LibWeb/Bindings/HTMLCanvasElementWrapper.h> -#include <LibWeb/Bindings/HTMLDListElementWrapper.h> -#include <LibWeb/Bindings/HTMLDataElementWrapper.h> -#include <LibWeb/Bindings/HTMLDataListElementWrapper.h> -#include <LibWeb/Bindings/HTMLDetailsElementWrapper.h> -#include <LibWeb/Bindings/HTMLDialogElementWrapper.h> -#include <LibWeb/Bindings/HTMLDirectoryElementWrapper.h> -#include <LibWeb/Bindings/HTMLDivElementWrapper.h> -#include <LibWeb/Bindings/HTMLElementWrapper.h> -#include <LibWeb/Bindings/HTMLEmbedElementWrapper.h> -#include <LibWeb/Bindings/HTMLFieldSetElementWrapper.h> -#include <LibWeb/Bindings/HTMLFontElementWrapper.h> -#include <LibWeb/Bindings/HTMLFormElementWrapper.h> -#include <LibWeb/Bindings/HTMLFrameElementWrapper.h> -#include <LibWeb/Bindings/HTMLFrameSetElementWrapper.h> -#include <LibWeb/Bindings/HTMLHRElementWrapper.h> -#include <LibWeb/Bindings/HTMLHeadElementWrapper.h> -#include <LibWeb/Bindings/HTMLHeadingElementWrapper.h> -#include <LibWeb/Bindings/HTMLHtmlElementWrapper.h> -#include <LibWeb/Bindings/HTMLIFrameElementWrapper.h> -#include <LibWeb/Bindings/HTMLImageElementWrapper.h> -#include <LibWeb/Bindings/HTMLInputElementWrapper.h> -#include <LibWeb/Bindings/HTMLLIElementWrapper.h> -#include <LibWeb/Bindings/HTMLLabelElementWrapper.h> -#include <LibWeb/Bindings/HTMLLegendElementWrapper.h> -#include <LibWeb/Bindings/HTMLLinkElementWrapper.h> -#include <LibWeb/Bindings/HTMLMapElementWrapper.h> -#include <LibWeb/Bindings/HTMLMarqueeElementWrapper.h> -#include <LibWeb/Bindings/HTMLMenuElementWrapper.h> -#include <LibWeb/Bindings/HTMLMetaElementWrapper.h> -#include <LibWeb/Bindings/HTMLMeterElementWrapper.h> -#include <LibWeb/Bindings/HTMLModElementWrapper.h> -#include <LibWeb/Bindings/HTMLOListElementWrapper.h> -#include <LibWeb/Bindings/HTMLObjectElementWrapper.h> -#include <LibWeb/Bindings/HTMLOptGroupElementWrapper.h> -#include <LibWeb/Bindings/HTMLOptionElementWrapper.h> -#include <LibWeb/Bindings/HTMLOutputElementWrapper.h> -#include <LibWeb/Bindings/HTMLParagraphElementWrapper.h> -#include <LibWeb/Bindings/HTMLParamElementWrapper.h> -#include <LibWeb/Bindings/HTMLPictureElementWrapper.h> -#include <LibWeb/Bindings/HTMLPreElementWrapper.h> -#include <LibWeb/Bindings/HTMLProgressElementWrapper.h> -#include <LibWeb/Bindings/HTMLQuoteElementWrapper.h> -#include <LibWeb/Bindings/HTMLScriptElementWrapper.h> -#include <LibWeb/Bindings/HTMLSelectElementWrapper.h> -#include <LibWeb/Bindings/HTMLSlotElementWrapper.h> -#include <LibWeb/Bindings/HTMLSourceElementWrapper.h> -#include <LibWeb/Bindings/HTMLSpanElementWrapper.h> -#include <LibWeb/Bindings/HTMLStyleElementWrapper.h> -#include <LibWeb/Bindings/HTMLTableCaptionElementWrapper.h> -#include <LibWeb/Bindings/HTMLTableCellElementWrapper.h> -#include <LibWeb/Bindings/HTMLTableColElementWrapper.h> -#include <LibWeb/Bindings/HTMLTableElementWrapper.h> -#include <LibWeb/Bindings/HTMLTableRowElementWrapper.h> -#include <LibWeb/Bindings/HTMLTableSectionElementWrapper.h> -#include <LibWeb/Bindings/HTMLTemplateElementWrapper.h> -#include <LibWeb/Bindings/HTMLTextAreaElementWrapper.h> -#include <LibWeb/Bindings/HTMLTimeElementWrapper.h> -#include <LibWeb/Bindings/HTMLTitleElementWrapper.h> -#include <LibWeb/Bindings/HTMLTrackElementWrapper.h> -#include <LibWeb/Bindings/HTMLUListElementWrapper.h> -#include <LibWeb/Bindings/HTMLUnknownElementWrapper.h> -#include <LibWeb/Bindings/HTMLVideoElementWrapper.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> -#include <LibWeb/Bindings/SVGCircleElementWrapper.h> -#include <LibWeb/Bindings/SVGEllipseElementWrapper.h> -#include <LibWeb/Bindings/SVGLineElementWrapper.h> -#include <LibWeb/Bindings/SVGPathElementWrapper.h> -#include <LibWeb/Bindings/SVGPolygonElementWrapper.h> -#include <LibWeb/Bindings/SVGPolylineElementWrapper.h> -#include <LibWeb/Bindings/SVGRectElementWrapper.h> -#include <LibWeb/Bindings/SVGSVGElementWrapper.h> -#include <LibWeb/Bindings/SVGTextContentElementWrapper.h> -#include <LibWeb/Bindings/TextWrapper.h> -#include <LibWeb/DOM/Document.h> -#include <LibWeb/DOM/Node.h> -#include <LibWeb/HTML/HTMLAnchorElement.h> -#include <LibWeb/HTML/HTMLAreaElement.h> -#include <LibWeb/HTML/HTMLAudioElement.h> -#include <LibWeb/HTML/HTMLBRElement.h> -#include <LibWeb/HTML/HTMLBaseElement.h> -#include <LibWeb/HTML/HTMLBodyElement.h> -#include <LibWeb/HTML/HTMLButtonElement.h> -#include <LibWeb/HTML/HTMLCanvasElement.h> -#include <LibWeb/HTML/HTMLDListElement.h> -#include <LibWeb/HTML/HTMLDataElement.h> -#include <LibWeb/HTML/HTMLDataListElement.h> -#include <LibWeb/HTML/HTMLDetailsElement.h> -#include <LibWeb/HTML/HTMLDialogElement.h> -#include <LibWeb/HTML/HTMLDirectoryElement.h> -#include <LibWeb/HTML/HTMLDivElement.h> -#include <LibWeb/HTML/HTMLEmbedElement.h> -#include <LibWeb/HTML/HTMLFieldSetElement.h> -#include <LibWeb/HTML/HTMLFontElement.h> -#include <LibWeb/HTML/HTMLFormElement.h> -#include <LibWeb/HTML/HTMLFrameElement.h> -#include <LibWeb/HTML/HTMLFrameSetElement.h> -#include <LibWeb/HTML/HTMLHRElement.h> -#include <LibWeb/HTML/HTMLHeadElement.h> -#include <LibWeb/HTML/HTMLHeadingElement.h> -#include <LibWeb/HTML/HTMLHtmlElement.h> -#include <LibWeb/HTML/HTMLIFrameElement.h> -#include <LibWeb/HTML/HTMLImageElement.h> -#include <LibWeb/HTML/HTMLInputElement.h> -#include <LibWeb/HTML/HTMLLIElement.h> -#include <LibWeb/HTML/HTMLLabelElement.h> -#include <LibWeb/HTML/HTMLLegendElement.h> -#include <LibWeb/HTML/HTMLLinkElement.h> -#include <LibWeb/HTML/HTMLMapElement.h> -#include <LibWeb/HTML/HTMLMarqueeElement.h> -#include <LibWeb/HTML/HTMLMenuElement.h> -#include <LibWeb/HTML/HTMLMetaElement.h> -#include <LibWeb/HTML/HTMLMeterElement.h> -#include <LibWeb/HTML/HTMLModElement.h> -#include <LibWeb/HTML/HTMLOListElement.h> -#include <LibWeb/HTML/HTMLObjectElement.h> -#include <LibWeb/HTML/HTMLOptGroupElement.h> -#include <LibWeb/HTML/HTMLOptionElement.h> -#include <LibWeb/HTML/HTMLOutputElement.h> -#include <LibWeb/HTML/HTMLParagraphElement.h> -#include <LibWeb/HTML/HTMLParamElement.h> -#include <LibWeb/HTML/HTMLPictureElement.h> -#include <LibWeb/HTML/HTMLPreElement.h> -#include <LibWeb/HTML/HTMLProgressElement.h> -#include <LibWeb/HTML/HTMLQuoteElement.h> -#include <LibWeb/HTML/HTMLScriptElement.h> -#include <LibWeb/HTML/HTMLSelectElement.h> -#include <LibWeb/HTML/HTMLSlotElement.h> -#include <LibWeb/HTML/HTMLSourceElement.h> -#include <LibWeb/HTML/HTMLSpanElement.h> -#include <LibWeb/HTML/HTMLStyleElement.h> -#include <LibWeb/HTML/HTMLTableCaptionElement.h> -#include <LibWeb/HTML/HTMLTableCellElement.h> -#include <LibWeb/HTML/HTMLTableColElement.h> -#include <LibWeb/HTML/HTMLTableElement.h> -#include <LibWeb/HTML/HTMLTableRowElement.h> -#include <LibWeb/HTML/HTMLTableSectionElement.h> -#include <LibWeb/HTML/HTMLTemplateElement.h> -#include <LibWeb/HTML/HTMLTextAreaElement.h> -#include <LibWeb/HTML/HTMLTimeElement.h> -#include <LibWeb/HTML/HTMLTitleElement.h> -#include <LibWeb/HTML/HTMLTrackElement.h> -#include <LibWeb/HTML/HTMLUListElement.h> -#include <LibWeb/HTML/HTMLUnknownElement.h> -#include <LibWeb/HTML/HTMLVideoElement.h> -#include <LibWeb/SVG/SVGCircleElement.h> -#include <LibWeb/SVG/SVGEllipseElement.h> -#include <LibWeb/SVG/SVGLineElement.h> -#include <LibWeb/SVG/SVGPathElement.h> -#include <LibWeb/SVG/SVGPolygonElement.h> -#include <LibWeb/SVG/SVGPolylineElement.h> -#include <LibWeb/SVG/SVGRectElement.h> -#include <LibWeb/SVG/SVGSVGElement.h> - -namespace Web::Bindings { - -NodeWrapper* wrap(JS::Realm& realm, DOM::Node& node) -{ - if (node.wrapper()) - return static_cast<NodeWrapper*>(node.wrapper()); - - if (is<DOM::Document>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::Document>(node))); - if (is<DOM::DocumentType>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::DocumentType>(node))); - if (is<HTML::HTMLAnchorElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLAnchorElement>(node))); - if (is<HTML::HTMLAreaElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLAreaElement>(node))); - if (is<HTML::HTMLAudioElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLAudioElement>(node))); - if (is<HTML::HTMLBaseElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLBaseElement>(node))); - if (is<HTML::HTMLBodyElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLBodyElement>(node))); - if (is<HTML::HTMLBRElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLBRElement>(node))); - if (is<HTML::HTMLButtonElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLButtonElement>(node))); - if (is<HTML::HTMLCanvasElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLCanvasElement>(node))); - if (is<HTML::HTMLDataElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLDataElement>(node))); - if (is<HTML::HTMLDataListElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLDataListElement>(node))); - if (is<HTML::HTMLDetailsElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLDetailsElement>(node))); - if (is<HTML::HTMLDialogElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLDialogElement>(node))); - if (is<HTML::HTMLDirectoryElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLDirectoryElement>(node))); - if (is<HTML::HTMLDivElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLDivElement>(node))); - if (is<HTML::HTMLDListElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLDListElement>(node))); - if (is<HTML::HTMLEmbedElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLEmbedElement>(node))); - if (is<HTML::HTMLFieldSetElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLFieldSetElement>(node))); - if (is<HTML::HTMLFontElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLFontElement>(node))); - if (is<HTML::HTMLFormElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLFormElement>(node))); - if (is<HTML::HTMLFrameElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLFrameElement>(node))); - if (is<HTML::HTMLFrameSetElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLFrameSetElement>(node))); - if (is<HTML::HTMLHeadElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLHeadElement>(node))); - if (is<HTML::HTMLHeadingElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLHeadingElement>(node))); - if (is<HTML::HTMLHRElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLHRElement>(node))); - if (is<HTML::HTMLHtmlElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLHtmlElement>(node))); - if (is<HTML::HTMLIFrameElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLIFrameElement>(node))); - if (is<HTML::HTMLImageElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLImageElement>(node))); - if (is<HTML::HTMLInputElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLInputElement>(node))); - if (is<HTML::HTMLLabelElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLLabelElement>(node))); - if (is<HTML::HTMLLegendElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLLegendElement>(node))); - if (is<HTML::HTMLLIElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLLIElement>(node))); - if (is<HTML::HTMLLinkElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLLinkElement>(node))); - if (is<HTML::HTMLMapElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLMapElement>(node))); - if (is<HTML::HTMLMarqueeElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLMarqueeElement>(node))); - if (is<HTML::HTMLMenuElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLMenuElement>(node))); - if (is<HTML::HTMLMetaElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLMetaElement>(node))); - if (is<HTML::HTMLMeterElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLMeterElement>(node))); - if (is<HTML::HTMLModElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLModElement>(node))); - if (is<HTML::HTMLObjectElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLObjectElement>(node))); - if (is<HTML::HTMLOListElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLOListElement>(node))); - if (is<HTML::HTMLOptGroupElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLOptGroupElement>(node))); - if (is<HTML::HTMLOptionElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLOptionElement>(node))); - if (is<HTML::HTMLOutputElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLOutputElement>(node))); - if (is<HTML::HTMLParagraphElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLParagraphElement>(node))); - if (is<HTML::HTMLParamElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLParamElement>(node))); - if (is<HTML::HTMLPictureElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLPictureElement>(node))); - if (is<HTML::HTMLPreElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLPreElement>(node))); - if (is<HTML::HTMLProgressElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLProgressElement>(node))); - if (is<HTML::HTMLQuoteElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLQuoteElement>(node))); - if (is<HTML::HTMLScriptElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLScriptElement>(node))); - if (is<HTML::HTMLSelectElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLSelectElement>(node))); - if (is<HTML::HTMLSlotElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLSlotElement>(node))); - if (is<HTML::HTMLSourceElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLSourceElement>(node))); - if (is<HTML::HTMLSpanElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLSpanElement>(node))); - if (is<HTML::HTMLStyleElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLStyleElement>(node))); - if (is<HTML::HTMLTableCaptionElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTableCaptionElement>(node))); - if (is<HTML::HTMLTableCellElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTableCellElement>(node))); - if (is<HTML::HTMLTableColElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTableColElement>(node))); - if (is<HTML::HTMLTableElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTableElement>(node))); - if (is<HTML::HTMLTableRowElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTableRowElement>(node))); - if (is<HTML::HTMLTableSectionElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTableSectionElement>(node))); - if (is<HTML::HTMLTemplateElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTemplateElement>(node))); - if (is<HTML::HTMLTextAreaElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTextAreaElement>(node))); - if (is<HTML::HTMLTimeElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTimeElement>(node))); - if (is<HTML::HTMLTitleElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTitleElement>(node))); - if (is<HTML::HTMLTrackElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLTrackElement>(node))); - if (is<HTML::HTMLUListElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLUListElement>(node))); - if (is<HTML::HTMLUnknownElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLUnknownElement>(node))); - if (is<HTML::HTMLVideoElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLVideoElement>(node))); - if (is<HTML::HTMLElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<HTML::HTMLElement>(node))); - if (is<SVG::SVGSVGElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGSVGElement>(node))); - if (is<SVG::SVGCircleElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGCircleElement>(node))); - if (is<SVG::SVGEllipseElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGEllipseElement>(node))); - if (is<SVG::SVGLineElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGLineElement>(node))); - if (is<SVG::SVGPolygonElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGPolygonElement>(node))); - if (is<SVG::SVGPolylineElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGPolylineElement>(node))); - if (is<SVG::SVGPathElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGPathElement>(node))); - if (is<SVG::SVGRectElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGRectElement>(node))); - if (is<SVG::SVGTextContentElement>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<SVG::SVGTextContentElement>(node))); - if (is<DOM::Element>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::Element>(node))); - if (is<DOM::DocumentFragment>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::DocumentFragment>(node))); - if (is<DOM::Comment>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::Comment>(node))); - if (is<DOM::Text>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::Text>(node))); - if (is<DOM::CharacterData>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::CharacterData>(node))); - if (is<DOM::Attribute>(node)) - return static_cast<NodeWrapper*>(wrap_impl(realm, verify_cast<DOM::Attribute>(node))); - return static_cast<NodeWrapper*>(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 69bad2cc08..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <LibJS/Forward.h> -#include <LibWeb/Forward.h> - -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 c4b7930f13..8c0a9984c2 100644 --- a/Userland/Libraries/LibWeb/Bindings/OptionConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/OptionConstructor.cpp @@ -5,11 +5,11 @@ */ #include <LibWeb/Bindings/HTMLOptionElementPrototype.h> -#include <LibWeb/Bindings/HTMLOptionElementWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> #include <LibWeb/Bindings/OptionConstructor.h> #include <LibWeb/DOM/ElementFactory.h> +#include <LibWeb/DOM/Text.h> #include <LibWeb/HTML/HTMLOptionElement.h> +#include <LibWeb/HTML/Scripting/Environments.h> #include <LibWeb/HTML/Window.h> #include <LibWeb/Namespace.h> @@ -23,7 +23,7 @@ OptionConstructor::OptionConstructor(JS::Realm& realm) void OptionConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<HTMLOptionElementPrototype>("HTMLOptionElement"), 0); @@ -42,18 +42,18 @@ JS::ThrowCompletionOr<JS::Object*> OptionConstructor::construct(FunctionObject&) auto& realm = *vm.current_realm(); // 1. Let document be the current global object's associated Document. - auto& window = static_cast<WindowObject&>(HTML::current_global_object()); - auto& document = window.impl().associated_document(); + auto& window = verify_cast<HTML::Window>(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<HTML::HTMLOptionElement>(DOM::create_element(document, HTML::TagNames::option, Namespace::HTML)); + JS::NonnullGCPtr<HTML::HTMLOptionElement> option_element = verify_cast<HTML::HTMLOptionElement>(*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<DOM::Text>(realm, document, text); + option_element->append_child(*new_text_node); } } @@ -75,7 +75,7 @@ JS::ThrowCompletionOr<JS::Object*> 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 b334f15265..8c65fa9388 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 <AK/TypeCasts.h> +#include <LibJS/Runtime/Realm.h> #include <LibWeb/Bindings/PlatformObject.h> +#include <LibWeb/HTML/Window.h> 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<HTML::Window>(realm().global_object()); +} + } diff --git a/Userland/Libraries/LibWeb/Bindings/PlatformObject.h b/Userland/Libraries/LibWeb/Bindings/PlatformObject.h index dc4b4ff81c..a866933dd4 100644 --- a/Userland/Libraries/LibWeb/Bindings/PlatformObject.h +++ b/Userland/Libraries/LibWeb/Bindings/PlatformObject.h @@ -6,19 +6,49 @@ #pragma once +#include <AK/Weakable.h> #include <LibJS/Heap/GCPtr.h> #include <LibJS/Runtime/Object.h> +#include <LibWeb/Forward.h> 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<PlatformObject> { 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 ef33827f17..909bd5e93b 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowConstructor.cpp @@ -6,8 +6,8 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibWeb/Bindings/WindowConstructor.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Bindings/WindowPrototype.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { @@ -31,7 +31,7 @@ JS::ThrowCompletionOr<JS::Object*> WindowConstructor::construct(FunctionObject&) void WindowConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<WindowPrototype>("Window"), 0); diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp deleted file mode 100644 index c9b530b425..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp +++ /dev/null @@ -1,774 +0,0 @@ -/* - * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org> - * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <AK/Base64.h> -#include <AK/String.h> -#include <AK/Utf8View.h> -#include <LibJS/Runtime/Completion.h> -#include <LibJS/Runtime/Error.h> -#include <LibJS/Runtime/FunctionObject.h> -#include <LibJS/Runtime/Shape.h> -#include <LibTextCodec/Decoder.h> -#include <LibWeb/Bindings/CSSNamespace.h> -#include <LibWeb/Bindings/CryptoWrapper.h> -#include <LibWeb/Bindings/DocumentWrapper.h> -#include <LibWeb/Bindings/ElementWrapper.h> -#include <LibWeb/Bindings/EventTargetConstructor.h> -#include <LibWeb/Bindings/EventTargetPrototype.h> -#include <LibWeb/Bindings/ExceptionOrUtils.h> -#include <LibWeb/Bindings/HistoryWrapper.h> -#include <LibWeb/Bindings/LocationObject.h> -#include <LibWeb/Bindings/MediaQueryListWrapper.h> -#include <LibWeb/Bindings/NavigatorObject.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> -#include <LibWeb/Bindings/PerformanceWrapper.h> -#include <LibWeb/Bindings/Replaceable.h> -#include <LibWeb/Bindings/ScreenWrapper.h> -#include <LibWeb/Bindings/SelectionWrapper.h> -#include <LibWeb/Bindings/StorageWrapper.h> -#include <LibWeb/Bindings/WindowObject.h> -#include <LibWeb/Bindings/WindowObjectHelper.h> -#include <LibWeb/Bindings/WindowPrototype.h> -#include <LibWeb/Crypto/Crypto.h> -#include <LibWeb/DOM/Document.h> -#include <LibWeb/DOM/Event.h> -#include <LibWeb/HTML/BrowsingContext.h> -#include <LibWeb/HTML/EventHandler.h> -#include <LibWeb/HTML/Origin.h> -#include <LibWeb/HTML/Scripting/Environments.h> -#include <LibWeb/HTML/Storage.h> -#include <LibWeb/HTML/Window.h> -#include <LibWeb/Page/Page.h> -#include <LibWeb/WebAssembly/WebAssemblyObject.h> - -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<WindowPrototype>("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<CSSNamespace>(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<LocationObject>(realm, realm); - - auto* m_navigator_object = heap().allocate<NavigatorObject>(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<WebAssemblyObject>(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<bool> WindowObject::internal_set_prototype_of(JS::Object* prototype) -{ - // 1. Return ? SetImmutablePrototype(O, V). - return set_immutable_prototype(prototype); -} - -static JS::ThrowCompletionOr<HTML::Window*> 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<WindowObject>(*this_object)) - return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "WindowObject"); - return &static_cast<WindowObject*>(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<TimerHandler> make_timer_handler(JS::VM& vm, JS::Value handler) -{ - if (handler.is_function()) - return JS::make_handle(vm.heap().allocate_without_realm<Bindings::CallbackType>(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::TypeError>(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<JS::Value> 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::TypeError>(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<JS::Value> 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::TypeError>(JS::ErrorType::BadArgCountOne, "requestAnimationFrame"); - auto* callback_object = TRY(vm.argument(0).to_object(vm)); - if (!callback_object->is_function()) - return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); - auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*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::TypeError>(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::TypeError>(JS::ErrorType::BadArgCountAtLeastOne, "queueMicrotask"); - auto* callback_object = TRY(vm.argument(0).to_object(vm)); - if (!callback_object->is_function()) - return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); - - auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*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::TypeError>(JS::ErrorType::BadArgCountAtLeastOne, "requestIdleCallback"); - auto* callback_object = TRY(vm.argument(0).to_object(vm)); - if (!callback_object->is_function()) - return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); - // FIXME: accept options object - - auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*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::TypeError>(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::TypeError>(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::TypeError>(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::TypeError>(JS::ErrorType::BadArgCountOne, "btoa"); - auto string = TRY(vm.argument(0).to_string(vm)); - - Vector<u8> 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::TypeError>(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<DOM::Event&>(*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<ElementWrapper>(object)) - return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "DOM element"); - - return wrap(realm, *impl->get_computed_style(static_cast<ElementWrapper*>(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<JS::TypeError>("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<JS::TypeError>("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<Bindings::CallbackType>( \ - 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 86cc00a6d4..ac4013b6d3 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<JS::Handle<CallbackType>, String>; - class WindowObject : public JS::GlobalObject , public Weakable<WindowObject> { @@ -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<typename T> - 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<T>(realm, realm); - m_prototypes.set(class_name, prototype); - return *prototype; - } - - template<typename T> - 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<T>(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<bool> 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<HTML::Window> m_impl; - - LocationObject* m_location_object { nullptr }; - - HashMap<String, JS::Object*> m_prototypes; - HashMap<String, JS::NativeFunction*> 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 ae967d4d12..4865ba607a 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<constructor_name>(#interface_name); \ + auto& constructor = ensure_web_constructor<Bindings::constructor_name>(#interface_name); \ constructor.define_direct_property(vm.names.name, js_string(vm, #interface_name), JS::Attribute::Configurable); \ - auto& prototype = ensure_web_prototype<prototype_name>(#interface_name); \ + auto& prototype = ensure_web_prototype<Bindings::prototype_name>(#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 9d99573be7..8f16471bc4 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowPrototype.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowPrototype.h @@ -10,8 +10,8 @@ #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/VM.h> #include <LibWeb/Bindings/EventTargetPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Forward.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { @@ -20,7 +20,7 @@ class WindowPrototype final : public JS::Object { public: explicit WindowPrototype(JS::Realm& realm) - : JS::Object(static_cast<WindowObject&>(realm.global_object()).ensure_web_prototype<EventTargetPrototype>("EventTarget")) + : JS::Object(verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<EventTargetPrototype>("EventTarget")) { } }; diff --git a/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp b/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp index 04fffa57cd..f943bef8b1 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowProxy.cpp @@ -12,7 +12,6 @@ #include <LibJS/Runtime/PropertyKey.h> #include <LibWeb/Bindings/CrossOriginAbstractOperations.h> #include <LibWeb/Bindings/DOMExceptionWrapper.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Bindings/WindowProxy.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/HTML/CrossOrigin/Reporting.h> @@ -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<Optional<JS::PropertyDescriptor>> 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<HTML::Window*>(m_window.ptr()), property_key); // 5. If property is not undefined, then return property. if (property.has_value()) @@ -155,7 +154,7 @@ JS::ThrowCompletionOr<JS::Value> 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<WindowObject&>(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::Window>(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<bool> 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<WindowObject&>(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::Window>(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<JS::MarkedVector<JS::Value>> 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 42f8c560ac..880fe3dead 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<JS::Object*> internal_get_prototype_of() const override; @@ -31,18 +30,20 @@ public: virtual JS::ThrowCompletionOr<bool> internal_delete(JS::PropertyKey const&) override; virtual JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> 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<T> 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<HTML::Window> m_window; }; } diff --git a/Userland/Libraries/LibWeb/Bindings/Wrappable.cpp b/Userland/Libraries/LibWeb/Bindings/Wrappable.cpp index 9f5efd78fd..bc5e052b8b 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<Wrapper>(); } } diff --git a/Userland/Libraries/LibWeb/Bindings/Wrapper.h b/Userland/Libraries/LibWeb/Bindings/Wrapper.h index 86b39899c9..0ddb87938d 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<Wrapper> { - 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 29c2d1d1c5..47e1f8e865 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 cd10d45401..9cb51a68ac 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp @@ -6,12 +6,12 @@ */ #include <LibWeb/Bindings/CSSConditionRulePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSConditionRule.h> +#include <LibWeb/HTML/Window.h> 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<Bindings::CSSConditionRulePrototype>("CSSConditionRule")); diff --git a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h index 58d040a5ee..f033d95877 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<void(CSSStyleRule const&)> 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 f6b3f69086..1d5d00aafa 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp @@ -6,17 +6,17 @@ */ #include <LibWeb/Bindings/CSSFontFaceRulePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSFontFaceRule.h> +#include <LibWeb/HTML/Window.h> 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<CSSFontFaceRule>(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 5967add8fc..344d46b6a4 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<CSSFontFaceRule>() 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 e852b1ff44..707eab3964 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp @@ -7,13 +7,13 @@ #include <LibWeb/Bindings/CSSGroupingRulePrototype.h> #include <LibWeb/Bindings/MainThreadVM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSGroupingRule.h> #include <LibWeb/CSS/CSSRuleList.h> +#include <LibWeb/HTML/Window.h> 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 a72b786b34..3616906120 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 52c25953bb..bb6ee1eb85 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp @@ -9,26 +9,26 @@ #include <AK/Debug.h> #include <AK/URL.h> #include <LibWeb/Bindings/CSSImportRulePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSImportRule.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/DOM/Document.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/Loader/ResourceLoader.h> 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<CSSImportRule>(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<Bindings::CSSImportRulePrototype>("CSSImportRule")); + set_prototype(&document.window().ensure_web_prototype<Bindings::CSSImportRulePrototype>("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 ac2cb26a38..5c289c91f7 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<CSSImportRule>() 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 245a80bb84..cb72a58e36 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp @@ -6,17 +6,17 @@ */ #include <LibWeb/Bindings/CSSMediaRulePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSMediaRule.h> +#include <LibWeb/HTML/Window.h> 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<CSSMediaRule>(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 2c502a7e52..a09a3dd5aa 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<CSSMediaRule>() 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 b3c8fcf351..ab1e30dafb 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.cpp @@ -7,13 +7,13 @@ */ #include <LibWeb/Bindings/CSSRulePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSRule.h> #include <LibWeb/CSS/CSSStyleSheet.h> +#include <LibWeb/HTML/Window.h> namespace Web::CSS { -CSSRule::CSSRule(Bindings::WindowObject& window_object) +CSSRule::CSSRule(HTML::Window& window_object) : PlatformObject(window_object.ensure_web_prototype<Bindings::CSSRulePrototype>("CSSRule")) { } diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.h b/Userland/Libraries/LibWeb/CSS/CSSRule.h index 7b82ba62ce..6394ec5338 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 8aa7bf293c..674383f403 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp @@ -6,17 +6,17 @@ #include <AK/TypeCasts.h> #include <LibWeb/Bindings/CSSRuleListPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSImportRule.h> #include <LibWeb/CSS/CSSMediaRule.h> #include <LibWeb/CSS/CSSRule.h> #include <LibWeb/CSS/CSSRuleList.h> #include <LibWeb/CSS/CSSSupportsRule.h> #include <LibWeb/CSS/Parser/Parser.h> +#include <LibWeb/HTML/Window.h> namespace Web::CSS { -CSSRuleList* CSSRuleList::create(Bindings::WindowObject& window_object, JS::MarkedVector<CSSRule*> const& rules) +CSSRuleList* CSSRuleList::create(HTML::Window& window_object, JS::MarkedVector<CSSRule*> const& rules) { auto* rule_list = window_object.heap().allocate<CSSRuleList>(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<Bindings::CSSRuleListPrototype>("CSSRuleList")) { } -CSSRuleList* CSSRuleList::create_empty(Bindings::WindowObject& window_object) +CSSRuleList* CSSRuleList::create_empty(HTML::Window& window_object) { return window_object.heap().allocate<CSSRuleList>(window_object.realm(), window_object); } @@ -65,7 +65,7 @@ DOM::ExceptionOr<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView, CS CSSRule* new_rule = nullptr; if (rule.has<StringView>()) { new_rule = parse_css_rule( - CSS::Parser::ParsingContext { static_cast<Bindings::WindowObject&>(global_object()) }, + CSS::Parser::ParsingContext { static_cast<HTML::Window&>(global_object()) }, rule.get<StringView>()); } else { new_rule = rule.get<CSSRule*>(); diff --git a/Userland/Libraries/LibWeb/CSS/CSSRuleList.h b/Userland/Libraries/LibWeb/CSS/CSSRuleList.h index 9f94bcc1d4..76cab74c06 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<CSSRule*> const&); + static CSSRuleList* create_empty(HTML::Window&); - static CSSRuleList* create(Bindings::WindowObject&, JS::MarkedVector<CSSRule*> 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 e5b4644463..1cb49c536a 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp @@ -5,25 +5,25 @@ */ #include <LibWeb/Bindings/CSSStyleDeclarationPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSStyleDeclaration.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Element.h> +#include <LibWeb/HTML/Window.h> namespace Web::CSS { -CSSStyleDeclaration::CSSStyleDeclaration(Bindings::WindowObject& window_object) +CSSStyleDeclaration::CSSStyleDeclaration(HTML::Window& window_object) : PlatformObject(window_object.ensure_web_prototype<Bindings::CSSStyleDeclarationPrototype>("CSSStyleDeclaration")) { } -PropertyOwningCSSStyleDeclaration* PropertyOwningCSSStyleDeclaration::create(Bindings::WindowObject& window_object, Vector<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties) +PropertyOwningCSSStyleDeclaration* PropertyOwningCSSStyleDeclaration::create(HTML::Window& window_object, Vector<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties) { return window_object.heap().allocate<PropertyOwningCSSStyleDeclaration>(window_object.realm(), window_object, move(properties), move(custom_properties)); } -PropertyOwningCSSStyleDeclaration::PropertyOwningCSSStyleDeclaration(Bindings::WindowObject& window_object, Vector<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties) +PropertyOwningCSSStyleDeclaration::PropertyOwningCSSStyleDeclaration(HTML::Window& window_object, Vector<StyleProperty> properties, HashMap<String, StyleProperty> 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<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties) { - auto& window_object = element.document().preferred_window_object(); + auto& window_object = element.document().window(); return window_object.heap().allocate<ElementInlineCSSStyleDeclaration>(window_object.realm(), element, move(properties), move(custom_properties)); } ElementInlineCSSStyleDeclaration::ElementInlineCSSStyleDeclaration(DOM::Element& element, Vector<StyleProperty> properties, HashMap<String, StyleProperty> 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<DOM::Element>()) { } +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 ac8a3e2471..6679125e8e 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<bool> 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<StyleProperty>, HashMap<String, StyleProperty> custom_properties); - PropertyOwningCSSStyleDeclaration(Bindings::WindowObject&, Vector<StyleProperty>, HashMap<String, StyleProperty>); + static PropertyOwningCSSStyleDeclaration* create(HTML::Window&, Vector<StyleProperty>, HashMap<String, StyleProperty> custom_properties); virtual ~PropertyOwningCSSStyleDeclaration() override = default; @@ -86,6 +83,8 @@ public: virtual String serialized() const final override; protected: + PropertyOwningCSSStyleDeclaration(HTML::Window&, Vector<StyleProperty>, HashMap<String, StyleProperty>); + 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<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties); - explicit ElementInlineCSSStyleDeclaration(DOM::Element&, Vector<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties); virtual ~ElementInlineCSSStyleDeclaration() override = default; @@ -110,9 +108,13 @@ public: bool is_updating() const { return m_updating; } private: + explicit ElementInlineCSSStyleDeclaration(DOM::Element&, Vector<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties); + + virtual void visit_edges(Cell::Visitor&) override; + virtual void update_style_attribute() override; - WeakPtr<DOM::Element> m_element; + JS::GCPtr<DOM::Element> 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 47d829a36c..15bb1463e1 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp @@ -5,18 +5,18 @@ */ #include <LibWeb/Bindings/CSSStyleRulePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSStyleRule.h> #include <LibWeb/CSS/Parser/Parser.h> +#include <LibWeb/HTML/Window.h> namespace Web::CSS { -CSSStyleRule* CSSStyleRule::create(Bindings::WindowObject& window_object, NonnullRefPtrVector<Web::CSS::Selector>&& selectors, CSSStyleDeclaration& declaration) +CSSStyleRule* CSSStyleRule::create(HTML::Window& window_object, NonnullRefPtrVector<Web::CSS::Selector>&& selectors, CSSStyleDeclaration& declaration) { return window_object.heap().allocate<CSSStyleRule>(window_object.realm(), window_object, move(selectors), declaration); } -CSSStyleRule::CSSStyleRule(Bindings::WindowObject& window_object, NonnullRefPtrVector<Selector>&& selectors, CSSStyleDeclaration& declaration) +CSSStyleRule::CSSStyleRule(HTML::Window& window_object, NonnullRefPtrVector<Selector>&& 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 27f2ced9cc..07292800a9 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<Selector>&&, CSSStyleDeclaration&); - CSSStyleRule(Bindings::WindowObject&, NonnullRefPtrVector<Selector>&&, CSSStyleDeclaration&); + static CSSStyleRule* create(HTML::Window&, NonnullRefPtrVector<Selector>&&, CSSStyleDeclaration&); virtual ~CSSStyleRule() override = default; - CSSStyleRule& impl() { return *this; } - NonnullRefPtrVector<Selector> 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<Selector>&&, CSSStyleDeclaration&); + virtual void visit_edges(Cell::Visitor&) override; virtual String serialized() const override; @@ -51,7 +48,4 @@ inline bool CSSRule::fast_is<CSSStyleRule>() 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 1828e30f62..5d210155f7 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<AK::URL> location) +CSSStyleSheet* CSSStyleSheet::create(HTML::Window& window_object, CSSRuleList& rules, Optional<AK::URL> location) { return window_object.heap().allocate<CSSStyleSheet>(window_object.realm(), window_object, rules, move(location)); } -CSSStyleSheet::CSSStyleSheet(Bindings::WindowObject& window_object, CSSRuleList& rules, Optional<AK::URL> location) +CSSStyleSheet::CSSStyleSheet(HTML::Window& window_object, CSSRuleList& rules, Optional<AK::URL> location) : StyleSheet(window_object) , m_rules(&rules) { diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h index 7712a13f3f..fd6ca3685d 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<CSSStyleSheet> { - JS_OBJECT(CSSStyleSheet, StyleSheet); + WEB_PLATFORM_OBJECT(CSSStyleSheet, StyleSheet); public: - static CSSStyleSheet* create(Bindings::WindowObject&, CSSRuleList& rules, Optional<AK::URL> location); + static CSSStyleSheet* create(HTML::Window&, CSSRuleList& rules, Optional<AK::URL> location); - explicit CSSStyleSheet(Bindings::WindowObject&, CSSRuleList&, Optional<AK::URL> location); + explicit CSSStyleSheet(HTML::Window&, CSSRuleList&, Optional<AK::URL> 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 602ca34768..860f142115 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp @@ -5,18 +5,18 @@ */ #include <LibWeb/Bindings/CSSSupportsRulePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSSupportsRule.h> #include <LibWeb/CSS/Parser/Parser.h> +#include <LibWeb/HTML/Window.h> namespace Web::CSS { -CSSSupportsRule* CSSSupportsRule::create(Bindings::WindowObject& window_object, NonnullRefPtr<Supports>&& supports, CSSRuleList& rules) +CSSSupportsRule* CSSSupportsRule::create(HTML::Window& window_object, NonnullRefPtr<Supports>&& supports, CSSRuleList& rules) { return window_object.heap().allocate<CSSSupportsRule>(window_object.realm(), window_object, move(supports), rules); } -CSSSupportsRule::CSSSupportsRule(Bindings::WindowObject& window_object, NonnullRefPtr<Supports>&& supports, CSSRuleList& rules) +CSSSupportsRule::CSSSupportsRule(HTML::Window& window_object, NonnullRefPtr<Supports>&& 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 31e0dcac7b..1cabc601f9 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<Supports>&&, CSSRuleList&); - explicit CSSSupportsRule(Bindings::WindowObject&, NonnullRefPtr<Supports>&&, CSSRuleList&); + static CSSSupportsRule* create(HTML::Window&, NonnullRefPtr<Supports>&&, 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<Supports>&&, CSSRuleList&); + virtual String serialized() const override; NonnullRefPtr<Supports> m_supports; @@ -46,7 +43,4 @@ inline bool CSSRule::fast_is<CSSSupportsRule>() 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 dbcea1fa35..7003b702b3 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaList.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaList.cpp @@ -6,18 +6,18 @@ */ #include <LibWeb/Bindings/MediaListPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/MediaList.h> #include <LibWeb/CSS/Parser/Parser.h> +#include <LibWeb/HTML/Window.h> namespace Web::CSS { -MediaList* MediaList::create(Bindings::WindowObject& window_object, NonnullRefPtrVector<MediaQuery>&& media) +MediaList* MediaList::create(HTML::Window& window_object, NonnullRefPtrVector<MediaQuery>&& media) { return window_object.heap().allocate<MediaList>(window_object.realm(), window_object, move(media)); } -MediaList::MediaList(Bindings::WindowObject& window_object, NonnullRefPtrVector<MediaQuery>&& media) +MediaList::MediaList(HTML::Window& window_object, NonnullRefPtrVector<MediaQuery>&& media) : Bindings::LegacyPlatformObject(window_object.ensure_web_prototype<Bindings::MediaListPrototype>("MediaList")) , m_media(move(media)) { diff --git a/Userland/Libraries/LibWeb/CSS/MediaList.h b/Userland/Libraries/LibWeb/CSS/MediaList.h index 4ffe4b9106..25a272c939 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<MediaQuery>&& media); - explicit MediaList(Bindings::WindowObject&, NonnullRefPtrVector<MediaQuery>&&); + static MediaList* create(HTML::Window&, NonnullRefPtrVector<MediaQuery>&& 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<MediaQuery>&&); + NonnullRefPtrVector<MediaQuery> 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 74caf27013..bbcf17a264 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 <LibWeb/Bindings/MediaQueryListWrapper.h> +#include <LibWeb/Bindings/MediaQueryListPrototype.h> #include <LibWeb/CSS/MediaQueryList.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/EventDispatcher.h> @@ -14,14 +14,26 @@ namespace Web::CSS { +JS::NonnullGCPtr<MediaQueryList> MediaQueryList::create(DOM::Document& document, NonnullRefPtrVector<MediaQuery>&& media) +{ + return *document.heap().allocate<MediaQueryList>(document.realm(), document, move(media)); +} + MediaQueryList::MediaQueryList(DOM::Document& document, NonnullRefPtrVector<MediaQuery>&& media) - : DOM::EventTarget() + : DOM::EventTarget(document.realm()) , m_document(document) , m_media(move(media)) { + set_prototype(&document.window().ensure_web_prototype<Bindings::MediaQueryListPrototype>("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 71f88439bb..a302425c93 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<MediaQueryList> - , public Weakable<MediaQueryList> - , 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<MediaQueryList> create(DOM::Document& document, NonnullRefPtrVector<MediaQuery>&& media_queries) - { - return adopt_ref(*new MediaQueryList(document, move(media_queries))); - } + static JS::NonnullGCPtr<MediaQueryList> create(DOM::Document&, NonnullRefPtrVector<MediaQuery>&&); 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<MediaQuery>&&); - WeakPtr<DOM::Document> m_document; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr<DOM::Document> m_document; NonnullRefPtrVector<MediaQuery> 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 ed16e9d712..6bd7b37606 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/MediaQueryListEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/MediaQueryListEvent.h> +#include <LibWeb/HTML/Window.h> 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<MediaQueryListEvent>(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 e934b9fd50..e217559dc4 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 dd3cf53e55..dae4505fe6 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<HTML::Window&>(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<HTML::Window&>(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 088756d81a..004e665da8 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 061214295b..d52749ce0c 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<ResolvedCSSStyleDeclaration>(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 285e853bfd..f1bd202117 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<StyleValue> style_value_for_property(Layout::NodeWithStyle const&, PropertyID) const; - NonnullRefPtr<DOM::Element> m_element; + JS::NonnullGCPtr<DOM::Element> m_element; }; } diff --git a/Userland/Libraries/LibWeb/CSS/Screen.cpp b/Userland/Libraries/LibWeb/CSS/Screen.cpp index 42ec725602..b4458e7256 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 ea6de94951..ce0e1abd9e 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<HTML::Window> + : public RefCounted<Screen> , 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<HTML::Window> m_window; }; } diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp b/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp index ae5d520889..894d0cdf85 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleSheet.cpp @@ -6,14 +6,14 @@ */ #include <LibWeb/Bindings/StyleSheetPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSStyleSheet.h> #include <LibWeb/CSS/StyleSheet.h> #include <LibWeb/DOM/Element.h> +#include <LibWeb/HTML/Window.h> namespace Web::CSS { -StyleSheet::StyleSheet(Bindings::WindowObject& window_object) +StyleSheet::StyleSheet(HTML::Window& window_object) : PlatformObject(window_object.ensure_web_prototype<Bindings::StyleSheetPrototype>("StyleSheet")) { } diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheet.h b/Userland/Libraries/LibWeb/CSS/StyleSheet.h index 5c5d2ff466..3304962b9d 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 c61fd64874..bcb3f470f9 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<StyleSheetList>(realm, document); } StyleSheetList::StyleSheetList(DOM::Document& document) - : Bindings::LegacyPlatformObject(document.preferred_window_object().ensure_web_prototype<Bindings::StyleSheetListPrototype>("StyleSheetList")) + : Bindings::LegacyPlatformObject(document.window().ensure_web_prototype<Bindings::StyleSheetListPrototype>("StyleSheetList")) , m_document(document) { } diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheetList.h b/Userland/Libraries/LibWeb/CSS/StyleSheetList.h index 32e26d54a6..18fa197ef0 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 4e92ee301e..76640bcf27 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 dc616ecc67..bb597309e5 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortController.h +++ b/Userland/Libraries/LibWeb/DOM/AbortController.h @@ -8,7 +8,6 @@ #include <AK/RefCounted.h> #include <AK/Weakable.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Bindings/Wrappable.h> #include <LibWeb/DOM/AbortSignal.h> #include <LibWeb/Forward.h> @@ -24,28 +23,23 @@ class AbortController final public: using WrapperType = Bindings::AbortControllerWrapper; - static NonnullRefPtr<AbortController> create() + static NonnullRefPtr<AbortController> create_with_global_object(HTML::Window& window) { - return adopt_ref(*new AbortController()); - } - - static NonnullRefPtr<AbortController> 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<AbortSignal> signal() const { return m_signal; } + JS::NonnullGCPtr<AbortSignal> signal() const { return *m_signal; } void abort(JS::Value reason); private: - AbortController(); + explicit AbortController(HTML::Window&); // https://dom.spec.whatwg.org/#abortcontroller-signal - NonnullRefPtr<AbortSignal> m_signal; + JS::Handle<AbortSignal> m_signal; }; } diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp index dc28fb3d11..a4cf9b4269 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 <LibWeb/Bindings/AbortSignalWrapper.h> #include <LibWeb/Bindings/DOMExceptionWrapper.h> #include <LibWeb/Bindings/Wrapper.h> #include <LibWeb/DOM/AbortSignal.h> @@ -14,14 +13,14 @@ namespace Web::DOM { -AbortSignal::AbortSignal() - : EventTarget() +JS::NonnullGCPtr<AbortSignal> AbortSignal::create_with_global_object(HTML::Window& window) { + return *window.heap().allocate<AbortSignal>(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<void()> 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<Bindings::WindowObject>(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<void> 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 3166e87a67..572a8d453d 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<AbortSignal> - , public Weakable<AbortSignal> - , public EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::AbortSignalWrapper; - - using RefCounted::ref; - using RefCounted::unref; +class AbortSignal final : public EventTarget { + WEB_PLATFORM_OBJECT(AbortSignal, EventTarget); - static NonnullRefPtr<AbortSignal> create() - { - return adopt_ref(*new AbortSignal()); - } - - static NonnullRefPtr<AbortSignal> create_with_global_object(Bindings::WindowObject&) - { - return AbortSignal::create(); - } +public: + static JS::NonnullGCPtr<AbortSignal> create_with_global_object(HTML::Window&); virtual ~AbortSignal() override = default; @@ -55,15 +40,10 @@ public: JS::ThrowCompletionOr<void> 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 357a0da71f..28e45ba65e 100644 --- a/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp @@ -5,14 +5,14 @@ */ #include <LibWeb/Bindings/AbstractRangePrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/AbstractRange.h> #include <LibWeb/DOM/Document.h> +#include <LibWeb/HTML/Window.h> 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<Bindings::AbstractRangePrototype>("AbstractRange")) + : Bindings::PlatformObject(start_container.document().window().ensure_web_prototype<Bindings::AbstractRangePrototype>("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 e0dded6372..ae97dc54be 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<Node> m_start_container; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr<Node> m_start_container; u32 m_start_offset; - NonnullRefPtr<Node> m_end_container; + JS::NonnullGCPtr<Node> m_end_container; u32 m_end_offset; }; diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.cpp b/Userland/Libraries/LibWeb/DOM/Attribute.cpp index da29d7cdc0..122e3d1ce3 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 <LibWeb/Bindings/AttributePrototype.h> #include <LibWeb/DOM/Attribute.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Element.h> @@ -12,9 +13,9 @@ namespace Web::DOM { -NonnullRefPtr<Attribute> Attribute::create(Document& document, FlyString local_name, String value, Element const* owner_element) +JS::NonnullGCPtr<Attribute> 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<Attribute>(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<Bindings::AttributePrototype>("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 1431d3083b..4f9787fb0b 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<Attribute> create(Document&, FlyString local_name, String value, Element const* = nullptr); +public: + static JS::NonnullGCPtr<Attribute> 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<Element> m_owner_element; + JS::GCPtr<Element> m_owner_element; }; template<> inline bool Node::fast_is<Attribute>() 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 bce61e89c3..5203875e96 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 <LibWeb/Bindings/CDATASectionPrototype.h> #include <LibWeb/DOM/CDATASection.h> +#include <LibWeb/HTML/Window.h> namespace Web::DOM { CDATASection::CDATASection(Document& document, String const& data) : Text(document, NodeType::CDATA_SECTION_NODE, data) { + set_prototype(&window().ensure_web_prototype<Bindings::CDATASectionPrototype>("CDATASection")); } -CDATASection::~CDATASection() -{ -} +CDATASection::~CDATASection() = default; } diff --git a/Userland/Libraries/LibWeb/DOM/CDATASection.h b/Userland/Libraries/LibWeb/DOM/CDATASection.h index bf57d3fad0..a5b18c0cc0 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<CDATASection>() 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 ab1e134271..929d477490 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 <LibWeb/Bindings/CharacterDataPrototype.h> #include <LibWeb/DOM/CharacterData.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/MutationType.h> @@ -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<Bindings::CharacterDataPrototype>("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 5765ee3f3d..481ed6bf69 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<CharacterData> , public NonDocumentTypeChildNode<CharacterData> { -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 4493e41afb..ca7b48ae1d 100644 --- a/Userland/Libraries/LibWeb/DOM/ChildNode.h +++ b/Userland/Libraries/LibWeb/DOM/ChildNode.h @@ -16,7 +16,7 @@ template<typename NodeType> class ChildNode { public: // https://dom.spec.whatwg.org/#dom-childnode-before - ExceptionOr<void> before(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) + ExceptionOr<void> before(Vector<Variant<JS::Handle<Node>, String>> const& nodes) { auto* node = static_cast<NodeType*>(this); @@ -46,7 +46,7 @@ public: } // https://dom.spec.whatwg.org/#dom-childnode-after - ExceptionOr<void> after(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) + ExceptionOr<void> after(Vector<Variant<JS::Handle<Node>, String>> const& nodes) { auto* node = static_cast<NodeType*>(this); @@ -70,7 +70,7 @@ public: } // https://dom.spec.whatwg.org/#dom-childnode-replacewith - ExceptionOr<void> replace_with(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) + ExceptionOr<void> replace_with(Vector<Variant<JS::Handle<Node>, String>> const& nodes) { auto* node = static_cast<NodeType*>(this); @@ -117,7 +117,7 @@ protected: ChildNode() = default; private: - RefPtr<Node> viable_previous_sibling_for_insertion(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) const + JS::GCPtr<Node> viable_previous_sibling_for_insertion(Vector<Variant<JS::Handle<Node>, String>> const& nodes) const { auto* node = static_cast<NodeType const*>(this); @@ -125,11 +125,11 @@ private: bool contained_in_nodes = false; for (auto const& node_or_string : nodes) { - if (!node_or_string.template has<NonnullRefPtr<Node>>()) + if (!node_or_string.template has<JS::Handle<Node>>()) continue; - auto node_in_vector = node_or_string.template get<NonnullRefPtr<Node>>(); - if (node_in_vector.ptr() == previous_sibling) { + auto node_in_vector = node_or_string.template get<JS::Handle<Node>>(); + if (node_in_vector.cell() == previous_sibling) { contained_in_nodes = true; break; } @@ -142,7 +142,7 @@ private: return nullptr; } - RefPtr<Node> viable_nest_sibling_for_insertion(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) const + JS::GCPtr<Node> viable_nest_sibling_for_insertion(Vector<Variant<JS::Handle<Node>, String>> const& nodes) const { auto* node = static_cast<NodeType const*>(this); @@ -150,11 +150,11 @@ private: bool contained_in_nodes = false; for (auto const& node_or_string : nodes) { - if (!node_or_string.template has<NonnullRefPtr<Node>>()) + if (!node_or_string.template has<JS::Handle<Node>>()) continue; - auto node_in_vector = node_or_string.template get<NonnullRefPtr<Node>>(); - if (node_in_vector.ptr() == next_sibling) { + auto& node_in_vector = node_or_string.template get<JS::Handle<Node>>(); + 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 9e79dd5869..b442edc0b2 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> Comment::create_with_global_object(Bindings::WindowObject& window, String const& data) +JS::NonnullGCPtr<Comment> Comment::create_with_global_object(HTML::Window& window, String const& data) { - return make_ref_counted<Comment>(window.impl().associated_document(), data); + return *window.heap().allocate<Comment>(window.realm(), window.associated_document(), data); } } diff --git a/Userland/Libraries/LibWeb/DOM/Comment.h b/Userland/Libraries/LibWeb/DOM/Comment.h index 9696a31137..9f4c37ef3d 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<Comment> create_with_global_object(HTML::Window&, String const& data); virtual ~Comment() override = default; virtual FlyString node_name() const override { return "#comment"; } - static NonnullRefPtr<Comment> create_with_global_object(Bindings::WindowObject& window, String const& data); +private: + explicit Comment(Document&, String const&); }; template<> inline bool Node::fast_is<Comment>() 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 1d5aefb56e..0cf777aa74 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp @@ -6,28 +6,28 @@ */ #include <LibWeb/Bindings/CustomEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/CustomEvent.h> +#include <LibWeb/HTML/Window.h> 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<CustomEvent>(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<Bindings::CustomEventPrototype>("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 5111b346be..50cfd7b63a 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 29c53a1b59..8ad08a11a1 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 a5a9b5d5d5..87a3b744a8 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMEventListener.h +++ b/Userland/Libraries/LibWeb/DOM/DOMEventListener.h @@ -27,7 +27,7 @@ public: JS::GCPtr<IDLEventListener> callback; // signal (null or an AbortSignal object) - RefPtr<DOM::AbortSignal> signal; + JS::GCPtr<DOM::AbortSignal> 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 d3f113e109..8240a300a9 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<DOMException> create_with_global_object(Bindings::WindowObject&, FlyString const& message, FlyString const& name) + static NonnullRefPtr<DOMException> 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 2216cc2f46..afe7045c95 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp @@ -6,25 +6,26 @@ */ #include <LibWeb/Bindings/DOMImplementationPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/DOM/DOMImplementation.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/DocumentType.h> #include <LibWeb/DOM/ElementFactory.h> #include <LibWeb/DOM/Text.h> #include <LibWeb/HTML/Origin.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/Namespace.h> namespace Web::DOM { JS::NonnullGCPtr<DOMImplementation> DOMImplementation::create(Document& document) { - auto& window_object = document.preferred_window_object(); - return *window_object.heap().allocate<DOMImplementation>(window_object.realm(), document); + auto& window = document.window(); + return *window.heap().allocate<DOMImplementation>(document.realm(), document); } DOMImplementation::DOMImplementation(Document& document) - : PlatformObject(document.preferred_window_object().ensure_web_prototype<Bindings::DOMImplementationPrototype>("DOMImplementation")) + : PlatformObject(document.window().ensure_web_prototype<Bindings::DOMImplementationPrototype>("DOMImplementation")) , m_document(document) { } @@ -38,23 +39,23 @@ void DOMImplementation::visit_edges(Cell::Visitor& visitor) } // https://dom.spec.whatwg.org/#dom-domimplementation-createdocument -ExceptionOr<NonnullRefPtr<Document>> DOMImplementation::create_document(String const& namespace_, String const& qualified_name, RefPtr<DocumentType> doctype) const +ExceptionOr<JS::NonnullGCPtr<Document>> DOMImplementation::create_document(String const& namespace_, String const& qualified_name, JS::GCPtr<DocumentType> 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> element; + JS::GCPtr<Element> 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<NonnullRefPtr<Document>> DOMImplementation::create_document(String c } // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument -NonnullRefPtr<Document> DOMImplementation::create_html_document(String const& title) const +JS::NonnullGCPtr<Document> 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<DocumentType>(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<Document> 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<Text>(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<Document> DOMImplementation::create_html_document(String const& ti } // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype -ExceptionOr<NonnullRefPtr<DocumentType>> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id) +ExceptionOr<JS::NonnullGCPtr<DocumentType>> 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 136cd83e1b..9315e459eb 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMImplementation.h +++ b/Userland/Libraries/LibWeb/DOM/DOMImplementation.h @@ -7,30 +7,29 @@ #pragma once -#include <AK/NonnullRefPtr.h> +#include <LibJS/Heap/GCPtr.h> #include <LibWeb/Bindings/PlatformObject.h> #include <LibWeb/DOM/Document.h> namespace Web::DOM { class DOMImplementation final : public Bindings::PlatformObject { - JS_OBJECT(DOMImplementation, Bindings::PlatformObject); + WEB_PLATFORM_OBJECT(DOMImplementation, Bindings::PlatformObject); public: static JS::NonnullGCPtr<DOMImplementation> create(Document&); - explicit DOMImplementation(Document&); virtual ~DOMImplementation(); - DOMImplementation& impl() { return *this; } - - ExceptionOr<NonnullRefPtr<Document>> create_document(String const&, String const&, RefPtr<DocumentType>) const; - NonnullRefPtr<Document> create_html_document(String const& title) const; - ExceptionOr<NonnullRefPtr<DocumentType>> create_document_type(String const& qualified_name, String const& public_id, String const& system_id); + ExceptionOr<JS::NonnullGCPtr<Document>> create_document(String const&, String const&, JS::GCPtr<DocumentType>) const; + JS::NonnullGCPtr<Document> create_html_document(String const& title) const; + ExceptionOr<JS::NonnullGCPtr<DocumentType>> 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 4b3575920f..439d9a3606 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp @@ -8,11 +8,11 @@ #include <AK/CharacterTypes.h> #include <AK/StringBuilder.h> #include <LibWeb/Bindings/DOMTokenListPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/DOM/DOMTokenList.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Element.h> +#include <LibWeb/HTML/Window.h> 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<DOMTokenList>(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<Bindings::DOMTokenListPrototype>("DOMTokenList")) + : Bindings::LegacyPlatformObject(associated_element.document().window().ensure_web_prototype<Bindings::DOMTokenListPrototype>("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<DOM::Element> associated_element = m_associated_element.ptr(); if (!associated_element) return; @@ -244,7 +244,7 @@ ExceptionOr<void> 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<DOM::Element> 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 890caffbc3..658a5457ce 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<void> 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 e53ace8fd8..dd180b8f4a 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -14,8 +14,9 @@ #include <LibJS/Interpreter.h> #include <LibJS/Parser.h> #include <LibJS/Runtime/FunctionObject.h> +#include <LibWeb/Bindings/DocumentPrototype.h> #include <LibWeb/Bindings/MainThreadVM.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/CSS/MediaQueryList.h> #include <LibWeb/CSS/MediaQueryListEvent.h> #include <LibWeb/CSS/StyleComputer.h> #include <LibWeb/Cookie/ParsedCookie.h> @@ -100,7 +101,7 @@ static NonnullRefPtr<HTML::BrowsingContext> 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<HTML::BrowsingContext> obtain_a_browsing_context_to_use_for } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#initialise-the-document-object -NonnullRefPtr<Document> Document::create_and_initialize(Type type, String content_type, HTML::NavigationParams navigation_params) +JS::NonnullGCPtr<Document> 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> Document::create_and_initialize(Type type, String conten creation_url = navigation_params.request->current_url(); } - RefPtr<HTML::Window> window; + JS::GCPtr<HTML::Window> 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> 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<Bindings::WindowObject>(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> 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> Document::create_and_initialize(Type type, String conten return document; } -NonnullRefPtr<Document> Document::create_with_global_object(Bindings::WindowObject&) +JS::NonnullGCPtr<Document> Document::create_with_global_object(HTML::Window& window) { - return Document::create(); + return Document::create(window); } -NonnullRefPtr<Document> Document::create(AK::URL const& url) +JS::NonnullGCPtr<Document> Document::create(HTML::Window& window, AK::URL const& url) { - return adopt_ref(*new Document(url)); + auto& realm = window.realm(); + return *realm.heap().allocate<Document>(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<CSS::StyleComputer>(*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<Bindings::DocumentPrototype>("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<Node> descendants; - for_each_in_inclusive_subtree([&](auto& node) { - if (&node != this) - descendants.append(node); - return IterationDecision::Continue; - }); - - for (auto& node : descendants) { - VERIFY(&node.document() == this); - VERIFY(!node.is_document()); - if (node.parent()) { - // We need to suppress mutation observers so that they don't try and queue a microtask for this Document which is in the process of dying, - // which will cause an `!m_in_removed_last_ref` assertion failure when it tries to ref this Document. - node.remove(true); - } - } - } - - m_in_removed_last_ref = false; - decrement_referencing_node_count(); - return; - } + HTML::main_thread_event_loop().unregister_document({}, *this); +} - m_in_removed_last_ref = false; - m_deletion_has_begun = true; +void Document::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_window.ptr()); + visitor.visit(m_style_sheets.ptr()); + visitor.visit(m_hovered_node.ptr()); + visitor.visit(m_inspected_node.ptr()); + visitor.visit(m_active_favicon.ptr()); + visitor.visit(m_focused_element.ptr()); + visitor.visit(m_active_element.ptr()); + visitor.visit(m_implementation.ptr()); + visitor.visit(m_current_script.ptr()); + visitor.visit(m_associated_inert_template_document.ptr()); + visitor.visit(m_pending_parsing_blocking_script.ptr()); - HTML::main_thread_event_loop().unregister_document({}, *this); + for (auto& script : m_scripts_to_execute_when_parsing_has_finished) + visitor.visit(script.ptr()); + for (auto& script : m_scripts_to_execute_as_soon_as_possible) + visitor.visit(script.ptr()); - delete this; + for (auto& node_iterator : m_node_iterators) + visitor.visit(node_iterator); } // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-write @@ -642,14 +612,14 @@ void Document::set_title(String const& title) if (!head_element) return; - RefPtr<HTML::HTMLTitleElement> title_element = head_element->first_child_of_type<HTML::HTMLTitleElement>(); + JS::GCPtr<HTML::HTMLTitleElement> title_element = head_element->first_child_of_type<HTML::HTMLTitleElement>(); if (!title_element) { - title_element = static_ptr_cast<HTML::HTMLTitleElement>(create_element(HTML::TagNames::title).release_value()); + title_element = &static_cast<HTML::HTMLTitleElement&>(*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<Text>(realm(), *this, title)); if (auto* page = this->page()) { if (browsing_context() == &page->top_level_browsing_context()) @@ -725,13 +695,13 @@ Vector<CSS::BackgroundLayerData> const* Document::background_layers() const return &body_layout_node->background_layers(); } -RefPtr<HTML::HTMLBaseElement> Document::first_base_element_with_href_in_tree_order() const +JS::GCPtr<HTML::HTMLBaseElement> Document::first_base_element_with_href_in_tree_order() const { - RefPtr<HTML::HTMLBaseElement> base_element; + JS::GCPtr<HTML::HTMLBaseElement> base_element; for_each_in_subtree_of_type<HTML::HTMLBaseElement>([&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<Node> old_hovered_node = move(m_hovered_node); + JS::GCPtr<Node> 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<HTML::EnvironmentSettingsObject>(*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<NonnullRefPtr<Element>> Document::create_element(String const& tag_name) +DOM::ExceptionOr<JS::NonnullGCPtr<Element>> 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<NonnullRefPtr<Element>> 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<NonnullRefPtr<Element>> Document::create_element_ns(String const& namespace_, String const& qualified_name) +DOM::ExceptionOr<JS::NonnullGCPtr<Element>> 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<NonnullRefPtr<Element>> 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<DocumentFragment> Document::create_document_fragment() +JS::NonnullGCPtr<DocumentFragment> Document::create_document_fragment() { - return adopt_ref(*new DocumentFragment(*this)); + return *heap().allocate<DocumentFragment>(realm(), *this); } -NonnullRefPtr<Text> Document::create_text_node(String const& data) +JS::NonnullGCPtr<Text> Document::create_text_node(String const& data) { - return adopt_ref(*new Text(*this, data)); + return *heap().allocate<Text>(realm(), *this, data); } -NonnullRefPtr<Comment> Document::create_comment(String const& data) +JS::NonnullGCPtr<Comment> Document::create_comment(String const& data) { - return adopt_ref(*new Comment(*this, data)); + return *heap().allocate<Comment>(realm(), *this, data); } JS::NonnullGCPtr<Range> Document::create_range() @@ -1162,7 +1125,7 @@ JS::NonnullGCPtr<Range> Document::create_range() // https://dom.spec.whatwg.org/#dom-document-createevent DOM::ExceptionOr<JS::NonnullGCPtr<Event>> 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<HTML::HTMLScriptElement m_pending_parsing_blocking_script = script; } -NonnullRefPtr<HTML::HTMLScriptElement> Document::take_pending_parsing_blocking_script(Badge<HTML::HTMLParser>) +JS::NonnullGCPtr<HTML::HTMLScriptElement> Document::take_pending_parsing_blocking_script(Badge<HTML::HTMLParser>) { - 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>, 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<HTML::HTMLScriptElement> Document::take_scripts_to_execute_when_parsing_has_finished(Badge<HTML::HTMLParser>) +Vector<JS::Handle<HTML::HTMLScriptElement>> Document::take_scripts_to_execute_when_parsing_has_finished(Badge<HTML::HTMLParser>) { return move(m_scripts_to_execute_when_parsing_has_finished); } void Document::add_script_to_execute_as_soon_as_possible(Badge<HTML::HTMLScriptElement>, 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<HTML::HTMLScriptElement> Document::take_scripts_to_execute_as_soon_as_possible(Badge<HTML::HTMLParser>) +Vector<JS::Handle<HTML::HTMLScriptElement>> Document::take_scripts_to_execute_as_soon_as_possible(Badge<HTML::HTMLParser>) { return move(m_scripts_to_execute_as_soon_as_possible); } // https://dom.spec.whatwg.org/#dom-document-importnode -ExceptionOr<NonnullRefPtr<Node>> Document::import_node(NonnullRefPtr<Node> node, bool deep) +ExceptionOr<JS::NonnullGCPtr<Node>> Document::import_node(JS::NonnullGCPtr<Node> node, bool deep) { // 1. If node is a document or shadow root, then throw a "NotSupportedError" DOMException. if (is<Document>(*node) || is<ShadowRoot>(*node)) @@ -1299,10 +1265,11 @@ void Document::adopt_node(Node& node) // Transfer NodeIterators rooted at `node` from old_document to this document. Vector<NodeIterator&> 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<NonnullRefPtr<Node>> Document::adopt_node_binding(NonnullRefPtr<Node> node) +ExceptionOr<JS::NonnullGCPtr<Node>> Document::adopt_node_binding(JS::NonnullGCPtr<Node> node) { if (is<Document>(*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<CSS::MediaQueryList>& media_query_list) +void Document::add_media_query_list(JS::NonnullGCPtr<CSS::MediaQueryList> 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<CSS::MediaQueryList> 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::BrowsingContext>, HTML::Window& window) { - m_window = window; + m_window = &window; +} + +CSS::StyleSheetList& Document::style_sheets() +{ + if (!m_style_sheets) + m_style_sheets = CSS::StyleSheetList::create(*this); + return *m_style_sheets; } -Bindings::WindowObject& Document::preferred_window_object() const +CSS::StyleSheetList const& Document::style_sheets() const { - if (m_window && m_window->wrapper()) - return const_cast<Bindings::WindowObject&>(*m_window->wrapper()); - return Bindings::main_thread_internal_window_object(); + return const_cast<Document*>(this)->style_sheets(); } } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index ccd0cd411f..d0d90e87e7 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -17,7 +17,6 @@ #include <AK/WeakPtr.h> #include <LibCore/Forward.h> #include <LibJS/Forward.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/CSS/CSSStyleSheet.h> #include <LibWeb/CSS/StyleComputer.h> #include <LibWeb/CSS/StyleSheetList.h> @@ -31,6 +30,7 @@ #include <LibWeb/HTML/History.h> #include <LibWeb/HTML/Origin.h> #include <LibWeb/HTML/Scripting/Environments.h> +#include <LibWeb/HTML/Window.h> namespace Web::DOM { @@ -44,25 +44,20 @@ class Document : public ParentNode , public NonElementParentNode<Document> , public HTML::GlobalEventHandlers { -public: - using WrapperType = Bindings::DocumentWrapper; + WEB_PLATFORM_OBJECT(Document, ParentNode); +public: enum class Type { XML, HTML }; - static NonnullRefPtr<Document> create_and_initialize(Type, String content_type, HTML::NavigationParams); + static JS::NonnullGCPtr<Document> create_and_initialize(Type, String content_type, HTML::NavigationParams); - static NonnullRefPtr<Document> create(AK::URL const& url = "about:blank"sv); - static NonnullRefPtr<Document> create_with_global_object(Bindings::WindowObject&); + static JS::NonnullGCPtr<Document> create(HTML::Window&, AK::URL const& url = "about:blank"sv); + static JS::NonnullGCPtr<Document> 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<Layout::Node>) { 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<HTML::HTMLBaseElement> first_base_element_with_href_in_tree_order() const; + JS::GCPtr<HTML::HTMLBaseElement> 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<NonnullRefPtr<Element>> create_element(String const& tag_name); - ExceptionOr<NonnullRefPtr<Element>> create_element_ns(String const& namespace_, String const& qualified_name); - NonnullRefPtr<DocumentFragment> create_document_fragment(); - NonnullRefPtr<Text> create_text_node(String const& data); - NonnullRefPtr<Comment> create_comment(String const& data); + ExceptionOr<JS::NonnullGCPtr<Element>> create_element(String const& tag_name); + ExceptionOr<JS::NonnullGCPtr<Element>> create_element_ns(String const& namespace_, String const& qualified_name); + JS::NonnullGCPtr<DocumentFragment> create_document_fragment(); + JS::NonnullGCPtr<Text> create_text_node(String const& data); + JS::NonnullGCPtr<Comment> create_comment(String const& data); ExceptionOr<JS::NonnullGCPtr<Event>> create_event(String const& interface); JS::NonnullGCPtr<Range> create_range(); void set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement*); - HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; } - NonnullRefPtr<HTML::HTMLScriptElement> take_pending_parsing_blocking_script(Badge<HTML::HTMLParser>); + HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script.ptr(); } + JS::NonnullGCPtr<HTML::HTMLScriptElement> take_pending_parsing_blocking_script(Badge<HTML::HTMLParser>); void add_script_to_execute_when_parsing_has_finished(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement&); - NonnullRefPtrVector<HTML::HTMLScriptElement> take_scripts_to_execute_when_parsing_has_finished(Badge<HTML::HTMLParser>); - NonnullRefPtrVector<HTML::HTMLScriptElement>& scripts_to_execute_when_parsing_has_finished() { return m_scripts_to_execute_when_parsing_has_finished; } + Vector<JS::Handle<HTML::HTMLScriptElement>> take_scripts_to_execute_when_parsing_has_finished(Badge<HTML::HTMLParser>); + Vector<JS::Handle<HTML::HTMLScriptElement>>& 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>, HTML::HTMLScriptElement&); - NonnullRefPtrVector<HTML::HTMLScriptElement> take_scripts_to_execute_as_soon_as_possible(Badge<HTML::HTMLParser>); - NonnullRefPtrVector<HTML::HTMLScriptElement>& scripts_to_execute_as_soon_as_possible() { return m_scripts_to_execute_as_soon_as_possible; } + Vector<JS::Handle<HTML::HTMLScriptElement>> take_scripts_to_execute_as_soon_as_possible(Badge<HTML::HTMLParser>); + Vector<JS::Handle<HTML::HTMLScriptElement>>& 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<NonnullRefPtr<Node>> import_node(NonnullRefPtr<Node> node, bool deep); + ExceptionOr<JS::NonnullGCPtr<Node>> import_node(JS::NonnullGCPtr<Node> node, bool deep); void adopt_node(Node&); - ExceptionOr<NonnullRefPtr<Node>> adopt_node_binding(NonnullRefPtr<Node>); + ExceptionOr<JS::NonnullGCPtr<Node>> adopt_node_binding(JS::NonnullGCPtr<Node>); 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<Node>) - { - increment_referencing_node_count(); - } - - void unref_from_node(Badge<Node>) - { - 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<HTML::Window&>(*m_window); } void set_window(Badge<HTML::BrowsingContext>, HTML::Window&); @@ -280,7 +261,7 @@ public: ExceptionOr<Document*> open(String const& = "", String const& = ""); ExceptionOr<void> 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<HTML::HTMLScriptElement> current_script() const { return m_current_script; } - void set_current_script(Badge<HTML::HTMLScriptElement>, RefPtr<HTML::HTMLScriptElement> script) { m_current_script = move(script); } + JS::GCPtr<HTML::HTMLScriptElement> current_script() const { return m_current_script.ptr(); } + void set_current_script(Badge<HTML::HTMLScriptElement>, JS::GCPtr<HTML::HTMLScriptElement> 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<CSS::MediaQueryList>&); + void add_media_query_list(JS::NonnullGCPtr<CSS::MediaQueryList>); bool has_focus() const; @@ -359,15 +340,13 @@ public: template<typename Callback> 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<void> 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<CSS::StyleComputer> m_style_computer; - JS::Handle<CSS::StyleSheetList> m_style_sheets; - RefPtr<Node> m_hovered_node; - RefPtr<Node> m_inspected_node; - RefPtr<Node> m_active_favicon; + JS::GCPtr<CSS::StyleSheetList> m_style_sheets; + JS::GCPtr<Node> m_hovered_node; + JS::GCPtr<Node> m_inspected_node; + JS::GCPtr<Node> m_active_favicon; WeakPtr<HTML::BrowsingContext> m_browsing_context; AK::URL m_url; - RefPtr<HTML::Window> m_window; + JS::GCPtr<HTML::Window> m_window; RefPtr<Layout::InitialContainingBlock> m_layout_root; @@ -434,9 +397,9 @@ private: OwnPtr<JS::Interpreter> m_interpreter; - RefPtr<HTML::HTMLScriptElement> m_pending_parsing_blocking_script; - NonnullRefPtrVector<HTML::HTMLScriptElement> m_scripts_to_execute_when_parsing_has_finished; - NonnullRefPtrVector<HTML::HTMLScriptElement> m_scripts_to_execute_as_soon_as_possible; + JS::GCPtr<HTML::HTMLScriptElement> m_pending_parsing_blocking_script; + Vector<JS::Handle<HTML::HTMLScriptElement>> m_scripts_to_execute_when_parsing_has_finished; + Vector<JS::Handle<HTML::HTMLScriptElement>> m_scripts_to_execute_as_soon_as_possible; QuirksMode m_quirks_mode { QuirksMode::No }; @@ -445,11 +408,11 @@ private: bool m_editable { false }; - WeakPtr<Element> m_focused_element; - WeakPtr<Element> m_active_element; + JS::GCPtr<Element> m_focused_element; + JS::GCPtr<Element> m_active_element; bool m_created_for_appropriate_template_contents { false }; - RefPtr<Document> m_associated_inert_template_document; + JS::GCPtr<Document> 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<DOMImplementation> m_implementation; - RefPtr<HTML::HTMLScriptElement> m_current_script; + JS::GCPtr<DOMImplementation> m_implementation; + JS::GCPtr<HTML::HTMLScriptElement> 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 67dc77eea2..58ceeb3f3c 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 <LibWeb/Bindings/DocumentFragmentPrototype.h> #include <LibWeb/DOM/DocumentFragment.h> #include <LibWeb/HTML/Window.h> @@ -12,12 +13,24 @@ namespace Web::DOM { DocumentFragment::DocumentFragment(Document& document) : ParentNode(document, NodeType::DOCUMENT_FRAGMENT_NODE) { + set_prototype(&window().ensure_web_prototype<Bindings::DocumentFragmentPrototype>("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> DocumentFragment::create_with_global_object(Bindings::WindowObject& window) +JS::NonnullGCPtr<DocumentFragment> DocumentFragment::create_with_global_object(HTML::Window& window) { - return make_ref_counted<DocumentFragment>(window.impl().associated_document()); + return *window.heap().allocate<DocumentFragment>(window.realm(), window.associated_document()); } } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentFragment.h b/Userland/Libraries/LibWeb/DOM/DocumentFragment.h index 715e9c8bbf..496ce67f9a 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<DocumentFragment> { -public: - using WrapperType = Bindings::DocumentFragmentWrapper; + WEB_PLATFORM_OBJECT(DocumentFragment, ParentNode); - static NonnullRefPtr<DocumentFragment> create_with_global_object(Bindings::WindowObject& window); +public: + static JS::NonnullGCPtr<DocumentFragment> create_with_global_object(HTML::Window& window); - explicit DocumentFragment(Document& document); virtual ~DocumentFragment() override = default; virtual FlyString node_name() const override { return "#document-fragment"; } - Element* host() { return m_host; } - Element const* host() const { return m_host; } + Element* host() { return m_host.ptr(); } + Element const* host() const { return m_host.ptr(); } - void set_host(Element* host) { m_host = host; } + void set_host(Element*); + +protected: + explicit DocumentFragment(Document& document); + + virtual void visit_edges(Cell::Visitor&) override; private: // https://dom.spec.whatwg.org/#concept-documentfragment-host - WeakPtr<Element> m_host; + JS::GCPtr<Element> m_host; }; template<> inline bool Node::fast_is<DocumentFragment>() 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 60043ea00c..44771d859e 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 ac8a17294f..72cf923e7b 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h +++ b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h @@ -7,7 +7,7 @@ #pragma once #include <AK/Noncopyable.h> -#include <AK/NonnullRefPtr.h> +#include <LibJS/Heap/Handle.h> #include <LibWeb/Forward.h> namespace Web::DOM { @@ -21,7 +21,7 @@ public: ~DocumentLoadEventDelayer(); private: - NonnullRefPtr<Document> m_document; + JS::Handle<Document> m_document; }; } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentType.cpp b/Userland/Libraries/LibWeb/DOM/DocumentType.cpp index 1f03de4657..e3b34b5fd6 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 <kling@serenityos.org> + * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/DocumentTypePrototype.h> +#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/DocumentType.h> namespace Web::DOM { +JS::NonnullGCPtr<DocumentType> DocumentType::create(Document& document) +{ + return *document.heap().allocate<DocumentType>(document.realm(), document); +} + DocumentType::DocumentType(Document& document) : Node(document, NodeType::DOCUMENT_TYPE_NODE) { + set_prototype(&window().ensure_web_prototype<Bindings::DocumentTypePrototype>("DocumentType")); } } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentType.h b/Userland/Libraries/LibWeb/DOM/DocumentType.h index 89816ef0ea..f540813aa1 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<DocumentType> { -public: - using WrapperType = Bindings::DocumentTypeWrapper; + WEB_PLATFORM_OBJECT(DocumentType, Node); - static NonnullRefPtr<DocumentType> create(Document& document) - { - return adopt_ref(*new DocumentType(document)); - } +public: + static JS::NonnullGCPtr<DocumentType> create(Document&); - explicit DocumentType(Document&); virtual ~DocumentType() override = default; virtual FlyString node_name() const override { return "#doctype"; } @@ -38,6 +34,8 @@ public: void set_system_id(String const& system_id) { m_system_id = system_id; } private: + explicit DocumentType(Document&); + String m_name; String m_public_id; String m_system_id; @@ -47,3 +45,5 @@ template<> inline bool Node::fast_is<DocumentType>() 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 89fe06ce28..665bf4b40e 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -8,6 +8,7 @@ #include <AK/CharacterTypes.h> #include <AK/Debug.h> #include <AK/StringBuilder.h> +#include <LibWeb/Bindings/ElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/CSS/PropertyID.h> #include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h> @@ -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<Bindings::ElementPrototype>("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<Layout::Node> 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<CSS::StyleProperties> 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<HTMLCollection> Element::get_elements_by_class_name(FlyString cons }); } -void Element::set_shadow_root(RefPtr<ShadowRoot> shadow_root) +void Element::set_shadow_root(JS::GCPtr<ShadowRoot> shadow_root) { if (m_shadow_root == shadow_root) return; @@ -509,9 +521,9 @@ void Element::set_shadow_root(RefPtr<ShadowRoot> 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<void()> 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 7da6d5b849..45aa9411e1 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<Element> , public NonDocumentTypeChildNode<Element> { + 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<bool> toggle_attribute(FlyString const& name, Optional<bool> 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<String> get_attribute_names() const; DOMTokenList* class_list(); @@ -115,9 +114,9 @@ public: NonnullRefPtr<HTMLCollection> 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>); + ShadowRoot* shadow_root() { return m_shadow_root.ptr(); } + ShadowRoot const* shadow_root() const { return m_shadow_root.ptr(); } + void set_shadow_root(JS::GCPtr<ShadowRoot>); void set_custom_properties(HashMap<FlyString, CSS::StyleProperty> custom_properties) { m_custom_properties = move(custom_properties); } HashMap<FlyString, CSS::StyleProperty> 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<NamedNodeMap> m_attributes; - JS::Handle<CSS::ElementInlineCSSStyleDeclaration> m_inline_style; + JS::NonnullGCPtr<NamedNodeMap> m_attributes; + JS::GCPtr<CSS::ElementInlineCSSStyleDeclaration> m_inline_style; + JS::GCPtr<DOMTokenList> m_class_list; + JS::GCPtr<ShadowRoot> m_shadow_root; RefPtr<CSS::StyleProperties> m_computed_css_values; HashMap<FlyString, CSS::StyleProperty> m_custom_properties; - JS::Handle<DOMTokenList> m_class_list; Vector<FlyString> m_classes; - RefPtr<ShadowRoot> m_shadow_root; - Array<RefPtr<Layout::Node>, CSS::Selector::PseudoElementCount> m_pseudo_element_nodes; }; @@ -171,3 +171,5 @@ inline bool Node::fast_is<Element>() const { return is_element(); } ExceptionOr<QualifiedName> 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 e1d7329db7..350ab64d2f 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 <kling@serenityos.org> + * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020, Luke Wilde <lukew@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/ElementFactory.h> #include <LibWeb/HTML/HTMLAnchorElement.h> #include <LibWeb/HTML/HTMLAreaElement.h> @@ -93,7 +94,7 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#concept-create-element -NonnullRefPtr<Element> create_element(Document& document, FlyString local_name, FlyString namespace_, FlyString prefix) +JS::NonnullGCPtr<Element> 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<Element> 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<HTML::HTMLAnchorElement>(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<HTML::HTMLAreaElement>(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<HTML::HTMLAudioElement>(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<HTML::HTMLBaseElement>(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<HTML::HTMLBlinkElement>(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<HTML::HTMLBodyElement>(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<HTML::HTMLBRElement>(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<HTML::HTMLButtonElement>(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<HTML::HTMLCanvasElement>(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<HTML::HTMLDataElement>(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<HTML::HTMLDataListElement>(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<HTML::HTMLDetailsElement>(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<HTML::HTMLDialogElement>(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<HTML::HTMLDirectoryElement>(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<HTML::HTMLDivElement>(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<HTML::HTMLDListElement>(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<HTML::HTMLEmbedElement>(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<HTML::HTMLFieldSetElement>(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<HTML::HTMLFontElement>(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<HTML::HTMLFormElement>(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<HTML::HTMLFrameElement>(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<HTML::HTMLFrameSetElement>(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<HTML::HTMLHeadElement>(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<HTML::HTMLHeadingElement>(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<HTML::HTMLHRElement>(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<HTML::HTMLHtmlElement>(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<HTML::HTMLIFrameElement>(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<HTML::HTMLImageElement>(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<HTML::HTMLInputElement>(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<HTML::HTMLLabelElement>(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<HTML::HTMLLegendElement>(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<HTML::HTMLLIElement>(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<HTML::HTMLLinkElement>(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<HTML::HTMLMapElement>(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<HTML::HTMLMarqueeElement>(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<HTML::HTMLMenuElement>(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<HTML::HTMLMetaElement>(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<HTML::HTMLMeterElement>(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<HTML::HTMLModElement>(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<HTML::HTMLObjectElement>(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<HTML::HTMLOListElement>(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<HTML::HTMLOptGroupElement>(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<HTML::HTMLOptionElement>(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<HTML::HTMLOutputElement>(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<HTML::HTMLParagraphElement>(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<HTML::HTMLParamElement>(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<HTML::HTMLPictureElement>(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<HTML::HTMLPreElement>(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<HTML::HTMLProgressElement>(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<HTML::HTMLQuoteElement>(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<HTML::HTMLScriptElement>(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<HTML::HTMLSelectElement>(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<HTML::HTMLSlotElement>(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<HTML::HTMLSourceElement>(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<HTML::HTMLSpanElement>(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<HTML::HTMLStyleElement>(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<HTML::HTMLTableCaptionElement>(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<HTML::HTMLTableCellElement>(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<HTML::HTMLTableColElement>(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<HTML::HTMLTableElement>(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<HTML::HTMLTableRowElement>(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<HTML::HTMLTableSectionElement>(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<HTML::HTMLTemplateElement>(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<HTML::HTMLTextAreaElement>(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<HTML::HTMLTimeElement>(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<HTML::HTMLTitleElement>(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<HTML::HTMLTrackElement>(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<HTML::HTMLUListElement>(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<HTML::HTMLVideoElement>(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<HTML::HTMLElement>(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<SVG::SVGSVGElement>(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<SVG::SVGClipPathElement>(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<SVG::SVGCircleElement>(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<SVG::SVGDefsElement>(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<SVG::SVGEllipseElement>(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<SVG::SVGLineElement>(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<SVG::SVGPathElement>(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<SVG::SVGPolygonElement>(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<SVG::SVGPolylineElement>(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<SVG::SVGRectElement>(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<SVG::SVGGElement>(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<SVG::SVGTextContentElement>(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<HTML::HTMLUnknownElement>(realm, document, move(qualified_name)); } } diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.h b/Userland/Libraries/LibWeb/DOM/ElementFactory.h index 879b1e004b..3c9ac81cbb 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.h +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.h @@ -10,6 +10,6 @@ namespace Web::DOM { -NonnullRefPtr<Element> create_element(Document&, FlyString local_name, FlyString namespace_, FlyString prefix = {}); +JS::NonnullGCPtr<Element> 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 5ccba65e31..024fa0104f 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.cpp +++ b/Userland/Libraries/LibWeb/DOM/Event.cpp @@ -8,31 +8,31 @@ #include <AK/TypeCasts.h> #include <LibWeb/Bindings/EventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/Node.h> #include <LibWeb/DOM/ShadowRoot.h> +#include <LibWeb/HTML/Window.h> namespace Web::DOM { -JS::NonnullGCPtr<Event> Event::create(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init) +JS::NonnullGCPtr<Event> Event::create(HTML::Window& window_object, FlyString const& event_name, EventInit const& event_init) { return *window_object.heap().allocate<Event>(window_object.realm(), window_object, event_name, event_init); } -JS::NonnullGCPtr<Event> Event::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init) +JS::NonnullGCPtr<Event> 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<Bindings::EventPrototype>("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<Bindings::EventPrototype>("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<EventTarget> shadow_adjusted_target, RefPtr<EventTarget> related_target, TouchTargetList& touch_targets, bool slot_in_closed_tree) +void Event::append_to_path(EventTarget& invocation_target, JS::GCPtr<EventTarget> shadow_adjusted_target, JS::GCPtr<EventTarget> 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<EventTarget> Event::composed_path() const +Vector<JS::Handle<EventTarget>> Event::composed_path() const { // 1. Let composedPath be an empty list. - NonnullRefPtrVector<EventTarget> composed_path; + Vector<JS::Handle<EventTarget>> composed_path; // 2. Let path be this’s path. (NOTE: Not necessary) @@ -136,7 +136,7 @@ NonnullRefPtrVector<EventTarget> 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<EventTarget*>(m_current_target.ptr())); // 6. Let currentTargetIndex be 0. size_t current_target_index = 0; @@ -182,7 +182,7 @@ NonnullRefPtrVector<EventTarget> 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<EventTarget*>(path_entry.invocation_target.ptr())); } // 3. If path[index]'s slot-in-closed-tree is true, then: @@ -214,7 +214,7 @@ NonnullRefPtrVector<EventTarget> 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<EventTarget*>(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 51e8533025..d4cb3edd34 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.h +++ b/Userland/Libraries/LibWeb/DOM/Event.h @@ -8,8 +8,8 @@ #include <AK/FlyString.h> #include <LibWeb/Bindings/PlatformObject.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/EventTarget.h> +#include <LibWeb/HTML/Window.h> 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<RefPtr<EventTarget>>; + // FIXME: These need explicit marking somehow. + using TouchTargetList = Vector<JS::GCPtr<EventTarget>>; struct PathEntry { - RefPtr<EventTarget> invocation_target; + JS::GCPtr<EventTarget> invocation_target; bool invocation_target_in_shadow_tree { false }; - RefPtr<EventTarget> shadow_adjusted_target; - RefPtr<EventTarget> related_target; + JS::GCPtr<EventTarget> shadow_adjusted_target; + JS::GCPtr<EventTarget> 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<PathEntry>; - static JS::NonnullGCPtr<Event> create(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init = {}); - static JS::NonnullGCPtr<Event> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init); + static JS::NonnullGCPtr<Event> create(HTML::Window&, FlyString const& event_name, EventInit const& event_init = {}); + static JS::NonnullGCPtr<Event> 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<EventTarget> target() const { return m_target; } + JS::GCPtr<EventTarget> target() const { return m_target; } void set_target(EventTarget* target) { m_target = target; } // NOTE: This is intended for the JS bindings. - RefPtr<EventTarget> src_element() const { return target(); } + JS::GCPtr<EventTarget> src_element() const { return target(); } - RefPtr<EventTarget> related_target() const { return m_related_target; } + JS::GCPtr<EventTarget> 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<EventTarget> current_target() const { return m_current_target; } + JS::GCPtr<EventTarget> 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<EventTarget>, RefPtr<EventTarget>, TouchTargetList&, bool); + void append_to_path(EventTarget&, JS::GCPtr<EventTarget>, JS::GCPtr<EventTarget>, 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<EventTarget> composed_path() const; + Vector<JS::Handle<EventTarget>> composed_path() const; protected: void initialize_event(String const&, bool, bool); private: FlyString m_type; - RefPtr<EventTarget> m_target; - RefPtr<EventTarget> m_related_target; - RefPtr<EventTarget> m_current_target; + JS::GCPtr<EventTarget> m_target; + JS::GCPtr<EventTarget> m_related_target; + JS::GCPtr<EventTarget> 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 5112681d92..19a9bb9da3 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp @@ -8,10 +8,7 @@ #include <AK/TypeCasts.h> #include <LibJS/Runtime/AbstractOperations.h> #include <LibJS/Runtime/FunctionObject.h> -#include <LibWeb/Bindings/EventTargetWrapper.h> -#include <LibWeb/Bindings/EventTargetWrapperFactory.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/AbortSignal.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> @@ -93,8 +90,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent Event* current_event = nullptr; // 8. If global is a Window object, then: - if (is<Bindings::WindowObject>(global)) { - auto& bindings_window_global = verify_cast<Bindings::WindowObject>(global); + if (is<HTML::Window>(global)) { + auto& bindings_window_global = verify_cast<HTML::Window>(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<JS::Handle<DOM::DOMEvent // 10. Call a user object’s operation with listener’s callback, "handleEvent", « event », and event’s currentTarget attribute value. If this throws an exception, then: // FIXME: These should be wrapped for us in call_user_object_operation, but it currently doesn't do that. - auto* this_value = Bindings::wrap(realm, *event.current_target()); - auto* wrapped_event = Bindings::wrap(realm, event); + auto* this_value = event.current_target().ptr(); + auto* wrapped_event = &event; auto result = Bindings::IDL::call_user_object_operation(callback, "handleEvent", this_value, wrapped_event); // If this throws an exception, then: @@ -127,8 +124,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent event.set_in_passive_listener(false); // 12. If global is a Window object, then set global’s current event to currentEvent. - if (is<Bindings::WindowObject>(global)) { - auto& bindings_window_global = verify_cast<Bindings::WindowObject>(global); + if (is<HTML::Window>(global)) { + auto& bindings_window_global = verify_cast<HTML::Window>(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<JS::Handle<DOM::DOMEvent void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Phase phase) { auto last_valid_shadow_adjusted_target = event.path().last_matching([&struct_](auto& entry) { - return entry.index <= struct_.index && !entry.shadow_adjusted_target.is_null(); + return entry.index <= struct_.index && entry.shadow_adjusted_target; }); VERIFY(last_valid_shadow_adjusted_target.has_value()); // 1. Set event’s target to the shadow-adjusted target of the last struct in event’s path, // that is either struct or preceding struct, whose shadow-adjusted target is non-null. - event.set_target(last_valid_shadow_adjusted_target.value().shadow_adjusted_target); + event.set_target(last_valid_shadow_adjusted_target.value().shadow_adjusted_target.ptr()); // 2. Set event’s relatedTarget to struct’s relatedTarget. - event.set_related_target(struct_.related_target); + event.set_related_target(struct_.related_target.ptr()); // 3. Set event’s touch target list to struct’s touch target list. event.set_touch_target_list(struct_.touch_target_list); @@ -166,7 +163,7 @@ void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Pha return; // 5. Initialize event’s currentTarget attribute to struct’s invocation target. - event.set_current_target(struct_.invocation_target); + event.set_current_target(struct_.invocation_target.ptr()); // 6. Let listeners be a clone of event’s currentTarget attribute value’s event listener list. // NOTE: This avoids event listeners added after this point from being run. Note that removal still has an effect due to the removed field. @@ -205,25 +202,25 @@ void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Pha } // https://dom.spec.whatwg.org/#concept-event-dispatch -bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, Event& event, bool legacy_target_override) +bool EventDispatcher::dispatch(JS::NonnullGCPtr<EventTarget> 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<EventTarget> target_override; + JS::GCPtr<EventTarget> target_override; if (!legacy_target_override) { target_override = target; } else { - target_override = verify_cast<HTML::Window>(*target).associated_document(); + target_override = &verify_cast<HTML::Window>(*target).associated_document(); } // 3. Let activationTarget be null. - RefPtr<EventTarget> activation_target; + JS::GCPtr<EventTarget> activation_target; // 4. Let relatedTarget be the result of retargeting event’s relatedTarget against target. - RefPtr<EventTarget> related_target = retarget(event.related_target(), target); + JS::GCPtr<EventTarget> 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<EventTarget> 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<EventTarget> 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 0943192787..26db70fa00 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<EventTarget>, Event&, bool legacy_target_override = false); + static bool dispatch(JS::NonnullGCPtr<EventTarget>, 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 c20e87f79f..58eb036cce 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp @@ -13,8 +13,7 @@ #include <LibJS/Runtime/NativeFunction.h> #include <LibJS/Runtime/ObjectEnvironment.h> #include <LibJS/Runtime/VM.h> -#include <LibWeb/Bindings/DocumentWrapper.h> -#include <LibWeb/Bindings/EventTargetWrapperFactory.h> +#include <LibWeb/Bindings/EventTargetPrototype.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> #include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/DOM/AbortSignal.h> @@ -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<JS::Handle<DOMEventListener>> EventTarget::event_listener_list() +{ + Vector<JS::Handle<DOMEventListener>> 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<EventListenerOptions, bool> const& options) { @@ -64,7 +86,7 @@ struct FlattenedAddEventListenerOptions { bool capture { false }; bool passive { false }; bool once { false }; - RefPtr<AbortSignal> signal; + JS::GCPtr<AbortSignal> 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<AbortSignal> signal; + JS::GCPtr<AbortSignal> signal; // 4. If options is a dictionary, then: if (options.has<AddEventListenerOptions>()) { @@ -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<String>()) { // 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> element; - RefPtr<Document> document; + JS::GCPtr<Element> element; + JS::GCPtr<Document> document; if (is<Element>(this)) { auto* element_event_target = verify_cast<Element>(this); element = element_event_target; - document = element_event_target->document(); + document = &element_event_target->document(); } else { VERIFY(is<HTML::Window>(this)); auto* window_event_target = verify_cast<HTML::Window>(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<HTML::HTMLFormElement> form_owner; + JS::GCPtr<HTML::HTMLFormElement> form_owner; if (is<HTML::FormAssociatedElement>(element.ptr())) { auto* form_associated_element = dynamic_cast<HTML::FormAssociatedElement*>(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<Bindings::CallbackType*>()) { - realm = &event_handler.value.get<Bindings::CallbackType*>()->callback_context.realm(); - } else if (is<Element>(this)) { - realm = &verify_cast<Element>(*this).document().realm(); - } else { - auto& window = verify_cast<HTML::Window>(*this); - // If an element attribute is set on a <body> 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<JS::Value> { + realm, [event_target = JS::make_handle(*this), name](JS::VM& vm) mutable -> JS::ThrowCompletionOr<JS::Value> { // 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<Bindings::EventWrapper>(event_wrapper_argument.as_object()); + auto& event_wrapper = verify_cast<DOM::Event>(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<Bindings::CallbackType>(*callback_function, verify_cast<HTML::EnvironmentSettingsObject>(*realm->host_defined())); + auto* callback = realm.heap().allocate_without_realm<Bindings::CallbackType>(*callback_function, verify_cast<HTML::EnvironmentSettingsObject>(*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<DOMEventListener>(); + auto* listener = realm.heap().allocate_without_realm<DOMEventListener>(); 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 9d94fb9129..cbd785643e 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -10,6 +10,7 @@ #include <AK/Noncopyable.h> #include <AK/Vector.h> #include <LibJS/Forward.h> +#include <LibWeb/Bindings/PlatformObject.h> #include <LibWeb/DOM/DOMEventListener.h> #include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/Forward.h> @@ -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<AddEventListenerOptions, bool> const& options); @@ -39,16 +36,13 @@ public: virtual bool dispatch_event(Event&); ExceptionOr<bool> 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<JS::Handle<DOMEventListener>> event_listener_list(); Function<void(Event const&)> 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<JS::Handle<DOMEventListener>> m_event_listener_list; + Vector<JS::NonnullGCPtr<DOMEventListener>> 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<FlyString, JS::Handle<HTML::EventHandler>> m_event_handler_map; + HashMap<FlyString, JS::GCPtr<HTML::EventHandler>> 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 c4f4bb7c63..9f95e30094 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<bool(Element const&)> filter) - : m_root(root) + : m_root(JS::make_handle(root)) , m_filter(move(filter)) { } HTMLCollection::~HTMLCollection() = default; -Vector<NonnullRefPtr<Element>> HTMLCollection::collect_matching_elements() const +JS::MarkedVector<Element*> HTMLCollection::collect_matching_elements() const { - Vector<NonnullRefPtr<Element>> elements; + JS::MarkedVector<Element*> elements(m_root->heap()); m_root->for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) { if (m_filter(element)) - elements.append(element); + elements.append(const_cast<Element*>(&element)); return IterationDecision::Continue; }); return elements; diff --git a/Userland/Libraries/LibWeb/DOM/HTMLCollection.h b/Userland/Libraries/LibWeb/DOM/HTMLCollection.h index ea1ceaa883..eae346bf07 100644 --- a/Userland/Libraries/LibWeb/DOM/HTMLCollection.h +++ b/Userland/Libraries/LibWeb/DOM/HTMLCollection.h @@ -9,6 +9,7 @@ #include <AK/FlyString.h> #include <AK/Function.h> #include <AK/Noncopyable.h> +#include <LibJS/Heap/GCPtr.h> #include <LibWeb/Bindings/Wrappable.h> #include <LibWeb/Forward.h> @@ -45,7 +46,7 @@ public: Element* item(size_t index) const; Element* named_item(FlyString const& name) const; - Vector<NonnullRefPtr<Element>> collect_matching_elements() const; + JS::MarkedVector<Element*> collect_matching_elements() const; Vector<String> supported_property_names() const; bool is_supported_property_index(u32) const; @@ -53,10 +54,10 @@ public: protected: HTMLCollection(ParentNode& root, Function<bool(Element const&)> filter); - NonnullRefPtr<ParentNode> root() { return m_root; } + JS::NonnullGCPtr<ParentNode> root() { return *m_root; } private: - NonnullRefPtr<ParentNode> m_root; + JS::Handle<ParentNode> m_root; Function<bool(Element const&)> m_filter; }; diff --git a/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp b/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp index 5c4c75f582..6fd55576e4 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 <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/IDLEventListener.h> +#include <LibWeb/HTML/Window.h> namespace Web::DOM { diff --git a/Userland/Libraries/LibWeb/DOM/IDLEventListener.h b/Userland/Libraries/LibWeb/DOM/IDLEventListener.h index f372353462..451ed60980 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<NonnullRefPtr<AbortSignal>> signal; + Optional<JS::NonnullGCPtr<AbortSignal>> signal; }; class IDLEventListener final : public JS::Object { JS_OBJECT(IDLEventListener, JS::Object); public: - IDLEventListener& impl() { return *this; } - static JS::NonnullGCPtr<IDLEventListener> create(JS::Realm&, JS::NonnullGCPtr<Bindings::CallbackType>); IDLEventListener(JS::Realm&, JS::NonnullGCPtr<Bindings::CallbackType>); diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp index 544f3bc244..5f19146094 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<bool(Node const&)> filter) - : m_root(root) + : m_root(JS::make_handle(root)) , m_filter(move(filter)) { } -NonnullRefPtrVector<Node> LiveNodeList::collection() const +JS::MarkedVector<Node*> LiveNodeList::collection() const { - NonnullRefPtrVector<Node> nodes; + JS::MarkedVector<Node*> 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*>(&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 1fe1c70a31..4c35b9e2b0 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<bool(Node const&)> filter); - NonnullRefPtrVector<Node> collection() const; + JS::MarkedVector<Node*> collection() const; - NonnullRefPtr<Node> m_root; + JS::Handle<Node> m_root; Function<bool(Node const&)> m_filter; }; diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp index e600ac58d9..7a7e9e8114 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp +++ b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp @@ -5,14 +5,14 @@ */ #include <LibWeb/Bindings/MainThreadVM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/MutationObserver.h> #include <LibWeb/DOM/Node.h> +#include <LibWeb/HTML/Window.h> namespace Web::DOM { // https://dom.spec.whatwg.org/#dom-mutationobserver-mutationobserver -MutationObserver::MutationObserver(Bindings::WindowObject& window_object, JS::Handle<Bindings::CallbackType> callback) +MutationObserver::MutationObserver(HTML::Window& window_object, JS::Handle<Bindings::CallbackType> callback) : m_callback(move(callback)) { // 1. Set this’s callback to callback. @@ -83,7 +83,7 @@ ExceptionOr<void> 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<Node>()); } return {}; diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.h b/Userland/Libraries/LibWeb/DOM/MutationObserver.h index 961220fda6..b222d9eaa4 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<MutationObserver> create_with_global_object(Bindings::WindowObject& window_object, Bindings::CallbackType* callback) + static NonnullRefPtr<MutationObserver> 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<Bindings::CallbackType> callback); + MutationObserver(HTML::Window& window_object, JS::Handle<Bindings::CallbackType> callback); // https://dom.spec.whatwg.org/#concept-mo-callback JS::Handle<Bindings::CallbackType> m_callback; diff --git a/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp b/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp index ded0a0ec71..78fdbdb9c6 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<Node> m_target; + JS::Handle<Node> m_target; NonnullRefPtr<NodeList> m_added_nodes; NonnullRefPtr<NodeList> m_removed_nodes; - RefPtr<Node> m_previous_sibling; - RefPtr<Node> m_next_sibling; + JS::Handle<Node> m_previous_sibling; + JS::Handle<Node> 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 bcc41bc824..3a80acc748 100644 --- a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp +++ b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp @@ -6,9 +6,6 @@ */ #include <LibWeb/Bindings/NamedNodeMapPrototype.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Attribute.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/NamedNodeMap.h> @@ -16,18 +13,26 @@ namespace Web::DOM { -NamedNodeMap* NamedNodeMap::create(Element& element) +JS::NonnullGCPtr<NamedNodeMap> NamedNodeMap::create(Element& element) { - auto& realm = element.document().preferred_window_object().realm(); - return realm.heap().allocate<NamedNodeMap>(realm, element); + auto& realm = element.realm(); + return *realm.heap().allocate<NamedNodeMap>(realm, element); } NamedNodeMap::NamedNodeMap(Element& element) - : Bindings::LegacyPlatformObject(element.document().preferred_window_object().ensure_web_prototype<Bindings::NamedNodeMapPrototype>("NamedNodeMap")) + : Bindings::LegacyPlatformObject(element.document().window().ensure_web_prototype<Bindings::NamedNodeMapPrototype>("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<String> 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> attribute = m_attributes.at(attribute_index); + JS::NonnullGCPtr<Attribute> 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<Attribute&>(*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<Attribute&>(*node)); + return node; } } diff --git a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h index d03d340290..7cc33a63b6 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<NamedNodeMap> create(Element&); ~NamedNodeMap() = default; - NamedNodeMap& impl() { return *this; } - virtual bool is_supported_property_index(u32 index) const override; virtual Vector<String> 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<Attribute> m_attributes; + JS::NonnullGCPtr<DOM::Element> m_element; + Vector<JS::NonnullGCPtr<Attribute>> 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 b3825ccee8..fc08dac50d 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -11,8 +11,7 @@ #include <LibJS/AST.h> #include <LibJS/Runtime/FunctionObject.h> #include <LibWeb/Bindings/MainThreadVM.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> +#include <LibWeb/Bindings/NodePrototype.h> #include <LibWeb/DOM/Comment.h> #include <LibWeb/DOM/DocumentType.h> #include <LibWeb/DOM/Element.h> @@ -23,7 +22,9 @@ #include <LibWeb/DOM/LiveNodeList.h> #include <LibWeb/DOM/MutationType.h> #include <LibWeb/DOM/Node.h> +#include <LibWeb/DOM/NodeIterator.h> #include <LibWeb/DOM/ProcessingInstruction.h> +#include <LibWeb/DOM/Range.h> #include <LibWeb/DOM/ShadowRoot.h> #include <LibWeb/DOM/StaticNodeList.h> #include <LibWeb/HTML/BrowsingContextContainer.h> @@ -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<void> Node::ensure_pre_insertion_validity(NonnullRefPtr<Node> node, RefPtr<Node> child) const +ExceptionOr<void> Node::ensure_pre_insertion_validity(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child) const { // 1. If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException. if (!is<Document>(this) && !is<DocumentFragment>(this) && !is<Element>(this)) @@ -342,14 +353,14 @@ ExceptionOr<void> Node::ensure_pre_insertion_validity(NonnullRefPtr<Node> node, } // https://dom.spec.whatwg.org/#concept-node-insert -void Node::insert_before(NonnullRefPtr<Node> node, RefPtr<Node> child, bool suppress_observers) +void Node::insert_before(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child, bool suppress_observers) { // 1. Let nodes be node’s children, if node is a DocumentFragment node; otherwise « node ». - NonnullRefPtrVector<Node> nodes; + Vector<JS::Handle<Node>> nodes; if (is<DocumentFragment>(*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> node, RefPtr<Node> child, bool supp } // 6. Let previousSibling be child’s previous sibling or parent’s last child if child is null. - RefPtr<Node> previous_sibling; + JS::GCPtr<Node> previous_sibling; if (child) previous_sibling = child->previous_sibling(); else @@ -394,14 +405,14 @@ void Node::insert_before(NonnullRefPtr<Node> node, RefPtr<Node> 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<Node>::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<Node>::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> node, RefPtr<Node> 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> node, RefPtr<Node> 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> node, RefPtr<Node> child, bool supp } // https://dom.spec.whatwg.org/#concept-node-pre-insert -ExceptionOr<NonnullRefPtr<Node>> Node::pre_insert(NonnullRefPtr<Node> node, RefPtr<Node> child) +ExceptionOr<JS::NonnullGCPtr<Node>> Node::pre_insert(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child) { // 1. Ensure pre-insertion validity of node into parent before child. TRY(ensure_pre_insertion_validity(node, child)); @@ -456,14 +467,14 @@ ExceptionOr<NonnullRefPtr<Node>> Node::pre_insert(NonnullRefPtr<Node> node, RefP } // https://dom.spec.whatwg.org/#dom-node-removechild -ExceptionOr<NonnullRefPtr<Node>> Node::remove_child(NonnullRefPtr<Node> child) +ExceptionOr<JS::NonnullGCPtr<Node>> Node::remove_child(JS::NonnullGCPtr<Node> 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<NonnullRefPtr<Node>> Node::pre_remove(NonnullRefPtr<Node> child) +ExceptionOr<JS::NonnullGCPtr<Node>> Node::pre_remove(JS::NonnullGCPtr<Node> child) { // 1. If child’s parent is not parent, then throw a "NotFoundError" DOMException. if (child->parent() != this) @@ -477,7 +488,7 @@ ExceptionOr<NonnullRefPtr<Node>> Node::pre_remove(NonnullRefPtr<Node> child) } // https://dom.spec.whatwg.org/#concept-node-append -ExceptionOr<NonnullRefPtr<Node>> Node::append_child(NonnullRefPtr<Node> node) +ExceptionOr<JS::NonnullGCPtr<Node>> Node::append_child(JS::NonnullGCPtr<Node> 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<NonnullRefPtr<Node>> Node::append_child(NonnullRefPtr<Node> node) void Node::remove(bool suppress_observers) { // 1. Let parent be node’s parent - auto* parent = TreeNode<Node>::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<Node> old_previous_sibling = previous_sibling(); + JS::GCPtr<Node> old_previous_sibling = previous_sibling(); // 10. Let oldNextSibling be node’s next sibling. - RefPtr<Node> old_next_sibling = next_sibling(); + JS::GCPtr<Node> 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<Node> 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<JS::Handle<Node>> 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<NonnullRefPtr<Node>> Node::replace_child(NonnullRefPtr<Node> node, NonnullRefPtr<Node> child) +ExceptionOr<JS::NonnullGCPtr<Node>> Node::replace_child(JS::NonnullGCPtr<Node> node, JS::NonnullGCPtr<Node> child) { // If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException. if (!is<Document>(this) && !is<DocumentFragment>(this) && !is<Element>(this)) @@ -637,52 +648,52 @@ ExceptionOr<NonnullRefPtr<Node>> Node::replace_child(NonnullRefPtr<Node> node, N } // 7. Let referenceChild be child’s next sibling. - RefPtr<Node> reference_child = child->next_sibling(); + JS::GCPtr<Node> 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<Node> previous_sibling = child->previous_sibling(); + JS::GCPtr<Node> previous_sibling = child->previous_sibling(); // 10. Let removedNodes be the empty set. - NonnullRefPtrVector<Node> removed_nodes; + Vector<JS::Handle<Node>> 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<Node> nodes; + Vector<JS::Handle<Node>> nodes; if (is<DocumentFragment>(*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> Node::clone_node(Document* document, bool clone_children) +JS::NonnullGCPtr<Node> 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<Node> copy; + document = m_document.ptr(); + JS::GCPtr<Node> copy; // 2. If node is an element, then: if (is<Element>(this)) { @@ -703,7 +714,7 @@ NonnullRefPtr<Node> Node::clone_node(Document* document, bool clone_children) else if (is<Document>(this)) { // Document auto document_ = verify_cast<Document>(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> Node::clone_node(Document* document, bool clone_children) } else if (is<DocumentType>(this)) { // DocumentType auto document_type = verify_cast<DocumentType>(this); - auto document_type_copy = adopt_ref(*new DocumentType(*document)); + auto document_type_copy = heap().allocate<DocumentType>(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> Node::clone_node(Document* document, bool clone_children) auto text = verify_cast<Text>(this); // Set copy’s data to that of node. - auto text_copy = adopt_ref(*new Text(*document, text->data())); + auto text_copy = heap().allocate<Text>(realm(), *document, text->data()); copy = move(text_copy); } else if (is<Comment>(this)) { // Comment auto comment = verify_cast<Comment>(this); // Set copy’s data to that of node. - auto comment_copy = adopt_ref(*new Comment(*document, comment->data())); + auto comment_copy = heap().allocate<Comment>(realm(), *document, comment->data()); copy = move(comment_copy); } else if (is<ProcessingInstruction>(this)) { // ProcessingInstruction auto processing_instruction = verify_cast<ProcessingInstruction>(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<ProcessingInstruction>(realm(), *document, processing_instruction->data(), processing_instruction->target()); + copy = processing_instruction_copy; } // Otherwise, Do nothing. else if (is<DocumentFragment>(this)) { - copy = adopt_ref(*new DocumentFragment(*document)); + copy = heap().allocate<DocumentFragment>(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> 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<NonnullRefPtr<Node>> Node::clone_node_binding(bool deep) +ExceptionOr<JS::NonnullGCPtr<Node>> Node::clone_node_binding(bool deep) { // 1. If this is a shadow root, then throw a "NotSupportedError" DOMException. if (is<ShadowRoot>(*this)) @@ -784,11 +795,9 @@ ExceptionOr<NonnullRefPtr<Node>> Node::clone_node_binding(bool deep) void Node::set_document(Badge<Document>, 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<Document>(*this)) { - verify_cast<Document>(*this).removed_last_ref(); - return; - } - m_deletion_has_begun = true; - delete this; -} - void Node::set_layout_node(Badge<Layout::Node>, Layout::Node* layout_node) const { m_layout_node = layout_node; @@ -866,12 +860,12 @@ NonnullRefPtr<NodeList> Node::child_nodes() }); } -NonnullRefPtrVector<Node> Node::children_as_vector() const +Vector<JS::Handle<Node>> Node::children_as_vector() const { - NonnullRefPtrVector<Node> nodes; + Vector<JS::Handle<Node>> nodes; for_each_child([&](auto& child) { - nodes.append(child); + nodes.append(JS::make_handle(child)); }); return nodes; @@ -879,12 +873,12 @@ NonnullRefPtrVector<Node> Node::children_as_vector() const void Node::remove_all_children(bool suppress_observers) { - while (RefPtr<Node> child = first_child()) + while (JS::GCPtr<Node> child = first_child()) child->remove(suppress_observers); } // https://dom.spec.whatwg.org/#dom-node-comparedocumentposition -u16 Node::compare_document_position(RefPtr<Node> other) +u16 Node::compare_document_position(JS::GCPtr<Node> other) { enum Position : u16 { DOCUMENT_POSITION_EQUAL = 0, @@ -897,7 +891,7 @@ u16 Node::compare_document_position(RefPtr<Node> 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<Document> Node::owner_document() const +JS::GCPtr<Document> 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<Node> other) const +bool Node::contains(JS::GCPtr<Node> 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> node) +void Node::replace_all(JS::GCPtr<Node> node) { // 1. Let removedNodes be parent’s children. auto removed_nodes = children_as_vector(); // 2. Let addedNodes be the empty set. - NonnullRefPtrVector<Node> added_nodes; + Vector<JS::Handle<Node>> added_nodes; // 3. If node is a DocumentFragment node, then set addedNodes to node’s children. if (node && is<DocumentFragment>(*node)) { @@ -1127,7 +1121,7 @@ void Node::replace_all(RefPtr<Node> 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> node) void Node::string_replace_all(String const& string) { // 1. Let node be null. - RefPtr<Node> node; + JS::GCPtr<Node> 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<Text>(document(), string); + node = heap().allocate<Text>(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> Node::get_root_node(GetRootNodeOptions const& options) +JS::NonnullGCPtr<Node> 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<NonnullRefPtr<MutationObserver>, String> interested_observers; // 2. Let nodes be the inclusive ancestors of target. - NonnullRefPtrVector<Node> nodes; - nodes.append(*this); + Vector<JS::Handle<Node>> 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<NodeList> 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> 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> node, JS::GCPtr<Node> 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> 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 d0e7354d69..f4d4b90120 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.h +++ b/Userland/Libraries/LibWeb/DOM/Node.h @@ -16,7 +16,6 @@ #include <LibWeb/DOM/EventTarget.h> #include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/DOM/MutationObserver.h> -#include <LibWeb/TreeNode.h> namespace Web::DOM { @@ -40,26 +39,16 @@ struct GetRootNodeOptions { bool composed { false }; }; -class Node - : public TreeNode<Node> - , public EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::NodeWrapper; - - using TreeNode<Node>::ref; - using TreeNode<Node>::unref; +class Node : public EventTarget { + WEB_PLATFORM_OBJECT(Node, EventTarget); +public: ParentNode* parent_or_shadow_host(); ParentNode const* parent_or_shadow_host() const { return const_cast<Node*>(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<NonnullRefPtr<Node>> pre_insert(NonnullRefPtr<Node>, RefPtr<Node>); - ExceptionOr<NonnullRefPtr<Node>> pre_remove(NonnullRefPtr<Node>); + ExceptionOr<JS::NonnullGCPtr<Node>> pre_insert(JS::NonnullGCPtr<Node>, JS::GCPtr<Node>); + ExceptionOr<JS::NonnullGCPtr<Node>> pre_remove(JS::NonnullGCPtr<Node>); - ExceptionOr<NonnullRefPtr<Node>> append_child(NonnullRefPtr<Node>); - ExceptionOr<NonnullRefPtr<Node>> remove_child(NonnullRefPtr<Node>); + ExceptionOr<JS::NonnullGCPtr<Node>> append_child(JS::NonnullGCPtr<Node>); + ExceptionOr<JS::NonnullGCPtr<Node>> remove_child(JS::NonnullGCPtr<Node>); - void insert_before(NonnullRefPtr<Node> node, RefPtr<Node> child, bool suppress_observers = false); + void insert_before(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child, bool suppress_observers = false); void remove(bool suppress_observers = false); void remove_all_children(bool suppress_observers = false); - u16 compare_document_position(RefPtr<Node> other); + u16 compare_document_position(JS::GCPtr<Node> other); - ExceptionOr<NonnullRefPtr<Node>> replace_child(NonnullRefPtr<Node> node, NonnullRefPtr<Node> child); + ExceptionOr<JS::NonnullGCPtr<Node>> replace_child(JS::NonnullGCPtr<Node> node, JS::NonnullGCPtr<Node> child); - NonnullRefPtr<Node> clone_node(Document* document = nullptr, bool clone_children = false); - ExceptionOr<NonnullRefPtr<Node>> clone_node_binding(bool deep); + JS::NonnullGCPtr<Node> clone_node(Document* document = nullptr, bool clone_children = false); + ExceptionOr<JS::NonnullGCPtr<Node>> clone_node_binding(bool deep); // NOTE: This is intended for the JS bindings. bool has_child_nodes() const { return has_children(); } NonnullRefPtr<NodeList> child_nodes(); - NonnullRefPtrVector<Node> children_as_vector() const; + Vector<JS::Handle<Node>> 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<Document> owner_document() const; + JS::GCPtr<Document> owner_document() const; const HTML::HTMLAnchorElement* enclosing_link_element() const; const HTML::HTMLElement* enclosing_html_element() const; @@ -190,14 +179,14 @@ public: template<typename T> bool fast_is() const = delete; - ExceptionOr<void> ensure_pre_insertion_validity(NonnullRefPtr<Node> node, RefPtr<Node> child) const; + ExceptionOr<void> ensure_pre_insertion_validity(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> 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<Node>) const; + bool contains(JS::GCPtr<Node>) const; // Used for dumping the DOM Tree void serialize_tree_as_json(JsonObjectSerializer<StringBuilder>&) const; @@ -212,13 +201,13 @@ public: String serialize_fragment() const; - void replace_all(RefPtr<Node>); + void replace_all(JS::GCPtr<Node>); void string_replace_all(String const&); bool is_same_node(Node const*) const; bool is_equal_node(Node const*) const; - NonnullRefPtr<Node> get_root_node(GetRootNodeOptions const& options = {}); + JS::NonnullGCPtr<Node> get_root_node(GetRootNodeOptions const& options = {}); bool is_uninteresting_whitespace_node() const; @@ -237,10 +226,407 @@ public: template<typename Callback> 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<Node*>(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<size_t> 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<typename ChildType> + Optional<size_t> 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<ChildType>(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); + + 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<Node*>(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<Node*>(this)->next_in_pre_order(); + } + + Node const* next_in_pre_order(Node const* stay_within) const + { + return const_cast<Node*>(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<Node*>(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<typename U> + 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<U>(node)) + return true; + } + return false; + } + + // https://dom.spec.whatwg.org/#concept-tree-following (Object A is 'typename U' and Object B is 'this') + template<typename U> + 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<U>(node)) + return true; + } + return false; + } + + template<typename Callback> + IterationDecision for_each_in_inclusive_subtree(Callback callback) const + { + if (callback(static_cast<Node const&>(*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<typename Callback> + IterationDecision for_each_in_inclusive_subtree(Callback callback) + { + if (callback(static_cast<Node&>(*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<typename U, typename Callback> + IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) + { + if (is<U>(static_cast<Node const&>(*this))) { + if (callback(static_cast<U&>(*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<U>(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template<typename U, typename Callback> + IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) const + { + if (is<U>(static_cast<Node const&>(*this))) { + if (callback(static_cast<U const&>(*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<U>(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template<typename Callback> + 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<typename Callback> + 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<typename U, typename Callback> + 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<U>(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template<typename U, typename Callback> + 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<U>(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template<typename Callback> + void for_each_child(Callback callback) const + { + return const_cast<Node*>(this)->template for_each_child(move(callback)); + } + + template<typename Callback> + void for_each_child(Callback callback) + { + for (auto* node = first_child(); node; node = node->next_sibling()) + callback(*node); + } + + template<typename U, typename Callback> + void for_each_child_of_type(Callback callback) + { + for (auto* node = first_child(); node; node = node->next_sibling()) { + if (is<U>(node)) + callback(verify_cast<U>(*node)); + } + } + + template<typename U, typename Callback> + void for_each_child_of_type(Callback callback) const + { + return const_cast<Node*>(this)->template for_each_child_of_type<U>(move(callback)); + } + + template<typename U> + U const* next_sibling_of_type() const + { + return const_cast<Node*>(this)->template next_sibling_of_type<U>(); + } + + template<typename U> + inline U* next_sibling_of_type() + { + for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) { + if (is<U>(*sibling)) + return &verify_cast<U>(*sibling); + } + return nullptr; + } + + template<typename U> + U const* previous_sibling_of_type() const + { + return const_cast<Node*>(this)->template previous_sibling_of_type<U>(); + } + + template<typename U> + U* previous_sibling_of_type() + { + for (auto* sibling = previous_sibling(); sibling; sibling = sibling->previous_sibling()) { + if (is<U>(*sibling)) + return &verify_cast<U>(*sibling); + } + return nullptr; + } + + template<typename U> + U const* first_child_of_type() const + { + return const_cast<Node*>(this)->template first_child_of_type<U>(); + } + + template<typename U> + U const* last_child_of_type() const + { + return const_cast<Node*>(this)->template last_child_of_type<U>(); + } + + template<typename U> + U* first_child_of_type() + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (is<U>(*child)) + return &verify_cast<U>(*child); + } + return nullptr; + } + + template<typename U> + U* last_child_of_type() + { + for (auto* child = last_child(); child; child = child->previous_sibling()) { + if (is<U>(*child)) + return &verify_cast<U>(*child); + } + return nullptr; + } + + template<typename U> + bool has_child_of_type() const + { + return first_child_of_type<U>() != nullptr; + } + + template<typename U> + U const* first_ancestor_of_type() const + { + return const_cast<Node*>(this)->template first_ancestor_of_type<U>(); + } + + template<typename U> + U* first_ancestor_of_type() + { + for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + if (is<U>(*ancestor)) + return &verify_cast<U>(*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<Document> m_document; mutable WeakPtr<Layout::Node> 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<NodeList> added_nodes, NonnullRefPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling); + + void insert_before_impl(JS::NonnullGCPtr<Node>, JS::GCPtr<Node> child); + void append_child_impl(JS::NonnullGCPtr<Node>); + void remove_child_impl(JS::NonnullGCPtr<Node>); + + JS::GCPtr<Node> m_parent; + JS::GCPtr<Node> m_first_child; + JS::GCPtr<Node> m_last_child; + JS::GCPtr<Node> m_next_sibling; + JS::GCPtr<Node> 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 d1dbec9136..5f02bb1cb5 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 <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/NodeFilter.h> +#include <LibWeb/HTML/Window.h> namespace Web::DOM { diff --git a/Userland/Libraries/LibWeb/DOM/NodeFilter.h b/Userland/Libraries/LibWeb/DOM/NodeFilter.h index 89b7aa1354..5ecf028650 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<NodeFilter> 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 a0421dc179..f57e7777db 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp @@ -7,15 +7,14 @@ #include <LibWeb/Bindings/DOMExceptionWrapper.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> #include <LibWeb/Bindings/NodeIteratorPrototype.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> +#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Node.h> #include <LibWeb/DOM/NodeIterator.h> namespace Web::DOM { NodeIterator::NodeIterator(Node& root) - : PlatformObject(root.document().preferred_window_object().ensure_web_prototype<Bindings::NodeIteratorPrototype>("NodeIterator")) + : PlatformObject(root.document().window().ensure_web_prototype<Bindings::NodeIteratorPrototype>("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> 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<NodeIterator>(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<RefPtr<Node>> NodeIterator::traverse(Direction direction) +JS::ThrowCompletionOr<JS::GCPtr<Node>> 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<Node> candidate; + JS::GCPtr<Node> candidate; // 3. While true: while (true) { @@ -79,7 +83,7 @@ JS::ThrowCompletionOr<RefPtr<Node>> 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<RefPtr<Node>> 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<NodeFilter::Result> NodeIterator::filter(Node& node) } // https://dom.spec.whatwg.org/#dom-nodeiterator-nextnode -JS::ThrowCompletionOr<RefPtr<Node>> NodeIterator::next_node() +JS::ThrowCompletionOr<JS::GCPtr<Node>> NodeIterator::next_node() { return traverse(Direction::Next); } // https://dom.spec.whatwg.org/#dom-nodeiterator-previousnode -JS::ThrowCompletionOr<RefPtr<Node>> NodeIterator::previous_node() +JS::ThrowCompletionOr<JS::GCPtr<Node>> 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 a629630694..e3ce0c308e 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<NodeIterator> create(Node& root, unsigned what_to_show, JS::GCPtr<NodeFilter>); - NodeIterator(Node& root); virtual ~NodeIterator() override; - NodeIterator& impl() { return *this; } - - NonnullRefPtr<Node> root() { return m_root; } - NonnullRefPtr<Node> reference_node() { return m_reference.node; } + JS::NonnullGCPtr<Node> root() { return m_root; } + JS::NonnullGCPtr<Node> 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<RefPtr<Node>> next_node(); - JS::ThrowCompletionOr<RefPtr<Node>> previous_node(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> next_node(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> 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<RefPtr<Node>> traverse(Direction); + JS::ThrowCompletionOr<JS::GCPtr<Node>> traverse(Direction); JS::ThrowCompletionOr<NodeFilter::Result> filter(Node&); // https://dom.spec.whatwg.org/#concept-traversal-root - NonnullRefPtr<DOM::Node> m_root; + JS::NonnullGCPtr<Node> m_root; struct NodePointer { - NonnullRefPtr<DOM::Node> node; + JS::NonnullGCPtr<Node> 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<DOM::NodeFilter> m_filter; + JS::GCPtr<NodeFilter> 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 d377991ad1..0f36843943 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeOperations.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeOperations.cpp @@ -6,6 +6,7 @@ #include <AK/String.h> #include <AK/Vector.h> +#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/DocumentFragment.h> #include <LibWeb/DOM/NodeOperations.h> #include <LibWeb/DOM/Text.h> @@ -13,7 +14,7 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#converting-nodes-into-a-node -ExceptionOr<NonnullRefPtr<Node>> convert_nodes_to_single_node(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes, DOM::Document& document) +ExceptionOr<JS::NonnullGCPtr<Node>> convert_nodes_to_single_node(Vector<Variant<JS::Handle<Node>, 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<NonnullRefPtr<Node>> convert_nodes_to_single_node(Vector<Variant<Non // 4. Otherwise, set node to a new DocumentFragment node whose node document is document, and then append each node in nodes, if any, to it. // 5. Return node. - auto potentially_convert_string_to_text_node = [&document](Variant<NonnullRefPtr<Node>, String> const& node) -> NonnullRefPtr<Node> { - if (node.has<NonnullRefPtr<Node>>()) - return node.get<NonnullRefPtr<Node>>(); + auto potentially_convert_string_to_text_node = [&document](Variant<JS::Handle<Node>, String> const& node) -> JS::NonnullGCPtr<Node> { + if (node.has<JS::Handle<Node>>()) + return *node.get<JS::Handle<Node>>(); - return adopt_ref(*new Text(document, node.get<String>())); + return *document.heap().allocate<DOM::Text>(document.realm(), document, node.get<String>()); }; if (nodes.size() == 1) return potentially_convert_string_to_text_node(nodes.first()); - // This is NNRP<Node> instead of NNRP<DocumentFragment> to be compatible with the return type. - NonnullRefPtr<Node> document_fragment = adopt_ref(*new DocumentFragment(document)); + // This is NNGCP<Node> instead of NNGCP<DocumentFragment> to be compatible with the return type. + JS::NonnullGCPtr<Node> document_fragment = *document.heap().allocate<DOM::DocumentFragment>(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 251a320104..fe9817e58e 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeOperations.h +++ b/Userland/Libraries/LibWeb/DOM/NodeOperations.h @@ -6,11 +6,12 @@ #pragma once -#include <AK/NonnullRefPtr.h> +#include <LibJS/Heap/GCPtr.h> +#include <LibJS/Heap/Handle.h> #include <LibWeb/Forward.h> namespace Web::DOM { -ExceptionOr<NonnullRefPtr<Node>> convert_nodes_to_single_node(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes, DOM::Document& document); +ExceptionOr<JS::NonnullGCPtr<Node>> convert_nodes_to_single_node(Vector<Variant<JS::Handle<Node>, String>> const& nodes, DOM::Document& document); } diff --git a/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h b/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h index 59c1ef65cb..20dccb37c3 100644 --- a/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h +++ b/Userland/Libraries/LibWeb/DOM/NonElementParentNode.h @@ -16,9 +16,9 @@ namespace Web::DOM { template<typename NodeType> class NonElementParentNode { public: - RefPtr<Element> get_element_by_id(FlyString const& id) const + JS::GCPtr<Element> get_element_by_id(FlyString const& id) const { - RefPtr<Element> found_element; + JS::GCPtr<Element> found_element; static_cast<NodeType const*>(this)->template for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) { if (element.attribute(HTML::AttributeNames::id) == id) { found_element = &element; @@ -28,7 +28,7 @@ public: }); return found_element; } - RefPtr<Element> get_element_by_id(FlyString const& id) + JS::GCPtr<Element> get_element_by_id(FlyString const& id) { return const_cast<NonElementParentNode const*>(this)->get_element_by_id(id); } diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp index 16f65efa41..de7fdd699a 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp @@ -15,7 +15,7 @@ namespace Web::DOM { -ExceptionOr<RefPtr<Element>> ParentNode::query_selector(StringView selector_text) +ExceptionOr<JS::GCPtr<Element>> 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<RefPtr<Element>> ParentNode::query_selector(StringView selector_text auto selectors = maybe_selectors.value(); - RefPtr<Element> result; + JS::GCPtr<Element> 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<Element>([&](auto& element) { for (auto& selector : selectors) { if (SelectorEngine::matches(selector, element)) { - result = element; + result = &element; return IterationDecision::Break; } } @@ -46,12 +46,12 @@ ExceptionOr<NonnullRefPtr<NodeList>> ParentNode::query_selector_all(StringView s auto selectors = maybe_selectors.value(); - NonnullRefPtrVector<Node> elements; + Vector<JS::Handle<Node>> 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<Element>([&](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<NonnullRefPtr<NodeList>> ParentNode::query_selector_all(StringView s return StaticNodeList::create(move(elements)); } -RefPtr<Element> ParentNode::first_element_child() +JS::GCPtr<Element> ParentNode::first_element_child() { return first_child_of_type<Element>(); } -RefPtr<Element> ParentNode::last_element_child() +JS::GCPtr<Element> ParentNode::last_element_child() { return last_child_of_type<Element>(); } @@ -157,7 +157,7 @@ NonnullRefPtr<HTMLCollection> ParentNode::get_elements_by_tag_name_ns(FlyString } // https://dom.spec.whatwg.org/#dom-parentnode-prepend -ExceptionOr<void> ParentNode::prepend(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) +ExceptionOr<void> ParentNode::prepend(Vector<Variant<JS::Handle<Node>, 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<void> ParentNode::prepend(Vector<Variant<NonnullRefPtr<Node>, String return {}; } -ExceptionOr<void> ParentNode::append(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) +ExceptionOr<void> ParentNode::append(Vector<Variant<JS::Handle<Node>, 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<void> ParentNode::append(Vector<Variant<NonnullRefPtr<Node>, String> return {}; } -ExceptionOr<void> ParentNode::replace_children(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes) +ExceptionOr<void> ParentNode::replace_children(Vector<Variant<JS::Handle<Node>, 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<void> ParentNode::replace_children(Vector<Variant<NonnullRefPtr<Node TRY(ensure_pre_insertion_validity(node, nullptr)); // 3. Replace all with node within this. - replace_all(node); + replace_all(*node); return {}; } diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.h b/Userland/Libraries/LibWeb/DOM/ParentNode.h index 402c4617b3..384db0cb6f 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.h +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.h @@ -6,23 +6,24 @@ #pragma once -#include <AK/NonnullRefPtrVector.h> #include <LibWeb/DOM/Node.h> namespace Web::DOM { class ParentNode : public Node { + WEB_PLATFORM_OBJECT(ParentNode, Node); + public: template<typename F> void for_each_child(F) const; template<typename F> void for_each_child(F); - RefPtr<Element> first_element_child(); - RefPtr<Element> last_element_child(); + JS::GCPtr<Element> first_element_child(); + JS::GCPtr<Element> last_element_child(); u32 child_element_count() const; - ExceptionOr<RefPtr<Element>> query_selector(StringView); + ExceptionOr<JS::GCPtr<Element>> query_selector(StringView); ExceptionOr<NonnullRefPtr<NodeList>> query_selector_all(StringView); NonnullRefPtr<HTMLCollection> children(); @@ -30,11 +31,16 @@ public: NonnullRefPtr<HTMLCollection> get_elements_by_tag_name(FlyString const&); NonnullRefPtr<HTMLCollection> get_elements_by_tag_name_ns(FlyString const&, FlyString const&); - ExceptionOr<void> prepend(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes); - ExceptionOr<void> append(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes); - ExceptionOr<void> replace_children(Vector<Variant<NonnullRefPtr<Node>, String>> const& nodes); + ExceptionOr<void> prepend(Vector<Variant<JS::Handle<Node>, String>> const& nodes); + ExceptionOr<void> append(Vector<Variant<JS::Handle<Node>, String>> const& nodes); + ExceptionOr<void> replace_children(Vector<Variant<JS::Handle<Node>, 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 7790e8e1e2..8f256c5b18 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 45ef6768a7..fd9847b8c4 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<Node> m_node; + JS::Handle<Node> m_node; unsigned m_offset { 0 }; }; diff --git a/Userland/Libraries/LibWeb/DOM/ProcessingInstruction.h b/Userland/Libraries/LibWeb/DOM/ProcessingInstruction.h index 5bc6706daf..a2196f9e31 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<ProcessingInstruction>() 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 eb8d1bceb8..d362577c36 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.cpp +++ b/Userland/Libraries/LibWeb/DOM/Range.cpp @@ -32,17 +32,17 @@ JS::NonnullGCPtr<Range> Range::create(HTML::Window& window) JS::NonnullGCPtr<Range> Range::create(Document& document) { - auto& window_object = document.preferred_window_object(); + auto& window_object = document.window(); return *window_object.heap().allocate<Range>(window_object.realm(), document); } JS::NonnullGCPtr<Range> 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<Range>(window_object.realm(), start_container, start_offset, end_container, end_offset); } -JS::NonnullGCPtr<Range> Range::create_with_global_object(Bindings::WindowObject& window) +JS::NonnullGCPtr<Range> Range::create_with_global_object(HTML::Window& window) { return Range::create(window.impl()); } @@ -50,13 +50,13 @@ JS::NonnullGCPtr<Range> 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<Bindings::RangePrototype>("Range")); + set_prototype(&document.window().ensure_web_prototype<Bindings::RangePrototype>("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<Bindings::RangePrototype>("Range")); + set_prototype(&start_container.document().window().ensure_web_prototype<Bindings::RangePrototype>("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<Node> child = node_b; + JS::NonnullGCPtr<Node> 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<void> 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<void> 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<void> 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<i16> 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<Node> this_point_node; + JS::GCPtr<Node> this_point_node; u32 this_point_offset = 0; - RefPtr<Node> other_point_node; + JS::GCPtr<Node> other_point_node; u32 other_point_offset = 0; // 3. If how is: @@ -353,11 +346,11 @@ ExceptionOr<void> 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<void> 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> Range::normalized() const } // https://dom.spec.whatwg.org/#dom-range-commonancestorcontainer -NonnullRefPtr<Node> Range::common_ancestor_container() const +JS::NonnullGCPtr<Node> Range::common_ancestor_container() const { // 1. Let container be start node. auto container = m_start_container; @@ -439,7 +432,7 @@ NonnullRefPtr<Node> 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<NonnullRefPtr<DocumentFragment>> Range::extract_contents() +ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> Range::extract_contents() { return extract(); } // https://dom.spec.whatwg.org/#concept-range-extract -ExceptionOr<NonnullRefPtr<DocumentFragment>> Range::extract() +ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> 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<Document&>(start_container()->document()))); + auto* fragment = heap().allocate<DOM::DocumentFragment>(realm(), const_cast<Document&>(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<Node> original_start_node = m_start_container; + JS::NonnullGCPtr<Node> original_start_node = m_start_container; auto original_start_offset = m_start_offset; - NonnullRefPtr<Node> original_end_node = m_end_container; + JS::NonnullGCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> Range::extract() static_cast<CharacterData&>(*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<Node> common_ancestor = original_start_node; + JS::NonnullGCPtr<Node> 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<Node> first_partially_contained_child; + JS::GCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> Range::extract() } // 9. Let last partially contained child be null. - RefPtr<Node> last_partially_contained_child; + JS::GCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> Range::extract() } // 11. Let contained children be a list of all children of common ancestor that are contained in range, in tree order. - Vector<NonnullRefPtr<Node>> contained_children; + Vector<JS::NonnullGCPtr<Node>> 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<NonnullRefPtr<DocumentFragment>> Range::extract() return DOM::HierarchyRequestError::create("Contained child is a DocumentType"); } - RefPtr<Node> new_node; + JS::GCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> Range::extract() // 14. Otherwise: else { // 1. Let reference node equal original start node. - RefPtr<Node> reference_node = original_start_node; + JS::GCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> 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<void> Range::insert_node(NonnullRefPtr<Node> node) +ExceptionOr<void> Range::insert_node(JS::NonnullGCPtr<Node> node) { return insert(node); } // https://dom.spec.whatwg.org/#concept-range-insert -ExceptionOr<void> Range::insert(NonnullRefPtr<Node> node) +ExceptionOr<void> Range::insert(JS::NonnullGCPtr<Node> 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<ProcessingInstruction>(*m_start_container) || is<Comment>(*m_start_container)) || (is<Text>(*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<Node> reference_node; + JS::GCPtr<Node> reference_node; // 3. If range’s start node is a Text node, set referenceNode to that Text node. if (is<Text>(*m_start_container)) { @@ -807,7 +800,7 @@ ExceptionOr<void> Range::insert(NonnullRefPtr<Node> node) } // 5. Let parent be range’s start node if referenceNode is null, and referenceNode’s parent otherwise. - RefPtr<Node> parent; + JS::GCPtr<Node> parent; if (!reference_node) parent = m_start_container; else @@ -852,7 +845,7 @@ ExceptionOr<void> Range::insert(NonnullRefPtr<Node> node) } // https://dom.spec.whatwg.org/#dom-range-surroundcontents -ExceptionOr<void> Range::surround_contents(NonnullRefPtr<Node> new_parent) +ExceptionOr<void> Range::surround_contents(JS::NonnullGCPtr<Node> 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<void> Range::surround_contents(NonnullRefPtr<Node> new_parent) } // https://dom.spec.whatwg.org/#dom-range-clonecontents -ExceptionOr<NonnullRefPtr<DocumentFragment>> Range::clone_contents() +ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> Range::clone_contents() { return clone_the_contents(); } // https://dom.spec.whatwg.org/#concept-range-clone -ExceptionOr<NonnullRefPtr<DocumentFragment>> Range::clone_the_contents() +ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> 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<Document&>(start_container()->document()))); + auto* fragment = heap().allocate<DOM::DocumentFragment>(realm(), const_cast<Document&>(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<Node> original_start_node = m_start_container; + JS::NonnullGCPtr<Node> original_start_node = m_start_container; auto original_start_offset = m_start_offset; - NonnullRefPtr<Node> original_end_node = m_end_container; + JS::NonnullGCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> 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<Node> common_ancestor = original_start_node; + JS::NonnullGCPtr<Node> 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<Node> first_partially_contained_child; + JS::GCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> Range::clone_the_contents() } // 9. Let last partially contained child be null. - RefPtr<Node> last_partially_contained_child; + JS::GCPtr<Node> 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<NonnullRefPtr<DocumentFragment>> 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<NonnullRefPtr<Node>> contained_children; + Vector<JS::NonnullGCPtr<Node>> 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<NonnullRefPtr<DocumentFragment>> 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<void> 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<Node> original_start_node = m_start_container; + JS::NonnullGCPtr<Node> original_start_node = m_start_container; auto original_start_offset = m_start_offset; - NonnullRefPtr<Node> original_end_node = m_end_container; + JS::NonnullGCPtr<Node> 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<void> 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<NonnullRefPtr<Node>> nodes_to_remove; + JS::MarkedVector<Node*> 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*>(node)); } - RefPtr<Node> new_node; + JS::GCPtr<Node> 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<void> 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 a63b0e4baf..50edff1233 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<Range> create(Document&); static JS::NonnullGCPtr<Range> create(HTML::Window&); static JS::NonnullGCPtr<Range> create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset); - static JS::NonnullGCPtr<Range> create_with_global_object(Bindings::WindowObject&); + static JS::NonnullGCPtr<Range> 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<Range> normalized() const; JS::NonnullGCPtr<Range> clone_range() const; - NonnullRefPtr<Node> common_ancestor_container() const; + JS::NonnullGCPtr<Node> common_ancestor_container() const; // https://dom.spec.whatwg.org/#dom-range-detach void detach() const @@ -67,11 +65,11 @@ public: ExceptionOr<i16> compare_point(Node const&, u32 offset) const; ExceptionOr<void> delete_contents(); - ExceptionOr<NonnullRefPtr<DocumentFragment>> extract_contents(); - ExceptionOr<NonnullRefPtr<DocumentFragment>> clone_contents(); + ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> extract_contents(); + ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> clone_contents(); - ExceptionOr<void> insert_node(NonnullRefPtr<Node>); - ExceptionOr<void> surround_contents(NonnullRefPtr<Node> new_parent); + ExceptionOr<void> insert_node(JS::NonnullGCPtr<Node>); + ExceptionOr<void> surround_contents(JS::NonnullGCPtr<Node> new_parent); String to_string() const; @@ -89,9 +87,9 @@ private: ExceptionOr<void> set_start_or_end(Node& node, u32 offset, StartOrEnd start_or_end); ExceptionOr<void> select(Node& node); - ExceptionOr<NonnullRefPtr<DocumentFragment>> extract(); - ExceptionOr<NonnullRefPtr<DocumentFragment>> clone_the_contents(); - ExceptionOr<void> insert(NonnullRefPtr<Node>); + ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> extract(); + ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> clone_the_contents(); + ExceptionOr<void> insert(JS::NonnullGCPtr<Node>); 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 ea561e7b4c..b01e156277 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<void> 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<ShadowRoot> shadow_root = static_cast<Element*>(child)->shadow_root()) { + if (JS::GCPtr<ShadowRoot> shadow_root = static_cast<Element*>(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 ec3707cdae..fdcdfca9a6 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<Node>&& static_nodes) +NonnullRefPtr<NodeList> StaticNodeList::create(Vector<JS::Handle<Node>> static_nodes) +{ + return adopt_ref(*new StaticNodeList(move(static_nodes))); +} + +StaticNodeList::StaticNodeList(Vector<JS::Handle<Node>> 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 0ea249f685..829aca3cce 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<NodeList> create(NonnullRefPtrVector<Node> static_nodes) - { - return adopt_ref(*new StaticNodeList(move(static_nodes))); - } + static NonnullRefPtr<NodeList> create(Vector<JS::Handle<Node>> static_nodes); virtual ~StaticNodeList() override = default; @@ -27,9 +24,9 @@ public: virtual bool is_supported_property_index(u32) const override; private: - StaticNodeList(NonnullRefPtrVector<Node>&& static_nodes); + StaticNodeList(Vector<JS::Handle<Node>> static_nodes); - NonnullRefPtrVector<Node> m_static_nodes; + Vector<JS::Handle<Node>> m_static_nodes; }; } diff --git a/Userland/Libraries/LibWeb/DOM/StaticRange.cpp b/Userland/Libraries/LibWeb/DOM/StaticRange.cpp index 6027b4195e..8d825110ee 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<Bindings::StaticRangePrototype>("StaticRange")); + set_prototype(&start_container.document().window().ensure_web_prototype<Bindings::StaticRangePrototype>("StaticRange")); } StaticRange::~StaticRange() = default; // https://dom.spec.whatwg.org/#dom-staticrange-staticrange -ExceptionOr<StaticRange*> StaticRange::create_with_global_object(Bindings::WindowObject& window_object, StaticRangeInit& init) +ExceptionOr<StaticRange*> 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<DocumentType>(*init.start_container) || is<Attribute>(*init.start_container)) diff --git a/Userland/Libraries/LibWeb/DOM/StaticRange.h b/Userland/Libraries/LibWeb/DOM/StaticRange.h index 7f44aefb27..c6c27b0aa6 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<Node> start_container; + JS::GCPtr<Node> start_container; u32 start_offset { 0 }; - RefPtr<Node> end_container; + JS::GCPtr<Node> 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<StaticRange*> create_with_global_object(Bindings::WindowObject&, StaticRangeInit& init); + static ExceptionOr<StaticRange*> 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 3225e9d6b0..0b8262cd26 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 <LibWeb/Bindings/TextPrototype.h> #include <LibWeb/DOM/Range.h> #include <LibWeb/DOM/Text.h> #include <LibWeb/HTML/HTMLInputElement.h> @@ -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<Bindings::TextPrototype>("Text")); } Text::Text(Document& document, NodeType type, String const& data) : CharacterData(document, type, data) { + set_prototype(&window().ensure_web_prototype<Bindings::TextPrototype>("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> Text::create_with_global_object(Bindings::WindowObject& window, String const& data) +JS::NonnullGCPtr<Text> Text::create_with_global_object(HTML::Window& window, String const& data) { - return make_ref_counted<Text>(window.impl().associated_document(), data); + return *window.heap().allocate<Text>(window.realm(), window.associated_document(), data); } void Text::set_owner_input_element(Badge<HTML::HTMLInputElement>, 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<NonnullRefPtr<Text>> Text::split_text(size_t offset) +ExceptionOr<JS::NonnullGCPtr<Text>> Text::split_text(size_t offset) { // 1. Let length be node’s length. auto length = this->length(); @@ -51,26 +60,26 @@ ExceptionOr<NonnullRefPtr<Text>> 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<Text>(realm(), document(), new_data)); // 6. Let parent be node’s parent. - RefPtr<Node> parent = this->parent(); + JS::GCPtr<Node> 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<NonnullRefPtr<Text>> 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 44762c8e55..aff7c91e3e 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<Text> create_with_global_object(Bindings::WindowObject& window, String const& data); + static JS::NonnullGCPtr<Text> 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&); - HTML::HTMLInputElement* owner_input_element() { return m_owner_input_element; } + HTML::HTMLInputElement* owner_input_element() { return m_owner_input_element.ptr(); } - ExceptionOr<NonnullRefPtr<Text>> split_text(size_t offset); + ExceptionOr<JS::NonnullGCPtr<Text>> 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<HTML::HTMLInputElement> m_owner_input_element; + JS::GCPtr<HTML::HTMLInputElement> m_owner_input_element; bool m_always_editable { false }; }; @@ -45,3 +47,5 @@ template<> inline bool Node::fast_is<Text>() 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 88f88af449..7021233b11 100644 --- a/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp +++ b/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp @@ -6,11 +6,10 @@ #include <LibWeb/Bindings/DOMExceptionWrapper.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> #include <LibWeb/Bindings/TreeWalkerPrototype.h> #include <LibWeb/Bindings/Wrapper.h> #include <LibWeb/DOM/DOMException.h> +#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Node.h> #include <LibWeb/DOM/NodeFilter.h> #include <LibWeb/DOM/TreeWalker.h> @@ -18,7 +17,7 @@ namespace Web::DOM { TreeWalker::TreeWalker(Node& root) - : PlatformObject(root.document().preferred_window_object().ensure_web_prototype<Bindings::TreeWalkerPrototype>("TreeWalker")) + : PlatformObject(root.document().window().ensure_web_prototype<Bindings::TreeWalkerPrototype>("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> 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<TreeWalker>(window_object.realm(), root); // 3. Set walker’s whatToShow to whatToShow. @@ -51,7 +52,7 @@ JS::NonnullGCPtr<TreeWalker> TreeWalker::create(Node& root, unsigned what_to_sho } // https://dom.spec.whatwg.org/#dom-treewalker-currentnode -NonnullRefPtr<Node> TreeWalker::current_node() const +JS::NonnullGCPtr<Node> TreeWalker::current_node() const { return *m_current; } @@ -59,14 +60,14 @@ NonnullRefPtr<Node> 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<RefPtr<Node>> TreeWalker::parent_node() +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::parent_node() { // 1. Let node be this’s current. - RefPtr<Node> node = m_current; + JS::GCPtr<Node> 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<RefPtr<Node>> 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<RefPtr<Node>> TreeWalker::parent_node() } // https://dom.spec.whatwg.org/#dom-treewalker-firstchild -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::first_child() +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::first_child() { return traverse_children(ChildTraversalType::First); } // https://dom.spec.whatwg.org/#dom-treewalker-lastchild -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::last_child() +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::last_child() { return traverse_children(ChildTraversalType::Last); } // https://dom.spec.whatwg.org/#dom-treewalker-previoussibling -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::previous_sibling() +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::previous_sibling() { return traverse_siblings(SiblingTraversalType::Previous); } // https://dom.spec.whatwg.org/#dom-treewalker-nextsibling -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::next_sibling() +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::next_sibling() { return traverse_siblings(SiblingTraversalType::Next); } // https://dom.spec.whatwg.org/#dom-treewalker-previousnode -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::previous_node() +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::previous_node() { // 1. Let node be this’s current. - RefPtr<Node> node = m_current; + JS::GCPtr<Node> node = m_current; // 2. While node is not this’s root: while (node != m_root) { // 1. Let sibling be node’s previous sibling. - RefPtr<Node> sibling = node->previous_sibling(); + JS::GCPtr<Node> sibling = node->previous_sibling(); // 2. While sibling is non-null: while (sibling) { @@ -141,7 +142,7 @@ JS::ThrowCompletionOr<RefPtr<Node>> 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<RefPtr<Node>> 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<RefPtr<Node>> TreeWalker::previous_node() } // https://dom.spec.whatwg.org/#dom-treewalker-nextnode -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::next_node() +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::next_node() { // 1. Let node be this’s current. - RefPtr<Node> node = m_current; + JS::GCPtr<Node> node = m_current; // 2. Let result be FILTER_ACCEPT. auto result = NodeFilter::FILTER_ACCEPT; @@ -187,16 +188,16 @@ JS::ThrowCompletionOr<RefPtr<Node>> 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<Node> sibling = nullptr; + JS::GCPtr<Node> sibling = nullptr; // 3. Let temporary be node. - RefPtr<Node> temporary = node; + JS::GCPtr<Node> temporary = node; // 4. While temporary is non-null: while (temporary) { @@ -222,7 +223,7 @@ JS::ThrowCompletionOr<RefPtr<Node>> 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<NodeFilter::Result> TreeWalker::filter(Node& node) } // https://dom.spec.whatwg.org/#concept-traverse-children -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::traverse_children(ChildTraversalType type) +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::traverse_children(ChildTraversalType type) { // 1. Let node be walker’s current. - RefPtr<Node> node = m_current; + JS::GCPtr<Node> 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<RefPtr<Node>> 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<Node> child = type == ChildTraversalType::First ? node->first_child() : node->last_child(); + JS::GCPtr<Node> 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<RefPtr<Node>> 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<Node> sibling = type == ChildTraversalType::First ? node->next_sibling() : node->previous_sibling(); + JS::GCPtr<Node> 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<Node> parent = node->parent(); + JS::GCPtr<Node> 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<RefPtr<Node>> TreeWalker::traverse_children(ChildTraversal } // https://dom.spec.whatwg.org/#concept-traverse-siblings -JS::ThrowCompletionOr<RefPtr<Node>> TreeWalker::traverse_siblings(SiblingTraversalType type) +JS::ThrowCompletionOr<JS::GCPtr<Node>> TreeWalker::traverse_siblings(SiblingTraversalType type) { // 1. Let node be walker’s current. - RefPtr<Node> node = m_current; + JS::GCPtr<Node> node = m_current; // 2. If node is root, then return null. if (node == m_root) @@ -337,7 +338,7 @@ JS::ThrowCompletionOr<RefPtr<Node>> 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<Node> sibling = type == SiblingTraversalType::Next ? node->next_sibling() : node->previous_sibling(); + JS::GCPtr<Node> sibling = type == SiblingTraversalType::Next ? node->next_sibling() : node->previous_sibling(); // 2. While sibling is non-null: while (sibling) { @@ -349,7 +350,7 @@ JS::ThrowCompletionOr<RefPtr<Node>> 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 076c6511aa..e43f7c21f2 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<TreeWalker> create(Node& root, unsigned what_to_show, JS::GCPtr<NodeFilter>); - explicit TreeWalker(Node& root); virtual ~TreeWalker() override; - TreeWalker& impl() { return *this; } - - NonnullRefPtr<Node> current_node() const; + JS::NonnullGCPtr<Node> current_node() const; void set_current_node(Node&); - JS::ThrowCompletionOr<RefPtr<Node>> parent_node(); - JS::ThrowCompletionOr<RefPtr<Node>> first_child(); - JS::ThrowCompletionOr<RefPtr<Node>> last_child(); - JS::ThrowCompletionOr<RefPtr<Node>> previous_sibling(); - JS::ThrowCompletionOr<RefPtr<Node>> next_sibling(); - JS::ThrowCompletionOr<RefPtr<Node>> previous_node(); - JS::ThrowCompletionOr<RefPtr<Node>> next_node(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> parent_node(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> first_child(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> last_child(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> previous_sibling(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> next_sibling(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> previous_node(); + JS::ThrowCompletionOr<JS::GCPtr<Node>> next_node(); - NonnullRefPtr<Node> root() { return m_root; } + JS::NonnullGCPtr<Node> 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<RefPtr<Node>> traverse_children(ChildTraversalType); + JS::ThrowCompletionOr<JS::GCPtr<Node>> traverse_children(ChildTraversalType); enum class SiblingTraversalType { Next, Previous, }; - JS::ThrowCompletionOr<RefPtr<Node>> traverse_siblings(SiblingTraversalType); + JS::ThrowCompletionOr<JS::GCPtr<Node>> traverse_siblings(SiblingTraversalType); JS::ThrowCompletionOr<NodeFilter::Result> filter(Node&); // https://dom.spec.whatwg.org/#concept-traversal-root - NonnullRefPtr<DOM::Node> m_root; + JS::NonnullGCPtr<Node> m_root; // https://dom.spec.whatwg.org/#treewalker-current - NonnullRefPtr<DOM::Node> m_current; + JS::NonnullGCPtr<Node> 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<DOM::NodeFilter> m_filter; + JS::GCPtr<NodeFilter> 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 d869dc717e..a92e187aa2 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<NonnullRefPtr<DOM::DocumentFragment>> parse_fragment(String const& markup, DOM::Element& context_element) +static DOM::ExceptionOr<JS::NonnullGCPtr<DOM::DocumentFragment>> 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<DOM::DocumentFragment>(context_element.document()); + auto fragment = realm.heap().allocate<DOM::DocumentFragment>(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<void> inner_html_setter(NonnullRefPtr<DOM::Node> context_object, String const& value) +DOM::ExceptionOr<void> inner_html_setter(JS::NonnullGCPtr<DOM::Node> 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<DOM::Element> context_element = is<DOM::ShadowRoot>(*context_object) ? *verify_cast<DOM::ShadowRoot>(*context_object).host() : verify_cast<DOM::Element>(*context_object); + JS::NonnullGCPtr<DOM::Element> context_element = is<DOM::ShadowRoot>(*context_object) ? *verify_cast<DOM::ShadowRoot>(*context_object).host() : verify_cast<DOM::Element>(*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 55175e9d47..9689d4edcc 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<void> inner_html_setter(NonnullRefPtr<DOM::Node> context_object, String const& value); +DOM::ExceptionOr<void> inner_html_setter(JS::NonnullGCPtr<DOM::Node> context_object, String const& value); } diff --git a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp index 71ae4e6ec9..ed1f194493 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<String> XMLSerializer::serialize_to_string(NonnullRefPtr<DOM::Node> root) +DOM::ExceptionOr<String> XMLSerializer::serialize_to_string(JS::NonnullGCPtr<DOM::Node> 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, HashMap<FlyString, Vec return candidates_list_iterator->value.contains_slow(prefix); } -DOM::ExceptionOr<String> serialize_node_to_xml_string_impl(NonnullRefPtr<DOM::Node> root, Optional<FlyString>& namespace_, HashMap<FlyString, Vector<String>>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed); +DOM::ExceptionOr<String> serialize_node_to_xml_string_impl(JS::NonnullGCPtr<DOM::Node> root, Optional<FlyString>& namespace_, HashMap<FlyString, Vector<String>>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed); // https://w3c.github.io/DOM-Parsing/#dfn-xml-serialization -DOM::ExceptionOr<String> serialize_node_to_xml_string(NonnullRefPtr<DOM::Node> root, RequireWellFormed require_well_formed) +DOM::ExceptionOr<String> serialize_node_to_xml_string(JS::NonnullGCPtr<DOM::Node> 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<String> serialize_document_type(DOM::DocumentType const& static DOM::ExceptionOr<String> serialize_processing_instruction(DOM::ProcessingInstruction const& processing_instruction, RequireWellFormed require_well_formed); // https://w3c.github.io/DOM-Parsing/#dfn-xml-serialization-algorithm -DOM::ExceptionOr<String> serialize_node_to_xml_string_impl(NonnullRefPtr<DOM::Node> root, Optional<FlyString>& namespace_, HashMap<FlyString, Vector<String>>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed) +DOM::ExceptionOr<String> serialize_node_to_xml_string_impl(JS::NonnullGCPtr<DOM::Node> root, Optional<FlyString>& namespace_, HashMap<FlyString, Vector<String>>& 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<String> serialize_node_to_xml_string_impl(NonnullRefPtr<DOM::No if (is<DOM::Element>(*root)) { // -> Element // Run the algorithm for XML serializing an Element node node. - return serialize_element(static_ptr_cast<DOM::Element>(root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); + return serialize_element(static_cast<DOM::Element&>(*root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); } if (is<DOM::Document>(*root)) { // -> Document // Run the algorithm for XML serializing a Document node node. - return serialize_document(static_ptr_cast<DOM::Document>(root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); + return serialize_document(static_cast<DOM::Document&>(*root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); } if (is<DOM::Comment>(*root)) { // -> Comment // Run the algorithm for XML serializing a Comment node node. - return serialize_comment(static_ptr_cast<DOM::Comment>(root), require_well_formed); + return serialize_comment(static_cast<DOM::Comment&>(*root), require_well_formed); } if (is<DOM::Text>(*root) || is<DOM::CDATASection>(*root)) { // -> Text // Run the algorithm for XML serializing a Text node node. - return serialize_text(static_ptr_cast<DOM::Text>(root), require_well_formed); + return serialize_text(static_cast<DOM::Text&>(*root), require_well_formed); } if (is<DOM::DocumentFragment>(*root)) { // -> DocumentFragment // Run the algorithm for XML serializing a DocumentFragment node node. - return serialize_document_fragment(static_ptr_cast<DOM::DocumentFragment>(root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); + return serialize_document_fragment(static_cast<DOM::DocumentFragment&>(*root), namespace_, namespace_prefix_map, prefix_index, require_well_formed); } if (is<DOM::DocumentType>(*root)) { // -> DocumentType // Run the algorithm for XML serializing a DocumentType node node. - return serialize_document_type(static_ptr_cast<DOM::DocumentType>(root), require_well_formed); + return serialize_document_type(static_cast<DOM::DocumentType&>(*root), require_well_formed); } if (is<DOM::ProcessingInstruction>(*root)) { // -> ProcessingInstruction // Run the algorithm for XML serializing a ProcessingInstruction node node. - return serialize_processing_instruction(static_ptr_cast<DOM::ProcessingInstruction>(root), require_well_formed); + return serialize_processing_instruction(static_cast<DOM::ProcessingInstruction&>(*root), require_well_formed); } if (is<DOM::Attribute>(*root)) { diff --git a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h index 1157ea4763..ca0d875e55 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<XMLSerializer> create_with_global_object(Bindings::WindowObject&) + static NonnullRefPtr<XMLSerializer> create_with_global_object(HTML::Window&) { return adopt_ref(*new XMLSerializer()); } virtual ~XMLSerializer() override; - DOM::ExceptionOr<String> serialize_to_string(NonnullRefPtr<DOM::Node> root); + DOM::ExceptionOr<String> serialize_to_string(JS::NonnullGCPtr<DOM::Node> root); private: XMLSerializer(); @@ -36,6 +36,6 @@ enum class RequireWellFormed { Yes, }; -DOM::ExceptionOr<String> serialize_node_to_xml_string(NonnullRefPtr<DOM::Node> root, RequireWellFormed require_well_formed); +DOM::ExceptionOr<String> serialize_node_to_xml_string(JS::NonnullGCPtr<DOM::Node> root, RequireWellFormed require_well_formed); } diff --git a/Userland/Libraries/LibWeb/Encoding/TextDecoder.h b/Userland/Libraries/LibWeb/Encoding/TextDecoder.h index 36e6840efd..729c30fae1 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<NonnullRefPtr<TextDecoder>> create_with_global_object(Bindings::WindowObject&, FlyString label) + static DOM::ExceptionOr<NonnullRefPtr<TextDecoder>> 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 dc39596147..aa3882d5cc 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<TextEncoder> create_with_global_object(Bindings::WindowObject&) + static NonnullRefPtr<TextEncoder> 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 828bb6758b..05da753472 100644 --- a/Userland/Libraries/LibWeb/Fetch/Headers.h +++ b/Userland/Libraries/LibWeb/Fetch/Headers.h @@ -36,7 +36,7 @@ public: static DOM::ExceptionOr<NonnullRefPtr<Headers>> create(Optional<HeadersInit> const&); - static DOM::ExceptionOr<NonnullRefPtr<Headers>> create_with_global_object(Bindings::WindowObject&, Optional<HeadersInit> const& init) + static DOM::ExceptionOr<NonnullRefPtr<Headers>> create_with_global_object(HTML::Window&, Optional<HeadersInit> const& init) { return create(init); } diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp index 573330e83b..69f912e00f 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<NonnullRefPtr<Blob>> Blob::create(Optional<Vector<BlobPart>> const& blob_parts, Optional<BlobPropertyBag> const& options) { @@ -149,7 +151,7 @@ DOM::ExceptionOr<NonnullRefPtr<Blob>> Blob::create(Optional<Vector<BlobPart>> co return adopt_ref(*new Blob(move(byte_buffer), move(type))); } -DOM::ExceptionOr<NonnullRefPtr<Blob>> Blob::create_with_global_object(Bindings::WindowObject&, Optional<Vector<BlobPart>> const& blob_parts, Optional<BlobPropertyBag> const& options) +DOM::ExceptionOr<NonnullRefPtr<Blob>> Blob::create_with_global_object(HTML::Window&, Optional<Vector<BlobPart>> const& blob_parts, Optional<BlobPropertyBag> 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 1604fd6a6e..0513db6eae 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.h +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.h @@ -10,8 +10,7 @@ #include <AK/RefCounted.h> #include <AK/String.h> #include <AK/Vector.h> -#include <LibWeb/Bindings/BlobWrapper.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/Bindings/BlobPrototype.h> #include <LibWeb/Bindings/Wrappable.h> #include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/Forward.h> @@ -39,8 +38,10 @@ public: using WrapperType = Bindings::BlobWrapper; Blob(ByteBuffer byte_buffer, String type); + virtual ~Blob() override; + static DOM::ExceptionOr<NonnullRefPtr<Blob>> create(Optional<Vector<BlobPart>> const& blob_parts = {}, Optional<BlobPropertyBag> const& options = {}); - static DOM::ExceptionOr<NonnullRefPtr<Blob>> create_with_global_object(Bindings::WindowObject&, Optional<Vector<BlobPart>> const& blob_parts = {}, Optional<BlobPropertyBag> const& options = {}); + static DOM::ExceptionOr<NonnullRefPtr<Blob>> create_with_global_object(HTML::Window&, Optional<Vector<BlobPart>> const& blob_parts = {}, Optional<BlobPropertyBag> 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 4498789aef..b982869ed2 100644 --- a/Userland/Libraries/LibWeb/FileAPI/File.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/File.cpp @@ -56,7 +56,7 @@ DOM::ExceptionOr<NonnullRefPtr<File>> File::create(Vector<BlobPart> const& file_ return adopt_ref(*new File(move(bytes), move(name), move(type), last_modified)); } -DOM::ExceptionOr<NonnullRefPtr<File>> File::create_with_global_object(Bindings::WindowObject&, Vector<BlobPart> const& file_bits, String const& file_name, Optional<FilePropertyBag> const& options) +DOM::ExceptionOr<NonnullRefPtr<File>> File::create_with_global_object(HTML::Window&, Vector<BlobPart> const& file_bits, String const& file_name, Optional<FilePropertyBag> 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 636a620b32..43a8008055 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<NonnullRefPtr<File>> create(Vector<BlobPart> const& file_bits, String const& file_name, Optional<FilePropertyBag> const& options = {}); - static DOM::ExceptionOr<NonnullRefPtr<File>> create_with_global_object(Bindings::WindowObject&, Vector<BlobPart> const& file_bits, String const& file_name, Optional<FilePropertyBag> const& options = {}); + static DOM::ExceptionOr<NonnullRefPtr<File>> create_with_global_object(HTML::Window&, Vector<BlobPart> const& file_bits, String const& file_name, Optional<FilePropertyBag> 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 1e4cfde06f..dac3d92321 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 ea75d9a36b..ccea076ebb 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<DOMPoint> create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double z = 0, double w = 0) + static NonnullRefPtr<DOMPoint> 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 5b088a41eb..b9587058ae 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<DOMPointReadOnly> create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double z = 0, double w = 0) + static NonnullRefPtr<DOMPointReadOnly> 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 dd46bec587..057ea1ca36 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<DOMRect> create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double width = 0, double height = 0) + static NonnullRefPtr<DOMRect> 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 1581ef6318..148ed1044f 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<DOMRectReadOnly> create_with_global_object(Bindings::WindowObject&, double x = 0, double y = 0, double width = 0, double height = 0) + static NonnullRefPtr<DOMRectReadOnly> 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 f9aedf8563..4af36b5b92 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> BrowsingContext::create_a_new_browsing_context(Page& page, RefPtr<DOM::Document> creator, RefPtr<DOM::Element> embedder) +NonnullRefPtr<BrowsingContext> BrowsingContext::create_a_new_browsing_context(Page& page, JS::GCPtr<DOM::Document> creator, JS::GCPtr<DOM::Element> embedder) { // 1. Let browsingContext be a new browsing context. BrowsingContextContainer* container = (embedder && is<BrowsingContextContainer>(*embedder)) ? static_cast<BrowsingContextContainer*>(embedder.ptr()) : nullptr; @@ -117,19 +117,17 @@ NonnullRefPtr<BrowsingContext> 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> window; + JS::GCPtr<Window> 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<Bindings::WindowObject>(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> 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> 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> 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<HTML::HTMLAnchorElement>(*candidate)) { - element = verify_cast<HTML::HTMLAnchorElement>(*candidate); + element = &verify_cast<HTML::HTMLAnchorElement>(*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<DOM::Node> BrowsingContext::currently_focused_area() +JS::GCPtr<DOM::Node> 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 f48ef6d4f5..ddcd870ea1 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<BrowsingContext> { public: - static NonnullRefPtr<BrowsingContext> create_a_new_browsing_context(Page&, RefPtr<DOM::Document> creator, RefPtr<DOM::Element> embedder); + static NonnullRefPtr<BrowsingContext> create_a_new_browsing_context(Page&, JS::GCPtr<DOM::Document> creator, JS::GCPtr<DOM::Element> 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<DOM::Node> currently_focused_area(); + JS::GCPtr<DOM::Node> 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<HTML::Origin> m_creator_origin; WeakPtr<HTML::BrowsingContextContainer> m_container; - RefPtr<DOM::Document> m_active_document; + JS::Handle<DOM::Document> 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 5cdc7ca497..80228438ac 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<HTML::BrowsingContextContainer>() 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 056620565c..3a6ab3cebc 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<HTMLImageElement>, NonnullRefPtr<HTMLCanvasElement>>; +using CanvasImageSource = Variant<JS::Handle<HTMLImageElement>, JS::Handle<HTMLCanvasElement>>; // 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 d748ba86a7..5aa89d10cb 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasGradient.h +++ b/Userland/Libraries/LibWeb/HTML/CanvasGradient.h @@ -16,14 +16,14 @@ class CanvasGradient final : public RefCounted<CanvasGradient> , public Bindings::Wrappable { public: - using WrapperType = Bindings::CanvasGradientWrapper; - enum class Type { Linear, Radial, Conic, }; + using WrapperType = Bindings::CanvasGradientWrapper; + static NonnullRefPtr<CanvasGradient> create_radial(double x0, double y0, double r0, double x1, double y1, double r1); static NonnullRefPtr<CanvasGradient> create_linear(double x0, double y0, double x1, double y1); static NonnullRefPtr<CanvasGradient> 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 ef49495736..fea84804e5 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -11,7 +11,6 @@ #include <LibGfx/Quad.h> #include <LibGfx/Rect.h> #include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/HTML/CanvasRenderingContext2D.h> #include <LibWeb/HTML/HTMLCanvasElement.h> @@ -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<HTMLCanvasElement> CanvasRenderingContext2D::canvas_for_binding() const +JS::NonnullGCPtr<HTMLCanvasElement> 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<CanvasImageSourceUsability> check_usability_of_image(CanvasImag // 1. Switch on image: auto usability = TRY(image.visit( // HTMLOrSVGImageElement - [](HTMLImageElement const& image_element) -> DOM::ExceptionOr<Optional<CanvasImageSourceUsability>> { + [](JS::Handle<HTMLImageElement> const& image_element) -> DOM::ExceptionOr<Optional<CanvasImageSourceUsability>> { // 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<CanvasImageSourceUsability> {}; }, @@ -538,9 +537,9 @@ DOM::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasImag // HTMLCanvasElement // FIXME: OffscreenCanvas - [](HTMLCanvasElement const& canvas_element) -> DOM::ExceptionOr<Optional<CanvasImageSourceUsability>> { + [](JS::Handle<HTMLCanvasElement> const& canvas_element) -> DOM::ExceptionOr<Optional<CanvasImageSourceUsability>> { // 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<CanvasImageSourceUsability> {}; })); @@ -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<HTMLImageElement> 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<HTMLCanvasElement> 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 3fecfb3fad..639e6dba4e 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<HTMLImageElement>, NonnullRefPtr<HTMLCanvasElement>>; +using CanvasImageSource = Variant<JS::Handle<HTMLImageElement>, JS::Handle<HTMLCanvasElement>>; class CanvasRenderingContext2D - : public RefCountForwarder<HTMLCanvasElement> + : public RefCounted<CanvasRenderingContext2D> , public Bindings::Wrappable , public CanvasPath , public CanvasState @@ -81,7 +81,7 @@ public: virtual void reset_to_default_state() override; - NonnullRefPtr<HTMLCanvasElement> canvas_for_binding() const; + JS::NonnullGCPtr<HTMLCanvasElement> canvas_for_binding() const; virtual RefPtr<TextMetrics> 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<HTMLCanvasElement> 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 6a1a0f9c6e..047cac8306 100644 --- a/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/CloseEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/CloseEvent.h> +#include <LibWeb/HTML/Window.h> 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<CloseEvent>(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 db3f1ba2b1..0930a7b0d0 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 7fc9d22c62..1f661a4ffd 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 <LibWeb/Bindings/DOMParserWrapper.h> +#include <LibWeb/Bindings/DOMParserPrototype.h> +#include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/HTML/DOMParser.h> #include <LibWeb/HTML/Parser/HTMLParser.h> #include <LibWeb/XML/XMLDocumentBuilder.h> 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<DOM::Document> DOMParser::parse_from_string(String const& string, Bindings::DOMParserSupportedType type) +JS::NonnullGCPtr<DOM::Document> 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<DOM::Document> 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<DOM::Document> 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<DOM::Document> 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 4df6ba2d5b..4c1c50f708 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<NonnullRefPtr<DOMParser>> create_with_global_object(Bindings::WindowObject&) + static DOM::ExceptionOr<NonnullRefPtr<DOMParser>> create_with_global_object(HTML::Window& window) { - return adopt_ref(*new DOMParser()); + return adopt_ref(*new DOMParser(window)); } virtual ~DOMParser() override; - NonnullRefPtr<DOM::Document> parse_from_string(String const&, Bindings::DOMParserSupportedType type); + JS::NonnullGCPtr<DOM::Document> parse_from_string(String const&, Bindings::DOMParserSupportedType type); private: - DOMParser(); + explicit DOMParser(HTML::Window&); + + JS::Handle<HTML::Window> m_window; }; } diff --git a/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp b/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp index 3e276996ed..6b6a0a85c3 100644 --- a/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp +++ b/Userland/Libraries/LibWeb/HTML/DOMStringMap.cpp @@ -6,27 +6,33 @@ #include <AK/CharacterTypes.h> #include <LibWeb/Bindings/DOMStringMapPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Element.h> #include <LibWeb/HTML/DOMStringMap.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { -DOMStringMap* DOMStringMap::create(DOM::Element& element) +JS::NonnullGCPtr<DOMStringMap> DOMStringMap::create(DOM::Element& element) { - auto& realm = element.document().preferred_window_object().realm(); - return realm.heap().allocate<DOMStringMap>(realm, element); + auto& realm = element.document().window().realm(); + return *realm.heap().allocate<DOMStringMap>(realm, element); } DOMStringMap::DOMStringMap(DOM::Element& element) - : PlatformObject(element.document().preferred_window_object().ensure_web_prototype<Bindings::DOMStringMapPrototype>("DOMStringMap")) + : PlatformObject(element.document().window().ensure_web_prototype<Bindings::DOMStringMapPrototype>("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::NameValuePair> DOMStringMap::get_name_value_pairs() const { diff --git a/Userland/Libraries/LibWeb/HTML/DOMStringMap.h b/Userland/Libraries/LibWeb/HTML/DOMStringMap.h index 902037a2db..c01294c2e9 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<DOMStringMap> create(DOM::Element&); virtual ~DOMStringMap() override; - DOMStringMap& impl() { return *this; } - Vector<String> 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<NameValuePair> get_name_value_pairs() const; // https://html.spec.whatwg.org/multipage/dom.html#concept-domstringmap-element - NonnullRefPtr<DOM::Element> m_associated_element; + JS::NonnullGCPtr<DOM::Element> 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 111f96a13d..7a9654c538 100644 --- a/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/ErrorEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/ErrorEvent.h> +#include <LibWeb/HTML/Window.h> 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<ErrorEvent>(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 83b137f497..ed978add81 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 8e421c3e88..612df30041 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 <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/DOMEventListener.h> #include <LibWeb/HTML/EventHandler.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index acded61637..34978bc6c3 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<DOM::Document> docs = documents_in_this_event_loop(); + Vector<JS::Handle<DOM::Document>> 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<Bindings::WindowObject>(global_object)) { - auto& window_object = verify_cast<Bindings::WindowObject>(global_object); + if (is<HTML::Window>(global_object)) { + auto& window_object = verify_cast<HTML::Window>(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<DOM::Document> EventLoop::documents_in_this_event_loop() const +Vector<JS::Handle<DOM::Document>> EventLoop::documents_in_this_event_loop() const { - NonnullRefPtrVector<DOM::Document> documents; + Vector<JS::Handle<DOM::Document>> 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<EnvironmentSettings } // https://html.spec.whatwg.org/multipage/webappapis.html#same-loop-windows -NonnullRefPtrVector<Window> EventLoop::same_loop_windows() const +Vector<JS::Handle<HTML::Window>> EventLoop::same_loop_windows() const { - NonnullRefPtrVector<Window> windows; + Vector<JS::Handle<HTML::Window>> 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 fbe0ec929d..61685ae6d6 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>, DOM::Document&); void unregister_document(Badge<DOM::Document>, DOM::Document&); - NonnullRefPtrVector<DOM::Document> documents_in_this_event_loop() const; + Vector<JS::Handle<DOM::Document>> documents_in_this_event_loop() const; - NonnullRefPtrVector<Window> same_loop_windows() const; + Vector<JS::Handle<HTML::Window>> same_loop_windows() const; void push_onto_backup_incumbent_settings_object_stack(Badge<EnvironmentSettingsObject>, EnvironmentSettingsObject& environment_settings_object); void pop_backup_incumbent_settings_object_stack(Badge<EnvironmentSettingsObject>); diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp index 4e9a49b385..600b76fe6a 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<void()> 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 22aaa8c10a..46de995069 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h @@ -9,6 +9,7 @@ #include <AK/Function.h> #include <AK/NonnullOwnPtr.h> #include <AK/RefPtr.h> +#include <LibJS/Heap/Handle.h> #include <LibWeb/Forward.h> 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<void()> m_steps; - RefPtr<DOM::Document> m_document; + JS::Handle<DOM::Document> m_document; }; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp index 3b2533fd13..8c19a47fab 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 <LibWeb/Bindings/HTMLAnchorElementPrototype.h> #include <LibWeb/HTML/HTMLAnchorElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLAnchorElement::HTMLAnchorElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLAnchorElementPrototype>("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 a936e7c027..1b1aad0536 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<HTML::HTMLAnchorElement>() 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 ea9b6ff47d..c941ef98bc 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 <LibWeb/Bindings/HTMLAreaElementPrototype.h> #include <LibWeb/HTML/HTMLAreaElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLAreaElement::HTMLAreaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLAreaElementPrototype>("HTMLAreaElement")); } HTMLAreaElement::~HTMLAreaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h index fecfb33af8..170524ce7a 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 1492fe4288..97befd800f 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 <LibWeb/Bindings/HTMLAudioElementPrototype.h> #include <LibWeb/HTML/HTMLAudioElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLAudioElement::HTMLAudioElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLMediaElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLAudioElementPrototype>("HTMLAudioElement")); } HTMLAudioElement::~HTMLAudioElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h index 498d43cdcf..4820124a07 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLAudioElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLAudioElement final : public HTMLMediaElement { + WEB_PLATFORM_OBJECT(HTMLAudioElement, HTMLMediaElement); + public: - using WrapperType = Bindings::HTMLAudioElementWrapper; + virtual ~HTMLAudioElement() override; +private: HTMLAudioElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLAudioElement() override; }; } + +WRAPPER_HACK(HTMLAudioElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp index d83f910fa1..9cf419290a 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 <LibWeb/Bindings/HTMLBRElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLBRElement.h> #include <LibWeb/Layout/BreakNode.h> @@ -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<Bindings::HTMLBRElementPrototype>("HTMLBRElement")); } HTMLBRElement::~HTMLBRElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h index 0c8b911158..d44f986c5a 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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) 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 afb6d0e292..66f3b44bed 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 <LibWeb/Bindings/HTMLBaseElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLBaseElement.h> @@ -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<Bindings::HTMLBaseElementPrototype>("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 0c904246cb..f32b9f5b6b 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<HTML::HTMLBaseElement>() 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 1a4cf3d456..39bb55d611 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<Core::Timer> m_timer; }; } + +WRAPPER_HACK(HTMLBlinkElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp index 5d2bc8959d..17b4bc7a76 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 <LibWeb/Bindings/HTMLBodyElementPrototype.h> #include <LibWeb/CSS/StyleProperties.h> #include <LibWeb/CSS/StyleValue.h> #include <LibWeb/DOM/Document.h> @@ -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<Bindings::HTMLBodyElementPrototype>("HTMLBodyElement")); } HTMLBodyElement::~HTMLBodyElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h index e916ecad46..302fbe58a4 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 419f4a607c..e8c9399a46 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 <LibWeb/Bindings/HTMLButtonElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLButtonElement.h> #include <LibWeb/HTML/HTMLFormElement.h> @@ -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<Bindings::HTMLButtonElementPrototype>("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 3c08419856..6ca9e78b15 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 8da131068d..79b9924935 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<CanvasRenderingContext2D>, NonnullRefPtr<WebGL::WebGLRenderingContext>, 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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) 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 b44d558d8f..e280e16342 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 <LibWeb/Bindings/HTMLDListElementPrototype.h> #include <LibWeb/HTML/HTMLDListElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLDListElement::HTMLDListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLDListElementPrototype>("HTMLDListElement")); } HTMLDListElement::~HTMLDListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h index 3664d3d32a..d2a3d975e9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDListElementWrapper; + virtual ~HTMLDListElement() override; +private: HTMLDListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDListElement() override; }; } + +WRAPPER_HACK(HTMLDListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.cpp index 39f81e6e2c..4740335f44 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 <LibWeb/Bindings/HTMLDataElementPrototype.h> #include <LibWeb/HTML/HTMLDataElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLDataElement::HTMLDataElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLDataElementPrototype>("HTMLDataElement")); } HTMLDataElement::~HTMLDataElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h index 3270881f21..7ad0fec7fd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDataElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDataElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDataElementWrapper; + virtual ~HTMLDataElement() override; +private: HTMLDataElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDataElement() override; }; } + +WRAPPER_HACK(HTMLDataElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.cpp index c12efcd6a2..b3866d30fb 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 <LibWeb/Bindings/HTMLDataListElementPrototype.h> #include <LibWeb/HTML/HTMLDataListElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLDataListElement::HTMLDataListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLDataListElementPrototype>("HTMLDataListElement")); } HTMLDataListElement::~HTMLDataListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h index d7af3b3141..26e96a83df 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDataListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDataListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDataListElementWrapper; + virtual ~HTMLDataListElement() override; +private: HTMLDataListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDataListElement() override; }; } + +WRAPPER_HACK(HTMLDataListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp index ce365af098..f2d6ac5a77 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 <LibWeb/Bindings/HTMLDetailsElementPrototype.h> #include <LibWeb/HTML/HTMLDetailsElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLDetailsElement::HTMLDetailsElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLDetailsElementPrototype>("HTMLDetailsElement")); } HTMLDetailsElement::~HTMLDetailsElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h index 9929e1e712..499e9d03be 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDetailsElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDetailsElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDetailsElementWrapper; + virtual ~HTMLDetailsElement() override; +private: HTMLDetailsElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDetailsElement() override; }; } + +WRAPPER_HACK(HTMLDetailsElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.cpp index 5885e8ef08..9aa1666f03 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 <LibWeb/Bindings/HTMLDialogElementPrototype.h> #include <LibWeb/HTML/HTMLDialogElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLDialogElement::HTMLDialogElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLDialogElementPrototype>("HTMLDialogElement")); } HTMLDialogElement::~HTMLDialogElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h index 8684fb8ca6..ad522374f6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDialogElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDialogElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDialogElementWrapper; + virtual ~HTMLDialogElement() override; +private: HTMLDialogElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDialogElement() override; }; } + +WRAPPER_HACK(HTMLDialogElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.cpp index c75726db6d..743a234ba6 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 <LibWeb/Bindings/HTMLDirectoryElementPrototype.h> #include <LibWeb/HTML/HTMLDirectoryElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLDirectoryElement::HTMLDirectoryElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLDirectoryElementPrototype>("HTMLDirectoryElement")); } HTMLDirectoryElement::~HTMLDirectoryElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h index 460415684d..7fac25e12c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDirectoryElement.h @@ -12,11 +12,15 @@ namespace Web::HTML { // NOTE: This element is marked as obsolete, but is still listed as required by the specification. class HTMLDirectoryElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDirectoryElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDirectoryElementWrapper; + virtual ~HTMLDirectoryElement() override; +private: HTMLDirectoryElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDirectoryElement() override; }; } + +WRAPPER_HACK(HTMLDirectoryElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.cpp index 74f6143665..22bc02ebc5 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 <LibWeb/Bindings/HTMLDivElementPrototype.h> #include <LibWeb/HTML/HTMLDivElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLDivElement::HTMLDivElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLDivElementPrototype>("HTMLDivElement")); } HTMLDivElement::~HTMLDivElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h index 01a28bf2d3..76e154560a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLDivElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLDivElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLDivElementWrapper; + virtual ~HTMLDivElement() override; +private: HTMLDivElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLDivElement() override; }; } + +WRAPPER_HACK(HTMLDivElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index 592f354d46..05350872c7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -7,6 +7,7 @@ #include <AK/StringBuilder.h> #include <LibJS/Interpreter.h> #include <LibJS/Parser.h> +#include <LibWeb/Bindings/HTMLElementPrototype.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/ExceptionOr.h> @@ -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<Bindings::HTMLElementPrototype>("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<DOM::Node> old_chain, NonnullRefPtrVector<DOM::Node> new_chain, DOM::Node& new_focus_target) +static void run_focus_update_steps(Vector<JS::Handle<DOM::Node>> old_chain, Vector<JS::Handle<DOM::Node>> 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<DOM::Node> old_chain, Non // then fire an event named change at the element, // with the bubbles attribute initialized to true. - RefPtr<DOM::EventTarget> blur_event_target; - if (is<DOM::Element>(entry)) { + JS::GCPtr<DOM::EventTarget> blur_event_target; + if (is<DOM::Element>(*entry)) { // 2. If entry is an element, let blur event target be entry. - blur_event_target = entry; - } else if (is<DOM::Document>(entry)) { + blur_event_target = entry.ptr(); + } else if (is<DOM::Document>(*entry)) { // If entry is a Document object, let blur event target be that Document object's relevant global object. - blur_event_target = static_cast<DOM::Document&>(entry).window(); + blur_event_target = &static_cast<DOM::Document&>(*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<DOM::EventTarget> related_blur_target; + JS::GCPtr<DOM::EventTarget> related_blur_target; if (!old_chain.is_empty() && &entry == &old_chain.last() - && is<DOM::Element>(entry) + && is<DOM::Element>(*entry) && !new_chain.is_empty() - && is<DOM::Element>(new_chain.last())) { - related_blur_target = new_chain.last(); + && is<DOM::Element>(*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<DOM::Node>(*blur_event_target).document().preferred_window_object(), HTML::EventNames::blur); + auto blur_event = UIEvents::FocusEvent::create(verify_cast<DOM::Node>(*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<DOM::Node> 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<DOM::Element>(entry)) - entry.document().set_focused_element(&static_cast<DOM::Element&>(entry)); + if (is<DOM::Element>(*entry)) + entry->document().set_focused_element(&static_cast<DOM::Element&>(*entry)); - RefPtr<DOM::EventTarget> focus_event_target; - if (is<DOM::Element>(entry)) { + JS::GCPtr<DOM::EventTarget> focus_event_target; + if (is<DOM::Element>(*entry)) { // 2. If entry is an element, let focus event target be entry. - focus_event_target = entry; - } else if (is<DOM::Document>(entry)) { + focus_event_target = entry.ptr(); + } else if (is<DOM::Document>(*entry)) { // If entry is a Document object, let focus event target be that Document object's relevant global object. - focus_event_target = static_cast<DOM::Document&>(entry).window(); + focus_event_target = &static_cast<DOM::Document&>(*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<DOM::EventTarget> related_focus_target; + JS::GCPtr<DOM::EventTarget> related_focus_target; if (!new_chain.is_empty() && &entry == &new_chain.last() - && is<DOM::Element>(entry) + && is<DOM::Element>(*entry) && !old_chain.is_empty() - && is<DOM::Element>(old_chain.last())) { - related_focus_target = old_chain.last(); + && is<DOM::Element>(*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<DOM::Node>(*focus_event_target).document().preferred_window_object(), HTML::EventNames::focus); + auto focus_event = UIEvents::FocusEvent::create(verify_cast<DOM::Node>(*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<DOM::Node> focus_chain(DOM::Node* subject) +static Vector<JS::Handle<DOM::Node>> focus_chain(DOM::Node* subject) { // FIXME: Move this somewhere more spec-friendly. if (!subject) return {}; // 1. Let output be an empty list. - NonnullRefPtrVector<DOM::Node> output; + Vector<JS::Handle<DOM::Node>> output; // 2. Let currentObject be subject. auto* current_object = subject; @@ -312,7 +320,7 @@ static NonnullRefPtrVector<DOM::Node> 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 1c0376668e..a40cd1cfd1 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<DOMStringMap> m_dataset; + JS::NonnullGCPtr<DOMStringMap> 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<HTML::HTMLElement>() 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 75f9cd9b98..d6d036c1b8 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 <LibWeb/Bindings/HTMLEmbedElementPrototype.h> #include <LibWeb/HTML/HTMLEmbedElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLEmbedElement::HTMLEmbedElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLEmbedElementPrototype>("HTMLEmbedElement")); } HTMLEmbedElement::~HTMLEmbedElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h b/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h index 4c68838800..f69e14744a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLEmbedElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLEmbedElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLEmbedElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLEmbedElementWrapper; + virtual ~HTMLEmbedElement() override; +private: HTMLEmbedElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLEmbedElement() override; }; } + +WRAPPER_HACK(HTMLEmbedElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp index 2d3db560f1..fe2f968a66 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 <LibWeb/Bindings/HTMLFieldSetElementPrototype.h> #include <LibWeb/HTML/HTMLFieldSetElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLFieldSetElement::HTMLFieldSetElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLFieldSetElementPrototype>("HTMLFieldSetElement")); } HTMLFieldSetElement::~HTMLFieldSetElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h index 1cb3a6c06c..146904a7de 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 a0c139863c..f969f03658 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 <LibWeb/Bindings/HTMLFontElementPrototype.h> #include <LibWeb/CSS/StyleProperties.h> #include <LibWeb/CSS/StyleValue.h> #include <LibWeb/HTML/HTMLFontElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLFontElement::HTMLFontElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLFontElementPrototype>("HTMLFontElement")); } HTMLFontElement::~HTMLFontElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFontElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFontElement.h index 401019fde1..7b4e2e7f21 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 6f1b96b9ea..b9ea743329 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp @@ -5,6 +5,7 @@ */ #include <AK/StringBuilder.h> +#include <LibWeb/Bindings/HTMLFormElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/BrowsingContext.h> #include <LibWeb/HTML/EventNames.h> @@ -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<Bindings::HTMLFormElementPrototype>("HTMLFormElement")); } HTMLFormElement::~HTMLFormElement() = default; -void HTMLFormElement::submit_form(RefPtr<HTMLElement> 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<HTMLElement> submitter, bool from_submit_binding) { if (cannot_navigate()) return; @@ -58,14 +67,14 @@ void HTMLFormElement::submit_form(RefPtr<HTMLElement> submitter, bool from_submi // FIXME: If the submitter element's no-validate state is false... - RefPtr<HTMLElement> submitter_button; + JS::GCPtr<HTMLElement> 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 cd0a192a79..d548bf41e9 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<HTMLElement> submitter, bool from_submit_binding = false); + void submit_form(JS::GCPtr<HTMLElement> 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<WeakPtr<HTMLElement>> m_associated_elements; + Vector<JS::GCPtr<HTMLElement>> 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 6ac1110c6b..c5ae687c05 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 <LibWeb/Bindings/HTMLFrameElementPrototype.h> #include <LibWeb/HTML/HTMLFrameElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLFrameElement::HTMLFrameElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLFrameElementPrototype>("HTMLFrameElement")); } HTMLFrameElement::~HTMLFrameElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h index 39087a6969..505b112213 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h @@ -12,11 +12,15 @@ namespace Web::HTML { // NOTE: This element is marked as obsolete, but is still listed as required by the specification. class HTMLFrameElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLFrameElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLFrameElementWrapper; + virtual ~HTMLFrameElement() override; +private: HTMLFrameElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLFrameElement() override; }; } + +WRAPPER_HACK(HTMLFrameElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp index bf7d86accd..52d06e9540 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 <LibWeb/Bindings/HTMLFrameSetElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLFrameSetElement.h> #include <LibWeb/HTML/Window.h> @@ -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<Bindings::HTMLFrameSetElementPrototype>("HTMLFrameSetElement")); } HTMLFrameSetElement::~HTMLFrameSetElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h index 3a4088d997..8ff5a34c83 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h @@ -15,11 +15,13 @@ namespace Web::HTML { class HTMLFrameSetElement final : public HTMLElement , public WindowEventHandlers { + WEB_PLATFORM_OBJECT(HTMLFrameSetElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLFrameSetElementWrapper; + virtual ~HTMLFrameSetElement() override; +private: HTMLFrameSetElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLFrameSetElement() override; virtual void parse_attribute(FlyString const&, String const&) override; @@ -32,3 +34,5 @@ private: }; } + +WRAPPER_HACK(HTMLFrameSetElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.cpp index 170973715a..89d19cb1e5 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 <LibWeb/Bindings/HTMLHRElementPrototype.h> #include <LibWeb/HTML/HTMLHRElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLHRElement::HTMLHRElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLHRElementPrototype>("HTMLHRElement")); } HTMLHRElement::~HTMLHRElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h index 69f5649ea9..21accb7746 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLHRElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLHRElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLHRElementWrapper; + virtual ~HTMLHRElement() override; +private: HTMLHRElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLHRElement() override; }; } + +WRAPPER_HACK(HTMLHRElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.cpp index e4533b2158..fa35126797 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 <LibWeb/Bindings/HTMLHeadElementPrototype.h> #include <LibWeb/HTML/HTMLHeadElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLHeadElement::HTMLHeadElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLHeadElementPrototype>("HTMLHeadElement")); } HTMLHeadElement::~HTMLHeadElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h index e2faf9a5c6..9996aa230b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHeadElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLHeadElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLHeadElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLHeadElementWrapper; + virtual ~HTMLHeadElement() override; +private: HTMLHeadElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLHeadElement() override; }; } + +WRAPPER_HACK(HTMLHeadElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp index 10b1c9b7d6..28b276f17a 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 <LibWeb/Bindings/HTMLHeadingElementPrototype.h> #include <LibWeb/HTML/HTMLHeadingElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLHeadingElement::HTMLHeadingElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLHeadingElementPrototype>("HTMLHeadingElement")); } HTMLHeadingElement::~HTMLHeadingElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h index d5c7644a79..5deffd8985 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLHeadingElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLHeadingElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLHeadingElementWrapper; + virtual ~HTMLHeadingElement() override; +private: HTMLHeadingElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLHeadingElement() override; }; } + +WRAPPER_HACK(HTMLHeadingElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp index 179c4d0b9b..90fe7f8c52 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 <LibWeb/Bindings/HTMLHtmlElementPrototype.h> #include <LibWeb/HTML/HTMLHtmlElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLHtmlElement::HTMLHtmlElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLHtmlElementPrototype>("HTMLHtmlElement")); } HTMLHtmlElement::~HTMLHtmlElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h index 1222355040..0f8c6b3c5f 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<HTML::HTMLHtmlElement>() 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 83b6fb3c45..2ee367455e 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 <LibWeb/Bindings/HTMLIFrameElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/HTML/BrowsingContext.h> @@ -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<Bindings::HTMLIFrameElementPrototype>("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 34149e50ed..f9728145e5 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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) 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 6a2ecb60f4..4e2d0d3911 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -5,6 +5,7 @@ */ #include <LibGfx/Bitmap.h> +#include <LibWeb/Bindings/HTMLImageElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/CSS/StyleComputer.h> #include <LibWeb/DOM/Document.h> @@ -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<Bindings::HTMLImageElementPrototype>("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 046a29fd64..88026331fd 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 66557d5cae..4ca7cc2f05 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 <LibWeb/Bindings/HTMLInputElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/ShadowRoot.h> @@ -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<Bindings::HTMLInputElementPrototype>("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<Layout::Node> HTMLInputElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> 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<HTMLFormElement> form; + JS::GCPtr<HTMLFormElement> 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<BrowsingContext>) // 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<DOM::ShadowRoot>(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<DOM::Text>(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<HTML::HTMLInputElement>([&](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 543295b653..4b7f3c1849 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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) 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<DOM::Text> m_text_node; + JS::GCPtr<DOM::Text> 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<HTMLInputElement> m_legacy_pre_activation_behavior_checked_element_in_group; + JS::GCPtr<HTMLInputElement> 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 2c166fabd4..1c85241a0a 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 <LibWeb/Bindings/HTMLLIElementPrototype.h> #include <LibWeb/HTML/HTMLLIElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLLIElement::HTMLLIElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLLIElementPrototype>("HTMLLIElement")); } HTMLLIElement::~HTMLLIElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h index 071f1f8927..4eb8572ff1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLLIElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLLIElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLLIElementWrapper; + virtual ~HTMLLIElement() override; +private: HTMLLIElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLLIElement() override; }; } + +WRAPPER_HACK(HTMLLIElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp index 71f73e2b4e..31398d3c90 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 <LibWeb/Bindings/HTMLLabelElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLLabelElement.h> #include <LibWeb/Layout/Label.h> @@ -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<Bindings::HTMLLabelElementPrototype>("HTMLLabelElement")); } HTMLLabelElement::~HTMLLabelElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h index cae5adb9ce..2cc266cd86 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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) 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 48247dba26..7cdaae7016 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 <LibWeb/Bindings/HTMLLegendElementPrototype.h> #include <LibWeb/HTML/HTMLLegendElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLLegendElement::HTMLLegendElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLLegendElementPrototype>("HTMLLegendElement")); } HTMLLegendElement::~HTMLLegendElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h index 5acdbec2d1..aea891af7b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLLegendElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLLegendElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLLegendElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLLegendElementWrapper; + virtual ~HTMLLegendElement() override; +private: HTMLLegendElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLLegendElement() override; }; } + +WRAPPER_HACK(HTMLLegendElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp index 345011dcc5..c2365ab429 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp @@ -9,6 +9,7 @@ #include <AK/ByteBuffer.h> #include <AK/Debug.h> #include <AK/URL.h> +#include <LibWeb/Bindings/HTMLLinkElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLLinkElement.h> @@ -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<Bindings::HTMLLinkElementPrototype>("HTMLLinkElement")); } HTMLLinkElement::~HTMLLinkElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.h index 844bba4149..ef8055adde 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 b8c68863f6..e02e7374f0 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 <LibWeb/Bindings/HTMLMapElementPrototype.h> #include <LibWeb/HTML/HTMLMapElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLMapElement::HTMLMapElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLMapElementPrototype>("HTMLMapElement")); } HTMLMapElement::~HTMLMapElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h index bf66b80239..84dd4211ac 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMapElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLMapElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLMapElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLMapElementWrapper; + virtual ~HTMLMapElement() override; +private: HTMLMapElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLMapElement() override; }; } + +WRAPPER_HACK(HTMLMapElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp index c70c667b12..9c9bebbb46 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 <LibWeb/Bindings/HTMLMarqueeElementPrototype.h> #include <LibWeb/HTML/HTMLMarqueeElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLMarqueeElement::HTMLMarqueeElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLMarqueeElementPrototype>("HTMLMarqueeElement")); } HTMLMarqueeElement::~HTMLMarqueeElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMarqueeElement.h index 556dfa1fae..9183ba73f7 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 545984dae1..2d53b2e716 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 <LibWeb/Bindings/HTMLMediaElementWrapper.h> +#include <LibWeb/Bindings/HTMLMediaElementPrototype.h> #include <LibWeb/HTML/HTMLMediaElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLMediaElement::HTMLMediaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLMediaElementPrototype>("HTMLMediaElement")); } HTMLMediaElement::~HTMLMediaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h index ed5bb41b5b..331a2f53c3 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 5b8405ff90..65528d3078 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 <LibWeb/Bindings/HTMLMenuElementPrototype.h> #include <LibWeb/HTML/HTMLMenuElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLMenuElement::HTMLMenuElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLMenuElementPrototype>("HTMLMenuElement")); } HTMLMenuElement::~HTMLMenuElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h index f05e3ab935..f1ae4a7833 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLMenuElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLMenuElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLMenuElementWrapper; + virtual ~HTMLMenuElement() override; +private: HTMLMenuElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLMenuElement() override; }; } + +WRAPPER_HACK(HTMLMenuElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp index 6812c46022..66eaf3cc03 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 <LibWeb/Bindings/HTMLMetaElementPrototype.h> #include <LibWeb/HTML/HTMLMetaElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLMetaElement::HTMLMetaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLMetaElementPrototype>("HTMLMetaElement")); } HTMLMetaElement::~HTMLMetaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h index 0e2a7e1883..62ac9dcdf7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLMetaElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLMetaElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLMetaElementWrapper; + virtual ~HTMLMetaElement() override; +private: HTMLMetaElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLMetaElement() override; }; } + +WRAPPER_HACK(HTMLMetaElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.cpp index 0341aac4bb..6d33d2e414 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 <LibWeb/Bindings/HTMLMeterElementPrototype.h> #include <LibWeb/HTML/HTMLMeterElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLMeterElement::HTMLMeterElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLMeterElementPrototype>("HTMLMeterElement")); } HTMLMeterElement::~HTMLMeterElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h index 7877ea7f58..28474b4234 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 4201d8b316..b4d7325868 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 <LibWeb/Bindings/HTMLModElementPrototype.h> #include <LibWeb/HTML/HTMLModElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLModElement::HTMLModElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLModElementPrototype>("HTMLModElement")); } HTMLModElement::~HTMLModElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLModElement.h b/Userland/Libraries/LibWeb/HTML/HTMLModElement.h index b8126fa1c1..64044da145 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLModElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLModElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLModElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLModElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLModElementWrapper; + virtual ~HTMLModElement() override; +private: HTMLModElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLModElement() override; }; } + +WRAPPER_HACK(HTMLModElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.cpp index 90ddc29efc..a397c00a57 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 <LibWeb/Bindings/HTMLOListElementPrototype.h> #include <LibWeb/HTML/HTMLOListElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLOListElement::HTMLOListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLOListElementPrototype>("HTMLOListElement")); } HTMLOListElement::~HTMLOListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h index 25eb96b486..a320b94fa2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLOListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLOListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLOListElementWrapper; + virtual ~HTMLOListElement() override; +private: HTMLOListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLOListElement() override; }; } + +WRAPPER_HACK(HTMLOListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index baea923426..678a058256 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -5,6 +5,7 @@ */ #include <LibGfx/Bitmap.h> +#include <LibWeb/Bindings/HTMLObjectElementPrototype.h> #include <LibWeb/CSS/StyleComputer.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> @@ -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<Bindings::HTMLObjectElementPrototype>("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 9b8b7aa558..d0d784beab 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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) 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 f44d2fcad0..ce45d467f2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.idl @@ -1,3 +1,4 @@ +#import <DOM/Document.idl> #import <HTML/HTMLElement.idl> interface HTMLObjectElement : HTMLElement { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.cpp index 648d9a686c..2460f1fe25 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 <LibWeb/Bindings/HTMLOptGroupElementPrototype.h> #include <LibWeb/HTML/HTMLOptGroupElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLOptGroupElement::HTMLOptGroupElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLOptGroupElementPrototype>("HTMLOptGroupElement")); } HTMLOptGroupElement::~HTMLOptGroupElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h index dc04138cb1..87427b5698 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLOptGroupElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLOptGroupElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLOptGroupElementWrapper; + virtual ~HTMLOptGroupElement() override; +private: HTMLOptGroupElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLOptGroupElement() override; }; } + +WRAPPER_HACK(HTMLOptGroupElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp index 8f4fed8b60..06c27df4b9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp @@ -6,11 +6,13 @@ */ #include <AK/StringBuilder.h> +#include <LibWeb/Bindings/HTMLOptionElementPrototype.h> #include <LibWeb/DOM/Node.h> #include <LibWeb/DOM/Text.h> #include <LibWeb/HTML/HTMLOptionElement.h> #include <LibWeb/HTML/HTMLScriptElement.h> #include <LibWeb/HTML/HTMLSelectElement.h> +#include <LibWeb/HTML/Window.h> #include <ctype.h> 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<Bindings::HTMLOptionElementPrototype>("HTMLOptionElement")); } HTMLOptionElement::~HTMLOptionElement() = default; @@ -138,7 +141,7 @@ int HTMLOptionElement::index() const if (auto select_element = first_ancestor_of_type<HTMLSelectElement>()) { 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 8b83003ced..79aade13c3 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 01a7fa79e4..b3d7589223 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<boo // https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmloptionscollection-add DOM::ExceptionOr<void> HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement element, Optional<HTMLElementOrElementIndex> before) { - auto resolved_element = element.visit([](auto const& e) -> NonnullRefPtr<HTMLElement> { return e; }); + auto resolved_element = element.visit( + [](auto& e) -> JS::Handle<HTMLElement> { + return JS::make_handle(static_cast<HTML::HTMLElement&>(*e)); + }); - RefPtr<DOM::Node> before_element; - if (before.has_value() && before->has<NonnullRefPtr<HTMLElement>>()) - before_element = before->get<NonnullRefPtr<HTMLElement>>(); + JS::GCPtr<DOM::Node> before_element; + if (before.has_value() && before->has<JS::Handle<HTMLElement>>()) + before_element = before->get<JS::Handle<HTMLElement>>().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<void> 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<DOM::Node> reference; + JS::GCPtr<DOM::Node> reference; if (before_element) reference = move(before_element); @@ -50,7 +53,7 @@ DOM::ExceptionOr<void> 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 105009b4ff..e27b2491e3 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<HTMLOptionElement>, NonnullRefPtr<HTMLOptGroupElement>>; -using HTMLElementOrElementIndex = Variant<NonnullRefPtr<HTMLElement>, i32>; +using HTMLOptionOrOptGroupElement = Variant<JS::Handle<HTMLOptionElement>, JS::Handle<HTMLOptGroupElement>>; +using HTMLElementOrElementIndex = Variant<JS::Handle<HTMLElement>, 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 e9fcc6a941..b5f8f5d07d 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 <LibWeb/Bindings/HTMLOutputElementPrototype.h> #include <LibWeb/HTML/HTMLOutputElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLOutputElement::HTMLOutputElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLOutputElementPrototype>("HTMLOutputElement")); } HTMLOutputElement::~HTMLOutputElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h index fb3ad802d0..9b75d17949 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 2e93713cb6..b8dabd218a 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 <LibWeb/Bindings/HTMLParagraphElementPrototype.h> #include <LibWeb/HTML/HTMLParagraphElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLParagraphElement::HTMLParagraphElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLParagraphElementPrototype>("HTMLParagraphElement")); } HTMLParagraphElement::~HTMLParagraphElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h index 9d03daf490..1a86e50e4e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLParagraphElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLParagraphElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLParagraphElementWrapper; + virtual ~HTMLParagraphElement() override; +private: HTMLParagraphElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLParagraphElement() override; }; } + +WRAPPER_HACK(HTMLParagraphElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.cpp index 93c88d92b3..9e41a5f402 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 <LibWeb/Bindings/HTMLParamElementPrototype.h> #include <LibWeb/HTML/HTMLParamElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLParamElement::HTMLParamElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLParamElementPrototype>("HTMLParamElement")); } HTMLParamElement::~HTMLParamElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h index e13ae0a2ea..524580ed44 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLParamElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLParamElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLParamElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLParamElementWrapper; + virtual ~HTMLParamElement() override; +private: HTMLParamElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLParamElement() override; }; } + +WRAPPER_HACK(HTMLParamElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.cpp index c6e3bbea72..6dcd14db66 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 <LibWeb/Bindings/HTMLPictureElementPrototype.h> #include <LibWeb/HTML/HTMLPictureElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLPictureElement::HTMLPictureElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLPictureElementPrototype>("HTMLPictureElement")); } HTMLPictureElement::~HTMLPictureElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h index 72bf00d8be..37f34c3725 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLPictureElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLPictureElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLPictureElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLPictureElementWrapper; + virtual ~HTMLPictureElement() override; +private: HTMLPictureElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLPictureElement() override; }; } + +WRAPPER_HACK(HTMLPictureElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.cpp index b098384bcc..400e9978ab 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 <LibWeb/Bindings/HTMLPreElementPrototype.h> #include <LibWeb/HTML/HTMLPreElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLPreElement::HTMLPreElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLPreElementPrototype>("HTMLPreElement")); } HTMLPreElement::~HTMLPreElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h index fa8f24887b..9797ea25da 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 62abdd9f95..d3e8bcd500 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 <LibWeb/Bindings/HTMLProgressElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/ShadowRoot.h> #include <LibWeb/HTML/HTMLProgressElement.h> @@ -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<Bindings::HTMLProgressElementPrototype>("HTMLProgressElement")); } HTMLProgressElement::~HTMLProgressElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h index f1af0fd1b6..d1cc612ef3 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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) 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 552ecdfce7..daed2603af 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 <LibWeb/Bindings/HTMLQuoteElementPrototype.h> #include <LibWeb/HTML/HTMLQuoteElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLQuoteElement::HTMLQuoteElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLQuoteElementPrototype>("HTMLQuoteElement")); } HTMLQuoteElement::~HTMLQuoteElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h index ea25c54144..7a38ce478c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLQuoteElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLQuoteElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLQuoteElementWrapper; + virtual ~HTMLQuoteElement() override; +private: HTMLQuoteElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLQuoteElement() override; }; } + +WRAPPER_HACK(HTMLQuoteElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp index fee2ba9df5..3b6f000e0f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp @@ -7,6 +7,7 @@ #include <AK/Debug.h> #include <AK/StringBuilder.h> #include <LibTextCodec/Decoder.h> +#include <LibWeb/Bindings/HTMLScriptElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/ShadowRoot.h> @@ -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<Bindings::HTMLScriptElementPrototype>("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<DOM::Document> node_document = document(); + JS::NonnullGCPtr<DOM::Document> 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<DOM::Document> parser_document = m_parser_document.ptr(); + JS::GCPtr<DOM::Document> 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 fbaa5eab51..0ff4f977a6 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<OneOf<XMLDocumentBuilder, HTMLParser> T> - void set_parser_document(Badge<T>, DOM::Document& document) { m_parser_document = document; } + void set_parser_document(Badge<T>, DOM::Document& document) { m_parser_document = &document; } template<OneOf<XMLDocumentBuilder, HTMLParser> T> void set_non_blocking(Badge<T>, bool b) { m_non_blocking = b; } @@ -51,13 +50,17 @@ public: void set_source_line_number(Badge<HTMLParser>, 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()>); void begin_delaying_document_load_event(DOM::Document&); - WeakPtr<DOM::Document> m_parser_document; - WeakPtr<DOM::Document> m_preparation_time_document; + JS::GCPtr<DOM::Document> m_parser_document; + JS::GCPtr<DOM::Document> 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 94333e018d..25027acd4d 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 <LibWeb/Bindings/HTMLSelectElementPrototype.h> #include <LibWeb/HTML/HTMLFormElement.h> #include <LibWeb/HTML/HTMLOptGroupElement.h> #include <LibWeb/HTML/HTMLOptionElement.h> #include <LibWeb/HTML/HTMLSelectElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLSelectElement::HTMLSelectElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLSelectElementPrototype>("HTMLSelectElement")); } HTMLSelectElement::~HTMLSelectElement() = default; @@ -42,19 +45,19 @@ DOM::ExceptionOr<void> HTMLSelectElement::add(HTMLOptionOrOptGroupElement elemen } // https://html.spec.whatwg.org/multipage/form-elements.html#concept-select-option-list -NonnullRefPtrVector<HTMLOptionElement> HTMLSelectElement::list_of_options() const +Vector<JS::Handle<HTMLOptionElement>> 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<HTMLOptionElement> list; + Vector<JS::Handle<HTMLOptionElement>> list; for_each_child_of_type<HTMLOptionElement>([&](HTMLOptionElement const& option_element) { - list.append(option_element); + list.append(JS::make_handle(const_cast<HTMLOptionElement&>(option_element))); }); for_each_child_of_type<HTMLOptGroupElement>([&](HTMLOptGroupElement const& optgroup_element) { optgroup_element.for_each_child_of_type<HTMLOptionElement>([&](HTMLOptionElement const& option_element) { - list.append(option_element); + list.append(JS::make_handle(const_cast<HTMLOptionElement&>(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<int>(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 cbb19ec9ba..86b42eb07e 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<HTMLOptionsCollection> const& options(); @@ -32,7 +30,7 @@ public: int selected_index() const; void set_selected_index(int); - NonnullRefPtrVector<HTMLOptionElement> list_of_options() const; + Vector<JS::Handle<HTMLOptionElement>> 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<HTMLOptionsCollection> m_options; }; } + +WRAPPER_HACK(HTMLSelectElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp index e3c72331df..36d316516c 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 <LibWeb/Bindings/HTMLSlotElementPrototype.h> #include <LibWeb/HTML/HTMLSlotElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLSlotElement::HTMLSlotElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLSlotElementPrototype>("HTMLSlotElement")); } HTMLSlotElement::~HTMLSlotElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h index c0564dc02f..795ad07558 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLSlotElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLSlotElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLSlotElementWrapper; + virtual ~HTMLSlotElement() override; +private: HTMLSlotElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLSlotElement() override; }; } + +WRAPPER_HACK(HTMLSlotElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.cpp index f682bf46e0..38c3172e56 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 <LibWeb/Bindings/HTMLSourceElementPrototype.h> #include <LibWeb/HTML/HTMLSourceElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLSourceElement::HTMLSourceElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLSourceElementPrototype>("HTMLSourceElement")); } HTMLSourceElement::~HTMLSourceElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h index 196a6041e7..65df7a4004 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSourceElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLSourceElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLSourceElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLSourceElementWrapper; + virtual ~HTMLSourceElement() override; +private: HTMLSourceElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLSourceElement() override; }; } + +WRAPPER_HACK(HTMLSourceElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.cpp index 1fb05693d4..8f3c0177f4 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 <LibWeb/Bindings/HTMLSpanElementPrototype.h> #include <LibWeb/HTML/HTMLSpanElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLSpanElement::HTMLSpanElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLSpanElementPrototype>("HTMLSpanElement")); } HTMLSpanElement::~HTMLSpanElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h index aa7b7a1d72..3b67123ced 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLSpanElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLSpanElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLSpanElementWrapper; + virtual ~HTMLSpanElement() override; +private: HTMLSpanElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLSpanElement() override; }; } + +WRAPPER_HACK(HTMLSpanElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp index f7655da00d..1013e8b2bf 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 <LibWeb/Bindings/HTMLStyleElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLStyleElement.h> @@ -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<Bindings::HTMLStyleElementPrototype>("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 e12d1dd3ec..9e1bfd268f 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<CSS::CSSStyleSheet> m_associated_css_style_sheet; + JS::GCPtr<CSS::CSSStyleSheet> 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 542de9fda5..27b7a0d80d 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 <LibWeb/Bindings/HTMLTableCaptionElementPrototype.h> #include <LibWeb/HTML/HTMLTableCaptionElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLTableCaptionElement::HTMLTableCaptionElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLTableCaptionElementPrototype>("HTMLTableCaptionElement")); } HTMLTableCaptionElement::~HTMLTableCaptionElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h index c813366dd8..0761306f7e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTableCaptionElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTableCaptionElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTableCaptionElementWrapper; + virtual ~HTMLTableCaptionElement() override; +private: HTMLTableCaptionElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTableCaptionElement() override; }; } + +WRAPPER_HACK(HTMLTableCaptionElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp index 936512dc97..9f97fa7540 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 <LibWeb/Bindings/HTMLTableCellElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/HTML/HTMLTableCellElement.h> #include <LibWeb/HTML/Parser/HTMLParser.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLTableCellElement::HTMLTableCellElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLTableCellElementPrototype>("HTMLTableCellElement")); } HTMLTableCellElement::~HTMLTableCellElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h index 1393e344d4..d6fd5104dc 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 97dfc3f6df..f48bbbb9bc 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 <LibWeb/Bindings/HTMLTableColElementPrototype.h> #include <LibWeb/HTML/HTMLTableColElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLTableColElement::HTMLTableColElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLTableColElementPrototype>("HTMLTableColElement")); } HTMLTableColElement::~HTMLTableColElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h index ee60076a19..21e397f14b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableColElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTableColElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTableColElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTableColElementWrapper; + virtual ~HTMLTableColElement() override; +private: HTMLTableColElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTableColElement() override; }; } + +WRAPPER_HACK(HTMLTableColElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp index 447005b95d..e3da69c0d3 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 <LibWeb/Bindings/HTMLTableElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/DOM/ElementFactory.h> #include <LibWeb/DOM/HTMLCollection.h> @@ -12,6 +13,7 @@ #include <LibWeb/HTML/HTMLTableElement.h> #include <LibWeb/HTML/HTMLTableRowElement.h> #include <LibWeb/HTML/Parser/HTMLParser.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/Namespace.h> 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<Bindings::HTMLTableElementPrototype>("HTMLTableElement")); } HTMLTableElement::~HTMLTableElement() = default; @@ -45,7 +48,7 @@ void HTMLTableElement::apply_presentational_hints(CSS::StyleProperties& style) c }); } -RefPtr<HTMLTableCaptionElement> HTMLTableElement::caption() +JS::GCPtr<HTMLTableCaptionElement> HTMLTableElement::caption() { return first_child_of_type<HTMLTableCaptionElement>(); } @@ -62,7 +65,7 @@ void HTMLTableElement::set_caption(HTMLTableCaptionElement* caption) pre_insert(*caption, first_child()); } -NonnullRefPtr<HTMLTableCaptionElement> HTMLTableElement::create_caption() +JS::NonnullGCPtr<HTMLTableCaptionElement> HTMLTableElement::create_caption() { auto maybe_caption = caption(); if (maybe_caption) { @@ -71,7 +74,7 @@ NonnullRefPtr<HTMLTableCaptionElement> HTMLTableElement::create_caption() auto caption = DOM::create_element(document(), TagNames::caption, Namespace::HTML); pre_insert(caption, first_child()); - return static_ptr_cast<HTMLTableCaptionElement>(caption); + return static_cast<HTMLTableCaptionElement&>(*caption); } void HTMLTableElement::delete_caption() @@ -82,7 +85,7 @@ void HTMLTableElement::delete_caption() } } -RefPtr<HTMLTableSectionElement> HTMLTableElement::t_head() +JS::GCPtr<HTMLTableSectionElement> HTMLTableElement::t_head() { for (auto* child = first_child(); child; child = child->next_sibling()) { if (is<HTMLTableSectionElement>(*child)) { @@ -130,7 +133,7 @@ DOM::ExceptionOr<void> HTMLTableElement::set_t_head(HTMLTableSectionElement* the return {}; } -NonnullRefPtr<HTMLTableSectionElement> HTMLTableElement::create_t_head() +JS::NonnullGCPtr<HTMLTableSectionElement> HTMLTableElement::create_t_head() { auto maybe_thead = t_head(); if (maybe_thead) @@ -158,7 +161,7 @@ NonnullRefPtr<HTMLTableSectionElement> HTMLTableElement::create_t_head() pre_insert(thead, child_to_append_after); - return static_ptr_cast<HTMLTableSectionElement>(thead); + return static_cast<HTMLTableSectionElement&>(*thead); } void HTMLTableElement::delete_t_head() @@ -169,7 +172,7 @@ void HTMLTableElement::delete_t_head() } } -RefPtr<HTMLTableSectionElement> HTMLTableElement::t_foot() +JS::GCPtr<HTMLTableSectionElement> HTMLTableElement::t_foot() { for (auto* child = first_child(); child; child = child->next_sibling()) { if (is<HTMLTableSectionElement>(*child)) { @@ -200,7 +203,7 @@ DOM::ExceptionOr<void> HTMLTableElement::set_t_foot(HTMLTableSectionElement* tfo return {}; } -NonnullRefPtr<HTMLTableSectionElement> HTMLTableElement::create_t_foot() +JS::NonnullGCPtr<HTMLTableSectionElement> HTMLTableElement::create_t_foot() { auto maybe_tfoot = t_foot(); if (maybe_tfoot) @@ -208,7 +211,7 @@ NonnullRefPtr<HTMLTableSectionElement> HTMLTableElement::create_t_foot() auto tfoot = DOM::create_element(document(), TagNames::tfoot, Namespace::HTML); append_child(tfoot); - return static_ptr_cast<HTMLTableSectionElement>(tfoot); + return static_cast<HTMLTableSectionElement&>(*tfoot); } void HTMLTableElement::delete_t_foot() @@ -226,7 +229,7 @@ NonnullRefPtr<DOM::HTMLCollection> HTMLTableElement::t_bodies() }); } -NonnullRefPtr<HTMLTableSectionElement> HTMLTableElement::create_t_body() +JS::NonnullGCPtr<HTMLTableSectionElement> HTMLTableElement::create_t_body() { auto tbody = DOM::create_element(document(), TagNames::tbody, Namespace::HTML); @@ -247,7 +250,7 @@ NonnullRefPtr<HTMLTableSectionElement> HTMLTableElement::create_t_body() pre_insert(tbody, child_to_append_after); - return static_ptr_cast<HTMLTableSectionElement>(tbody); + return static_cast<HTMLTableSectionElement&>(*tbody); } NonnullRefPtr<DOM::HTMLCollection> HTMLTableElement::rows() @@ -278,7 +281,7 @@ NonnullRefPtr<DOM::HTMLCollection> HTMLTableElement::rows() }); } -DOM::ExceptionOr<NonnullRefPtr<HTMLTableRowElement>> HTMLTableElement::insert_row(long index) +DOM::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> HTMLTableElement::insert_row(long index) { auto rows = this->rows(); auto rows_length = rows->length(); @@ -286,7 +289,7 @@ DOM::ExceptionOr<NonnullRefPtr<HTMLTableRowElement>> 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<HTMLTableRowElement>(DOM::create_element(document(), TagNames::tr, Namespace::HTML)); + auto& tr = static_cast<HTMLTableRowElement&>(*DOM::create_element(document(), TagNames::tr, Namespace::HTML)); if (rows_length == 0 && !has_child_of_type<HTMLTableRowElement>()) { auto tbody = DOM::create_element(document(), TagNames::tbody, Namespace::HTML); tbody->append_child(tr); @@ -300,7 +303,7 @@ DOM::ExceptionOr<NonnullRefPtr<HTMLTableRowElement>> 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 cd166087db..1b6840d88e 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<HTMLTableCaptionElement> caption(); + JS::GCPtr<HTMLTableCaptionElement> caption(); void set_caption(HTMLTableCaptionElement*); - NonnullRefPtr<HTMLTableCaptionElement> create_caption(); + JS::NonnullGCPtr<HTMLTableCaptionElement> create_caption(); void delete_caption(); - RefPtr<HTMLTableSectionElement> t_head(); + JS::GCPtr<HTMLTableSectionElement> t_head(); DOM::ExceptionOr<void> set_t_head(HTMLTableSectionElement* thead); - NonnullRefPtr<HTMLTableSectionElement> create_t_head(); + JS::NonnullGCPtr<HTMLTableSectionElement> create_t_head(); void delete_t_head(); - RefPtr<HTMLTableSectionElement> t_foot(); + JS::GCPtr<HTMLTableSectionElement> t_foot(); DOM::ExceptionOr<void> set_t_foot(HTMLTableSectionElement* tfoot); - NonnullRefPtr<HTMLTableSectionElement> create_t_foot(); + JS::NonnullGCPtr<HTMLTableSectionElement> create_t_foot(); void delete_t_foot(); NonnullRefPtr<DOM::HTMLCollection> t_bodies(); - NonnullRefPtr<HTMLTableSectionElement> create_t_body(); + JS::NonnullGCPtr<HTMLTableSectionElement> create_t_body(); NonnullRefPtr<DOM::HTMLCollection> rows(); - DOM::ExceptionOr<NonnullRefPtr<HTMLTableRowElement>> insert_row(long index); + DOM::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> insert_row(long index); DOM::ExceptionOr<void> 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 107d807359..307cc5cc8c 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 <LibWeb/Bindings/HTMLTableRowElementPrototype.h> #include <LibWeb/DOM/HTMLCollection.h> #include <LibWeb/HTML/HTMLTableCellElement.h> #include <LibWeb/HTML/HTMLTableElement.h> #include <LibWeb/HTML/HTMLTableRowElement.h> #include <LibWeb/HTML/HTMLTableSectionElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLTableRowElement::HTMLTableRowElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLTableRowElementPrototype>("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 065244ec7a..03b6cb1eb2 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<DOM::HTMLCollection> 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 326dffa95d..6e66c9d33c 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 <LibWeb/Bindings/HTMLTableSectionElementPrototype.h> #include <LibWeb/DOM/ElementFactory.h> #include <LibWeb/DOM/HTMLCollection.h> #include <LibWeb/HTML/HTMLTableRowElement.h> #include <LibWeb/HTML/HTMLTableSectionElement.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/Namespace.h> 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<Bindings::HTMLTableSectionElementPrototype>("HTMLTableSectionElement")); } HTMLTableSectionElement::~HTMLTableSectionElement() = default; @@ -34,7 +37,7 @@ NonnullRefPtr<DOM::HTMLCollection> HTMLTableSectionElement::rows() const } // https://html.spec.whatwg.org/multipage/tables.html#dom-tbody-insertrow -DOM::ExceptionOr<NonnullRefPtr<HTMLTableRowElement>> HTMLTableSectionElement::insert_row(long index) +DOM::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> HTMLTableSectionElement::insert_row(long index) { auto rows_collection = rows(); auto rows_collection_size = static_cast<long>(rows_collection->length()); @@ -44,17 +47,17 @@ DOM::ExceptionOr<NonnullRefPtr<HTMLTableRowElement>> 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<HTMLTableRowElement>(DOM::create_element(document(), TagNames::tr, Namespace::HTML)); + auto& table_row = static_cast<HTMLTableRowElement&>(*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 98642fdde3..112a92a9ff 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<DOM::HTMLCollection> rows() const; - DOM::ExceptionOr<NonnullRefPtr<HTMLTableRowElement>> insert_row(long index); + DOM::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> insert_row(long index); DOM::ExceptionOr<void> 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 2b6a9a6a1a..b32e5a8dd9 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 <LibWeb/Bindings/HTMLTemplateElementPrototype.h> +#include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLTemplateElement.h> @@ -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<Bindings::HTMLTemplateElementPrototype>("HTMLTemplateElement")); + + m_content = heap().allocate<DOM::DocumentFragment>(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 b00dc90bf7..9c1c2e712e 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<DOM::DocumentFragment> content() { return *m_content; } - NonnullRefPtr<DOM::DocumentFragment> const content() const { return *m_content; } + JS::NonnullGCPtr<DOM::DocumentFragment> content() { return *m_content; } + JS::NonnullGCPtr<DOM::DocumentFragment> 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<DOM::DocumentFragment> m_content; + JS::GCPtr<DOM::DocumentFragment> m_content; }; } @@ -38,3 +40,5 @@ namespace Web::DOM { template<> inline bool Node::fast_is<HTML::HTMLTemplateElement>() 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 e9c0db91d4..70ea1f21d0 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 <LibWeb/Bindings/HTMLTextAreaElementPrototype.h> #include <LibWeb/HTML/HTMLTextAreaElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLTextAreaElement::HTMLTextAreaElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLTextAreaElementPrototype>("HTMLTextAreaElement")); } HTMLTextAreaElement::~HTMLTextAreaElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h index f8705b2551..f0d64e82b9 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 c40869599f..9464799740 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 <LibWeb/Bindings/HTMLTextAreaElementPrototype.h> #include <LibWeb/HTML/HTMLTimeElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLTimeElement::HTMLTimeElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLTextAreaElementPrototype>("HTMLTextAreaElement")); } HTMLTimeElement::~HTMLTimeElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h index 762b495a8e..494f42d1af 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTimeElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTimeElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTimeElementWrapper; + virtual ~HTMLTimeElement() override; +private: HTMLTimeElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTimeElement() override; }; } + +WRAPPER_HACK(HTMLTimeElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.cpp index 0942f0d6d1..e556863278 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 <LibWeb/Bindings/HTMLTitleElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLTitleElement.h> #include <LibWeb/Page/Page.h> @@ -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<Bindings::HTMLTitleElementPrototype>("HTMLTitleElement")); } HTMLTitleElement::~HTMLTitleElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTitleElement.h index 564401792b..7b4bc13750 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 944dbdbb09..eadfacaf69 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 <LibWeb/Bindings/HTMLTrackElementPrototype.h> #include <LibWeb/HTML/HTMLTrackElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLTrackElement::HTMLTrackElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLTrackElementPrototype>("HTMLTrackElement")); } HTMLTrackElement::~HTMLTrackElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h index 2996f6a120..f3655e2dfe 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLTrackElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLTrackElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLTrackElementWrapper; + virtual ~HTMLTrackElement() override; +private: HTMLTrackElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLTrackElement() override; }; } + +WRAPPER_HACK(HTMLTrackElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.cpp index 80c68a724f..71eb3820a9 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 <LibWeb/Bindings/HTMLUListElementPrototype.h> #include <LibWeb/HTML/HTMLUListElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLUListElement::HTMLUListElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLUListElementPrototype>("HTMLUListElement")); } HTMLUListElement::~HTMLUListElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h index d2838c7576..fa7f609bd0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLUListElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLUListElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLUListElementWrapper; + virtual ~HTMLUListElement() override; +private: HTMLUListElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLUListElement() override; }; } + +WRAPPER_HACK(HTMLUListElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.cpp index 1274e0a9bf..b5df91ad7d 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 <LibWeb/Bindings/HTMLUnknownElementPrototype.h> #include <LibWeb/HTML/HTMLUnknownElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLUnknownElement::HTMLUnknownElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLUnknownElementPrototype>("HTMLUnknownElement")); } HTMLUnknownElement::~HTMLUnknownElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h index 6d36dbbc1d..dc5e518a03 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLUnknownElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLUnknownElement final : public HTMLElement { + WEB_PLATFORM_OBJECT(HTMLUnknownElement, HTMLElement); + public: - using WrapperType = Bindings::HTMLUnknownElementWrapper; + virtual ~HTMLUnknownElement() override; +private: HTMLUnknownElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLUnknownElement() override; }; } + +WRAPPER_HACK(HTMLUnknownElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.cpp index eb34e7c8c0..76b3941e27 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 <LibWeb/Bindings/HTMLVideoElementPrototype.h> #include <LibWeb/HTML/HTMLVideoElement.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { HTMLVideoElement::HTMLVideoElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLMediaElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::HTMLVideoElementPrototype>("HTMLVideoElement")); } HTMLVideoElement::~HTMLVideoElement() = default; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h index de4e292113..e16de819c3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h @@ -11,11 +11,15 @@ namespace Web::HTML { class HTMLVideoElement final : public HTMLMediaElement { + WEB_PLATFORM_OBJECT(HTMLVideoElement, HTMLMediaElement); + public: - using WrapperType = Bindings::HTMLVideoElementWrapper; + virtual ~HTMLVideoElement() override; +private: HTMLVideoElement(DOM::Document&, DOM::QualifiedName); - virtual ~HTMLVideoElement() override; }; } + +WRAPPER_HACK(HTMLVideoElement, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp b/Userland/Libraries/LibWeb/HTML/MessageChannel.cpp index cb877324f9..8c74020b78 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 1d212db933..7ac38e3912 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<MessageChannel> create_with_global_object(Bindings::WindowObject&) + static NonnullRefPtr<MessageChannel> 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<MessagePort> m_port1; - RefPtr<MessagePort> m_port2; + JS::Handle<MessagePort> m_port1; + JS::Handle<MessagePort> m_port2; }; } diff --git a/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp b/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp index 8fa050904d..b993d22a66 100644 --- a/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/MessageEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/MessageEvent.h> +#include <LibWeb/HTML/Window.h> 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<MessageEvent>(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 5671f8bd01..6d7d180d93 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 b6938d6909..9e4bb94101 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 <LibWeb/Bindings/MessagePortWrapper.h> +#include <LibWeb/Bindings/MessagePortPrototype.h> #include <LibWeb/DOM/EventDispatcher.h> #include <LibWeb/HTML/EventHandler.h> #include <LibWeb/HTML/EventLoop/EventLoop.h> @@ -14,13 +14,25 @@ namespace Web::HTML { -MessagePort::MessagePort() - : DOM::EventTarget() +JS::NonnullGCPtr<MessagePort> MessagePort::create(HTML::Window& window) { + return *window.heap().allocate<MessagePort>(window.realm(), window); +} + +MessagePort::MessagePort(HTML::Window& window) + : DOM::EventTarget(window.realm()) +{ + set_prototype(&window.ensure_web_prototype<Bindings::MessagePortPrototype>("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 = "<origin>"; - strong_port->dispatch_event(*MessageEvent::create(verify_cast<Bindings::WindowObject>(strong_port->wrapper()->global_object()), HTML::EventNames::message, event_init)); + strong_port->dispatch_event(*MessageEvent::create(verify_cast<HTML::Window>(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 3cebac0aa2..9380b6f9a5 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<MessagePort> - , public Weakable<MessagePort> - , public DOM::EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::MessagePortWrapper; - - using RefCounted::ref; - using RefCounted::unref; +class MessagePort final : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget); - static NonnullRefPtr<MessagePort> create() - { - return adopt_ref(*new MessagePort()); - } +public: + static JS::NonnullGCPtr<MessagePort> 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<MessagePort> m_remote_port; + JS::GCPtr<MessagePort> 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 95d1e6a922..450be24913 100644 --- a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/PageTransitionEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/PageTransitionEvent.h> +#include <LibWeb/HTML/Window.h> 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<PageTransitionEvent>(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 febd7ccb2b..ed5ece0f2d 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 9348c8ea7a..919070a595 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp @@ -96,7 +96,7 @@ Optional<StringView> extract_character_encoding_from_meta_element(String const& return TextCodec::get_standardized_encoding(encoding); } -RefPtr<DOM::Attribute> prescan_get_attribute(DOM::Document& document, ByteBuffer const& input, size_t& position) +JS::GCPtr<DOM::Attribute> 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<DOM::Attribute> 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 6cb9fc7e31..0bda305d16 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<StringView> extract_character_encoding_from_meta_element(String const&); -RefPtr<DOM::Attribute> prescan_get_attribute(DOM::Document&, ByteBuffer const& input, size_t& position); +JS::GCPtr<DOM::Attribute> prescan_get_attribute(DOM::Document&, ByteBuffer const& input, size_t& position); Optional<String> 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 ee78f35d5d..e37e78b684 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -9,6 +9,7 @@ #include <AK/SourceLocation.h> #include <AK/Utf32View.h> #include <LibTextCodec/Decoder.h> +#include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/DOM/Comment.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/DocumentType.h> @@ -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> window = document->window(); + JS::NonnullGCPtr<Window> 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<DOM::Comment>(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<DOM::DocumentType>(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<DOM::Comment>(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<DOM::Element> override_target) +HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_inserting_node(JS::GCPtr<DOM::Element> 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<HTMLTemplateElement>(last_template.element)->content(), nullptr }; + return { verify_cast<HTMLTemplateElement>(*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<HTMLTemplateElement>(*adjusted_insertion_location.parent)) - return { verify_cast<HTMLTemplateElement>(*adjusted_insertion_location.parent).content(), nullptr }; + return { verify_cast<HTMLTemplateElement>(*adjusted_insertion_location.parent).content().ptr(), nullptr }; return adjusted_insertion_location; } -NonnullRefPtr<DOM::Element> HTMLParser::create_element_for(HTMLToken const& token, FlyString const& namespace_, DOM::Node const& intended_parent) +JS::NonnullGCPtr<DOM::Element> 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<DOM::Document> document = intended_parent.document(); + JS::NonnullGCPtr<DOM::Document> 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<DOM::Element> 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<DOM::Element> 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<DOM::Element> HTMLParser::create_element_for(HTMLToken const& toke } // https://html.spec.whatwg.org/multipage/parsing.html#insert-a-foreign-element -NonnullRefPtr<DOM::Element> HTMLParser::insert_foreign_element(HTMLToken const& token, FlyString const& namespace_) +JS::NonnullGCPtr<DOM::Element> 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<DOM::Element> 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<DOM::Element> HTMLParser::insert_foreign_element(HTMLToken const& return element; } -NonnullRefPtr<DOM::Element> HTMLParser::insert_html_element(HTMLToken const& token) +JS::NonnullGCPtr<DOM::Element> 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<HTMLHeadElement>(*element); + m_head_element = JS::make_handle(verify_cast<HTMLHeadElement>(*element)); m_insertion_mode = InsertionMode::InHead; return; } @@ -712,7 +713,7 @@ void HTMLParser::handle_before_head(HTMLToken& token) } AnythingElse: - m_head_element = verify_cast<HTMLHeadElement>(*insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::head))); + m_head_element = JS::make_handle(verify_cast<HTMLHeadElement>(*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<DOM::Comment>(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<DOM::Text>(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<DOM::Text>(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<DOM::Comment>(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<DOM::Comment>(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<DOM::Element> furthest_block = m_stack_of_open_elements.topmost_special_node_below(*formatting_element); + JS::GCPtr<DOM::Element> 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<HTMLFormElement>(*element); + m_form_element = JS::make_handle(verify_cast<HTMLFormElement>(*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<DOM::Element> node = m_stack_of_open_elements.elements()[i]; + JS::GCPtr<DOM::Element> 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<DOM::Element> node = m_stack_of_open_elements.elements()[i]; + JS::GCPtr<DOM::Element> 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<DOM::Element> node; + JS::GCPtr<DOM::Element> 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 <script> element has up-to-date text content before preparing the script. flush_character_insertions(); - NonnullRefPtr<HTMLScriptElement> script = verify_cast<HTMLScriptElement>(current_node()); + JS::NonnullGCPtr<HTMLScriptElement> script = verify_cast<HTMLScriptElement>(current_node()); (void)m_stack_of_open_elements.pop(); m_insertion_mode = m_original_insertion_mode; @@ -2636,11 +2637,11 @@ void HTMLParser::handle_in_table(HTMLToken& token) } if (token.is_start_tag() && token.tag_name() == HTML::TagNames::form) { log_parse_error(); - 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_)) { return; } - m_form_element = verify_cast<HTMLFormElement>(*insert_html_element(token)); + m_form_element = JS::make_handle(verify_cast<HTMLFormElement>(*insert_html_element(token))); // FIXME: See previous FIXME, as this is the same situation but for form. (void)m_stack_of_open_elements.pop(); @@ -3103,8 +3104,8 @@ void HTMLParser::handle_after_frameset(HTMLToken& token) void HTMLParser::handle_after_after_frameset(HTMLToken& token) { if (token.is_comment()) { - auto comment = adopt_ref(*new DOM::Comment(document(), token.comment())); - document().append_child(move(comment)); + auto* comment = document().heap().allocate<DOM::Comment>(document().realm(), document(), token.comment()); + document().append_child(*comment); return; } @@ -3220,24 +3221,24 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token) } if (token.is_end_tag()) { - RefPtr<DOM::Element> node = current_node(); + JS::GCPtr<DOM::Element> node = current_node(); // FIXME: Not sure if this is the correct to_lowercase, as the specification says "to ASCII lowercase" if (node->tag_name().to_lowercase() != token.tag_name()) log_parse_error(); for (ssize_t i = m_stack_of_open_elements.elements().size() - 1; i >= 0; --i) { - if (node == m_stack_of_open_elements.first()) { + if (node.ptr() == &m_stack_of_open_elements.first()) { VERIFY(m_parsing_fragment); return; } // FIXME: See the above FIXME if (node->tag_name().to_lowercase() == token.tag_name()) { - while (current_node() != node) + while (¤t_node() != node.ptr()) (void)m_stack_of_open_elements.pop(); (void)m_stack_of_open_elements.pop(); return; } - node = m_stack_of_open_elements.elements().at(i - 1); + node = m_stack_of_open_elements.elements().at(i - 1).ptr(); if (node->namespace_() != Namespace::HTML) continue; @@ -3256,11 +3257,11 @@ void HTMLParser::reset_the_insertion_mode_appropriately() for (ssize_t i = m_stack_of_open_elements.elements().size() - 1; i >= 0; --i) { bool last = i == 0; // NOTE: When parsing fragments, we substitute the context element for the root of the stack of open elements. - RefPtr<DOM::Element> node; + JS::GCPtr<DOM::Element> node; if (last && m_parsing_fragment) { - node = m_context_element; + node = m_context_element.ptr(); } else { - node = m_stack_of_open_elements.elements().at(i); + node = m_stack_of_open_elements.elements().at(i).ptr(); } if (node->local_name() == HTML::TagNames::select) { @@ -3268,10 +3269,10 @@ void HTMLParser::reset_the_insertion_mode_appropriately() for (ssize_t j = i; j > 0; --j) { auto& ancestor = m_stack_of_open_elements.elements().at(j - 1); - if (is<HTMLTemplateElement>(ancestor)) + if (is<HTMLTemplateElement>(*ancestor)) break; - if (is<HTMLTableElement>(ancestor)) { + if (is<HTMLTableElement>(*ancestor)) { m_insertion_mode = InsertionMode::InSelectInTable; return; } @@ -3366,11 +3367,11 @@ DOM::Document& HTMLParser::document() return *m_document; } -NonnullRefPtrVector<DOM::Node> HTMLParser::parse_html_fragment(DOM::Element& context_element, StringView markup) +Vector<JS::Handle<DOM::Node>> HTMLParser::parse_html_fragment(DOM::Element& context_element, StringView markup) { - auto temp_document = DOM::Document::create(); + auto temp_document = DOM::Document::create(Bindings::main_thread_internal_window_object()); auto parser = HTMLParser::create(*temp_document, markup, "utf-8"); - parser->m_context_element = context_element; + parser->m_context_element = JS::make_handle(context_element); parser->m_parsing_fragment = true; parser->document().set_quirks_mode(context_element.document().mode()); @@ -3401,18 +3402,18 @@ NonnullRefPtrVector<DOM::Node> HTMLParser::parse_html_fragment(DOM::Element& con for (auto* form_candidate = &context_element; form_candidate; form_candidate = form_candidate->parent_element()) { if (is<HTMLFormElement>(*form_candidate)) { - parser->m_form_element = verify_cast<HTMLFormElement>(*form_candidate); + parser->m_form_element = JS::make_handle(verify_cast<HTMLFormElement>(*form_candidate)); break; } } parser->run(context_element.document().url()); - NonnullRefPtrVector<DOM::Node> children; - while (RefPtr<DOM::Node> child = root->first_child()) { + Vector<JS::Handle<DOM::Node>> children; + while (JS::GCPtr<DOM::Node> child = root->first_child()) { root->remove_child(*child); context_element.document().adopt_node(*child); - children.append(*child); + children.append(JS::make_handle(*child)); } return children; } @@ -3441,7 +3442,7 @@ String HTMLParser::serialize_html_fragment(DOM::Node const& node) { // The algorithm takes as input a DOM Element, Document, or DocumentFragment referred to as the node. VERIFY(node.is_element() || node.is_document() || node.is_document_fragment()); - NonnullRefPtr<DOM::Node> actual_node = node; + JS::NonnullGCPtr<DOM::Node> actual_node = node; if (is<DOM::Element>(node)) { auto& element = verify_cast<DOM::Element>(node); @@ -3745,4 +3746,9 @@ RefPtr<CSS::StyleValue> parse_nonzero_dimension_value(StringView string) return value; } +JS::Realm& HTMLParser::realm() +{ + return m_document->realm(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h index ba7fa4854e..6838972ba4 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h @@ -6,7 +6,6 @@ #pragma once -#include <AK/NonnullRefPtrVector.h> #include <LibWeb/DOM/Node.h> #include <LibWeb/HTML/Parser/HTMLTokenizer.h> #include <LibWeb/HTML/Parser/ListOfActiveFormattingElements.h> @@ -54,7 +53,7 @@ public: DOM::Document& document(); - static NonnullRefPtrVector<DOM::Node> parse_html_fragment(DOM::Element& context_element, StringView); + static Vector<JS::Handle<DOM::Node>> parse_html_fragment(DOM::Element& context_element, StringView); static String serialize_html_fragment(DOM::Node const& node); enum class InsertionMode { @@ -111,19 +110,19 @@ private: void generate_implied_end_tags(FlyString const& exception = {}); void generate_all_implied_end_tags_thoroughly(); - NonnullRefPtr<DOM::Element> create_element_for(HTMLToken const&, FlyString const& namespace_, DOM::Node const& intended_parent); + JS::NonnullGCPtr<DOM::Element> create_element_for(HTMLToken const&, FlyString const& namespace_, DOM::Node const& intended_parent); struct AdjustedInsertionLocation { - RefPtr<DOM::Node> parent; - RefPtr<DOM::Node> insert_before_sibling; + JS::GCPtr<DOM::Node> parent; + JS::GCPtr<DOM::Node> insert_before_sibling; }; - AdjustedInsertionLocation find_appropriate_place_for_inserting_node(RefPtr<DOM::Element> override_target = nullptr); + AdjustedInsertionLocation find_appropriate_place_for_inserting_node(JS::GCPtr<DOM::Element> override_target = nullptr); DOM::Text* find_character_insertion_node(); void flush_character_insertions(); - NonnullRefPtr<DOM::Element> insert_foreign_element(HTMLToken const&, FlyString const&); - NonnullRefPtr<DOM::Element> insert_html_element(HTMLToken const&); + JS::NonnullGCPtr<DOM::Element> insert_foreign_element(HTMLToken const&, FlyString const&); + JS::NonnullGCPtr<DOM::Element> insert_html_element(HTMLToken const&); DOM::Element& current_node(); DOM::Element& adjusted_current_node(); DOM::Element& node_before_current_node(); @@ -173,14 +172,16 @@ private: bool m_stop_parsing { false }; size_t m_script_nesting_level { 0 }; - NonnullRefPtr<DOM::Document> m_document; - RefPtr<HTMLHeadElement> m_head_element; - RefPtr<HTMLFormElement> m_form_element; - RefPtr<DOM::Element> m_context_element; + JS::Realm& realm(); + + JS::Handle<DOM::Document> m_document; + JS::Handle<HTMLHeadElement> m_head_element; + JS::Handle<HTMLFormElement> m_form_element; + JS::Handle<DOM::Element> m_context_element; Vector<HTMLToken> m_pending_table_character_tokens; - RefPtr<DOM::Text> m_character_insertion_node; + JS::Handle<DOM::Text> m_character_insertion_node; StringBuilder m_character_insertion_builder; }; diff --git a/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.cpp b/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.cpp index 1d2453aad6..e17a6abb48 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.cpp @@ -14,18 +14,18 @@ ListOfActiveFormattingElements::~ListOfActiveFormattingElements() = default; void ListOfActiveFormattingElements::add(DOM::Element& element) { // FIXME: Implement the Noah's Ark clause https://html.spec.whatwg.org/multipage/parsing.html#push-onto-the-list-of-active-formatting-elements - m_entries.append({ element }); + m_entries.append({ JS::make_handle(element) }); } void ListOfActiveFormattingElements::add_marker() { - m_entries.append({ nullptr }); + m_entries.append({ JS::make_handle<DOM::Element>(nullptr) }); } bool ListOfActiveFormattingElements::contains(const DOM::Element& element) const { for (auto& entry : m_entries) { - if (entry.element == &element) + if (entry.element.ptr() == &element) return true; } return false; @@ -38,7 +38,7 @@ DOM::Element* ListOfActiveFormattingElements::last_element_with_tag_name_before_ if (entry.is_marker()) return nullptr; if (entry.element->local_name() == tag_name) - return entry.element; + return entry.element.ptr(); } return nullptr; } @@ -46,7 +46,7 @@ DOM::Element* ListOfActiveFormattingElements::last_element_with_tag_name_before_ void ListOfActiveFormattingElements::remove(DOM::Element& element) { m_entries.remove_first_matching([&](auto& entry) { - return entry.element == &element; + return entry.element.ptr() == &element; }); } @@ -62,7 +62,7 @@ void ListOfActiveFormattingElements::clear_up_to_the_last_marker() Optional<size_t> ListOfActiveFormattingElements::find_index(DOM::Element const& element) const { for (size_t i = 0; i < m_entries.size(); i++) { - if (m_entries[i].element == element) + if (m_entries[i].element.ptr() == &element) return i; } return {}; @@ -71,14 +71,14 @@ Optional<size_t> ListOfActiveFormattingElements::find_index(DOM::Element const& void ListOfActiveFormattingElements::replace(DOM::Element& to_remove, DOM::Element& to_add) { for (size_t i = 0; i < m_entries.size(); i++) { - if (m_entries[i].element == to_remove) - m_entries[i].element = to_add; + if (m_entries[i].element.ptr() == &to_remove) + m_entries[i].element = JS::make_handle(to_add); } } void ListOfActiveFormattingElements::insert_at(size_t index, DOM::Element& element) { - m_entries.insert(index, { element }); + m_entries.insert(index, { JS::make_handle(element) }); } } diff --git a/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.h b/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.h index bf8293d1f5..167e93a347 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.h +++ b/Userland/Libraries/LibWeb/HTML/Parser/ListOfActiveFormattingElements.h @@ -20,7 +20,7 @@ public: struct Entry { bool is_marker() const { return !element; } - RefPtr<DOM::Element> element; + JS::Handle<DOM::Element> element; }; bool is_empty() const { return m_entries.is_empty(); } diff --git a/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.cpp b/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.cpp index e44c65264b..091eb8cdc7 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.cpp @@ -17,9 +17,9 @@ StackOfOpenElements::~StackOfOpenElements() = default; bool StackOfOpenElements::has_in_scope_impl(FlyString const& tag_name, Vector<FlyString> const& list) const { for (auto const& element : m_elements.in_reverse()) { - if (element.local_name() == tag_name) + if (element->local_name() == tag_name) return true; - if (list.contains_slow(element.local_name())) + if (list.contains_slow(element->local_name())) return false; } VERIFY_NOT_REACHED(); @@ -33,9 +33,9 @@ bool StackOfOpenElements::has_in_scope(FlyString const& tag_name) const bool StackOfOpenElements::has_in_scope_impl(const DOM::Element& target_node, Vector<FlyString> const& list) const { for (auto& element : m_elements.in_reverse()) { - if (&element == &target_node) + if (element.ptr() == &target_node) return true; - if (list.contains_slow(element.local_name())) + if (list.contains_slow(element->local_name())) return false; } VERIFY_NOT_REACHED(); @@ -78,11 +78,11 @@ bool StackOfOpenElements::has_in_select_scope(FlyString const& tag_name) const // 1. Initialize node to be the current node (the bottommost node of the stack). for (auto& node : m_elements.in_reverse()) { // 2. If node is the target node, terminate in a match state. - if (node.local_name() == tag_name) + if (node->local_name() == tag_name) return true; // 3. Otherwise, if node is one of the element types in list, terminate in a failure state. // NOTE: Here "list" refers to all elements except option and optgroup - if (node.local_name() != HTML::TagNames::option && node.local_name() != HTML::TagNames::optgroup) + if (node->local_name() != HTML::TagNames::option && node->local_name() != HTML::TagNames::optgroup) return false; // 4. Otherwise, set node to the previous entry in the stack of open elements and return to step 2. } @@ -94,7 +94,7 @@ bool StackOfOpenElements::has_in_select_scope(FlyString const& tag_name) const bool StackOfOpenElements::contains(const DOM::Element& element) const { for (auto& element_on_stack : m_elements) { - if (&element == &element_on_stack) + if (&element == element_on_stack.ptr()) return true; } return false; @@ -103,7 +103,7 @@ bool StackOfOpenElements::contains(const DOM::Element& element) const bool StackOfOpenElements::contains(FlyString const& tag_name) const { for (auto& element_on_stack : m_elements) { - if (element_on_stack.local_name() == tag_name) + if (element_on_stack->local_name() == tag_name) return true; } return false; @@ -111,68 +111,68 @@ bool StackOfOpenElements::contains(FlyString const& tag_name) const void StackOfOpenElements::pop_until_an_element_with_tag_name_has_been_popped(FlyString const& tag_name) { - while (m_elements.last().local_name() != tag_name) + while (m_elements.last()->local_name() != tag_name) (void)pop(); (void)pop(); } -DOM::Element* StackOfOpenElements::topmost_special_node_below(const DOM::Element& formatting_element) +JS::GCPtr<DOM::Element> StackOfOpenElements::topmost_special_node_below(DOM::Element const& formatting_element) { - DOM::Element* found_element = nullptr; + JS::GCPtr<DOM::Element> found_element = nullptr; for (auto& element : m_elements.in_reverse()) { - if (&element == &formatting_element) + if (element.ptr() == &formatting_element) break; - if (HTMLParser::is_special_tag(element.local_name(), element.namespace_())) - found_element = &element; + if (HTMLParser::is_special_tag(element->local_name(), element->namespace_())) + found_element = element.ptr(); } - return found_element; + return found_element.ptr(); } StackOfOpenElements::LastElementResult StackOfOpenElements::last_element_with_tag_name(FlyString const& tag_name) { for (ssize_t i = m_elements.size() - 1; i >= 0; --i) { auto& element = m_elements[i]; - if (element.local_name() == tag_name) - return { &element, i }; + if (element->local_name() == tag_name) + return { element.ptr(), i }; } return { nullptr, -1 }; } -DOM::Element* StackOfOpenElements::element_immediately_above(DOM::Element const& target) +JS::GCPtr<DOM::Element> StackOfOpenElements::element_immediately_above(DOM::Element const& target) { bool found_target = false; for (auto& element : m_elements.in_reverse()) { - if (&element == &target) { + if (element.ptr() == &target) { found_target = true; } else if (found_target) - return &element; + return element.ptr(); } return nullptr; } -void StackOfOpenElements::remove(const DOM::Element& element) +void StackOfOpenElements::remove(DOM::Element const& element) { - m_elements.remove_first_matching([&element](DOM::Element const& other) { - return &other == &element; + m_elements.remove_first_matching([&element](auto& other) { + return other.ptr() == &element; }); } -void StackOfOpenElements::replace(const DOM::Element& to_remove, NonnullRefPtr<DOM::Element> to_add) +void StackOfOpenElements::replace(DOM::Element const& to_remove, JS::NonnullGCPtr<DOM::Element> to_add) { for (size_t i = 0; i < m_elements.size(); i++) { - if (&m_elements[i] == &to_remove) { + if (m_elements[i].ptr() == &to_remove) { m_elements.remove(i); - m_elements.insert(i, move(to_add)); + m_elements.insert(i, JS::make_handle(*to_add)); break; } } } -void StackOfOpenElements::insert_immediately_below(NonnullRefPtr<DOM::Element> element_to_add, DOM::Element const& target) +void StackOfOpenElements::insert_immediately_below(JS::NonnullGCPtr<DOM::Element> element_to_add, DOM::Element const& target) { for (size_t i = 0; i < m_elements.size(); i++) { - if (&m_elements[i] == &target) { - m_elements.insert(i + 1, move(element_to_add)); + if (m_elements[i].ptr() == &target) { + m_elements.insert(i + 1, JS::make_handle(*element_to_add)); break; } } diff --git a/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.h b/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.h index 726d7018de..8cdf9fe527 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.h +++ b/Userland/Libraries/LibWeb/HTML/Parser/StackOfOpenElements.h @@ -23,18 +23,18 @@ public: StackOfOpenElements() = default; ~StackOfOpenElements(); - DOM::Element& first() { return m_elements.first(); } - DOM::Element& last() { return m_elements.last(); } + DOM::Element& first() { return *m_elements.first(); } + DOM::Element& last() { return *m_elements.last(); } bool is_empty() const { return m_elements.is_empty(); } - void push(NonnullRefPtr<DOM::Element> element) { m_elements.append(move(element)); } - NonnullRefPtr<DOM::Element> pop() { return m_elements.take_last(); } + void push(JS::NonnullGCPtr<DOM::Element> element) { m_elements.append(JS::make_handle(*element)); } + JS::NonnullGCPtr<DOM::Element> pop() { return *m_elements.take_last(); } void remove(DOM::Element const& element); - void replace(DOM::Element const& to_remove, NonnullRefPtr<DOM::Element> to_add); - void insert_immediately_below(NonnullRefPtr<DOM::Element> element_to_add, DOM::Element const& target); + void replace(DOM::Element const& to_remove, JS::NonnullGCPtr<DOM::Element> to_add); + void insert_immediately_below(JS::NonnullGCPtr<DOM::Element> element_to_add, DOM::Element const& target); - const DOM::Element& current_node() const { return m_elements.last(); } - DOM::Element& current_node() { return m_elements.last(); } + const DOM::Element& current_node() const { return *m_elements.last(); } + DOM::Element& current_node() { return *m_elements.last(); } bool has_in_scope(FlyString const& tag_name) const; bool has_in_button_scope(FlyString const& tag_name) const; @@ -47,25 +47,25 @@ public: bool contains(const DOM::Element&) const; bool contains(FlyString const& tag_name) const; - NonnullRefPtrVector<DOM::Element> const& elements() const { return m_elements; } - NonnullRefPtrVector<DOM::Element>& elements() { return m_elements; } + Vector<JS::Handle<DOM::Element>> const& elements() const { return m_elements; } + Vector<JS::Handle<DOM::Element>>& elements() { return m_elements; } void pop_until_an_element_with_tag_name_has_been_popped(FlyString const&); - DOM::Element* topmost_special_node_below(const DOM::Element&); + JS::GCPtr<DOM::Element> topmost_special_node_below(DOM::Element const&); struct LastElementResult { - DOM::Element* element; + JS::GCPtr<DOM::Element> element; ssize_t index; }; LastElementResult last_element_with_tag_name(FlyString const&); - DOM::Element* element_immediately_above(DOM::Element const&); + JS::GCPtr<DOM::Element> element_immediately_above(DOM::Element const&); private: bool has_in_scope_impl(FlyString const& tag_name, Vector<FlyString> const&) const; bool has_in_scope_impl(const DOM::Element& target_node, Vector<FlyString> const&) const; - NonnullRefPtrVector<DOM::Element> m_elements; + Vector<JS::Handle<DOM::Element>> m_elements; }; } diff --git a/Userland/Libraries/LibWeb/HTML/Path2D.h b/Userland/Libraries/LibWeb/HTML/Path2D.h index 8f58a4589a..92d7a4a3c6 100644 --- a/Userland/Libraries/LibWeb/HTML/Path2D.h +++ b/Userland/Libraries/LibWeb/HTML/Path2D.h @@ -25,7 +25,7 @@ class Path2D public: using WrapperType = Bindings::Path2DWrapper; - static NonnullRefPtr<Path2D> create_with_global_object(Bindings::WindowObject&, Optional<Variant<NonnullRefPtr<Path2D>, String>> const& path) { return adopt_ref(*new Path2D(path)); } + static NonnullRefPtr<Path2D> create_with_global_object(HTML::Window&, Optional<Variant<NonnullRefPtr<Path2D>, String>> const& path) { return adopt_ref(*new Path2D(path)); } static NonnullRefPtr<Path2D> create(Optional<Variant<NonnullRefPtr<Path2D>, String>> const& path) { return adopt_ref(*new Path2D(path)); } ~Path2D() = default; diff --git a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp index 13b6099763..a7b246fa06 100644 --- a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/PromiseRejectionEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/PromiseRejectionEvent.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { -PromiseRejectionEvent* PromiseRejectionEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init) +PromiseRejectionEvent* PromiseRejectionEvent::create(HTML::Window& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init) { return window_object.heap().allocate<PromiseRejectionEvent>(window_object.realm(), window_object, event_name, event_init); } -PromiseRejectionEvent* PromiseRejectionEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init) +PromiseRejectionEvent* PromiseRejectionEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init) { return create(window_object, event_name, event_init); } -PromiseRejectionEvent::PromiseRejectionEvent(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init) +PromiseRejectionEvent::PromiseRejectionEvent(HTML::Window& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init) : DOM::Event(window_object, event_name, event_init) , m_promise(const_cast<JS::Promise*>(event_init.promise.cell())) , m_reason(event_init.reason) diff --git a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h index 1571127881..2443a6c6b7 100644 --- a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h +++ b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h @@ -19,18 +19,16 @@ struct PromiseRejectionEventInit : public DOM::EventInit { }; class PromiseRejectionEvent final : public DOM::Event { - JS_OBJECT(PromiseRejectionEvent, DOM::Event); + WEB_PLATFORM_OBJECT(PromiseRejectionEvent, DOM::Event); public: - static PromiseRejectionEvent* create(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init = {}); - static PromiseRejectionEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init); + static PromiseRejectionEvent* create(HTML::Window&, FlyString const& event_name, PromiseRejectionEventInit const& event_init = {}); + static PromiseRejectionEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, PromiseRejectionEventInit const& event_init); - PromiseRejectionEvent(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init); + PromiseRejectionEvent(HTML::Window&, FlyString const& event_name, PromiseRejectionEventInit const& event_init); virtual ~PromiseRejectionEvent() override; - PromiseRejectionEvent& impl() { return *this; } - // Needs to return a pointer for the generated JS bindings to work. JS::Promise const* promise() const { return m_promise; } JS::Value reason() const { return m_reason; } diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp index 150746aff1..eea9c37b95 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp @@ -6,7 +6,6 @@ */ #include <LibWeb/Bindings/MainThreadVM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/PromiseRejectionEvent.h> #include <LibWeb/HTML/Scripting/Environments.h> @@ -67,7 +66,7 @@ EventLoop& EnvironmentSettingsObject::responsible_event_loop() RunScriptDecision EnvironmentSettingsObject::can_run_script() { // 1. If the global object specified by settings is a Window object whose Document object is not fully active, then return "do not run". - if (is<Bindings::WindowObject>(global_object()) && !verify_cast<Bindings::WindowObject>(global_object()).impl().associated_document().is_fully_active()) + if (is<HTML::Window>(global_object()) && !verify_cast<HTML::Window>(global_object()).associated_document().is_fully_active()) return RunScriptDecision::DoNotRun; // 2. If scripting is disabled for settings, then return "do not run". @@ -218,11 +217,11 @@ void EnvironmentSettingsObject::notify_about_rejected_promises(Badge<EventLoop>) /* .reason = */ promise.result(), }; // FIXME: This currently assumes that global is a WindowObject. - auto& window = verify_cast<Bindings::WindowObject>(*global.cell()); + auto& window = verify_cast<HTML::Window>(*global.cell()); auto promise_rejection_event = PromiseRejectionEvent::create(window, HTML::EventNames::unhandledrejection, event_init); - bool not_handled = window.impl().dispatch_event(*promise_rejection_event); + bool not_handled = window.dispatch_event(*promise_rejection_event); // 3. If notHandled is false, then the promise rejection is handled. Otherwise, the promise rejection is not handled. diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h index ae95542d27..b8a0dd4f7e 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h @@ -62,7 +62,7 @@ struct EnvironmentSettingsObject // FIXME: A module map https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-module-map // https://html.spec.whatwg.org/multipage/webappapis.html#responsible-document - virtual RefPtr<DOM::Document> responsible_document() = 0; + virtual JS::GCPtr<DOM::Document> responsible_document() = 0; // https://html.spec.whatwg.org/multipage/webappapis.html#api-url-character-encoding virtual String api_url_character_encoding() = 0; diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp index e5b6c8e636..b38b9c409e 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp +++ b/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp @@ -4,15 +4,15 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { WindowEnvironmentSettingsObject::WindowEnvironmentSettingsObject(Window& window, NonnullOwnPtr<JS::ExecutionContext> execution_context) : EnvironmentSettingsObject(move(execution_context)) - , m_window(window) + , m_window(JS::make_handle(window)) { } @@ -25,7 +25,7 @@ void WindowEnvironmentSettingsObject::setup(AK::URL const& creation_url, Nonnull // 2. Let window be realm's global object. // NOTE: We want to store the Window impl rather than the WindowObject. - auto& window = verify_cast<Bindings::WindowObject>(realm->global_object()).impl(); + auto& window = verify_cast<HTML::Window>(realm->global_object()).impl(); // 3. Let settings object be a new environment settings object whose algorithms are defined as follows: // NOTE: See the functions defined for this class. @@ -61,7 +61,7 @@ void WindowEnvironmentSettingsObject::setup(AK::URL const& creation_url, Nonnull } // https://html.spec.whatwg.org/multipage/window-object.html#script-settings-for-window-objects:responsible-document -RefPtr<DOM::Document> WindowEnvironmentSettingsObject::responsible_document() +JS::GCPtr<DOM::Document> WindowEnvironmentSettingsObject::responsible_document() { // Return window's associated Document. return m_window->associated_document(); diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h b/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h index f15a2397e1..d14300b84c 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h +++ b/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h @@ -17,7 +17,7 @@ public: virtual ~WindowEnvironmentSettingsObject() override = default; - virtual RefPtr<DOM::Document> responsible_document() override; + virtual JS::GCPtr<DOM::Document> responsible_document() override; virtual String api_url_character_encoding() override; virtual AK::URL api_base_url() override; virtual Origin origin() override; @@ -26,7 +26,7 @@ public: private: WindowEnvironmentSettingsObject(Window&, NonnullOwnPtr<JS::ExecutionContext>); - NonnullRefPtr<Window> m_window; + JS::Handle<Window> m_window; }; } diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/WorkerEnvironmentSettingsObject.h b/Userland/Libraries/LibWeb/HTML/Scripting/WorkerEnvironmentSettingsObject.h index e4ea62459a..0a39f64eaf 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/WorkerEnvironmentSettingsObject.h +++ b/Userland/Libraries/LibWeb/HTML/Scripting/WorkerEnvironmentSettingsObject.h @@ -20,7 +20,7 @@ class WorkerEnvironmentSettingsObject final public: WorkerEnvironmentSettingsObject(DOM::Document& document, NonnullOwnPtr<JS::ExecutionContext> execution_context) : EnvironmentSettingsObject(move(execution_context)) - , m_document(document) + , m_document(JS::make_handle(document)) { } @@ -37,14 +37,14 @@ public: virtual ~WorkerEnvironmentSettingsObject() override = default; - RefPtr<DOM::Document> responsible_document() override { return m_document; } + JS::GCPtr<DOM::Document> responsible_document() override { return m_document.ptr(); } String api_url_character_encoding() override { return m_document->encoding_or_default(); } AK::URL api_base_url() override { return m_document->url(); } Origin origin() override { return m_document->origin(); } CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() override { TODO(); } private: - NonnullRefPtr<DOM::Document> m_document; + JS::Handle<DOM::Document> m_document; }; } diff --git a/Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp b/Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp index c7dce0f599..2aa2c2650a 100644 --- a/Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/SubmitEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/SubmitEvent.h> +#include <LibWeb/HTML/Window.h> namespace Web::HTML { -SubmitEvent* SubmitEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init) +SubmitEvent* SubmitEvent::create(HTML::Window& window_object, FlyString const& event_name, SubmitEventInit const& event_init) { return window_object.heap().allocate<SubmitEvent>(window_object.realm(), window_object, event_name, event_init); } -SubmitEvent* SubmitEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init) +SubmitEvent* SubmitEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, SubmitEventInit const& event_init) { return create(window_object, event_name, event_init); } -SubmitEvent::SubmitEvent(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init) +SubmitEvent::SubmitEvent(HTML::Window& window_object, FlyString const& event_name, SubmitEventInit const& event_init) : DOM::Event(window_object, event_name, event_init) , m_submitter(event_init.submitter) { @@ -29,4 +29,10 @@ SubmitEvent::SubmitEvent(Bindings::WindowObject& window_object, FlyString const& SubmitEvent::~SubmitEvent() = default; +void SubmitEvent::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_submitter.ptr()); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/SubmitEvent.h b/Userland/Libraries/LibWeb/HTML/SubmitEvent.h index e3fdd37662..9e484d54ce 100644 --- a/Userland/Libraries/LibWeb/HTML/SubmitEvent.h +++ b/Userland/Libraries/LibWeb/HTML/SubmitEvent.h @@ -6,33 +6,32 @@ #pragma once -#include <LibWeb/Bindings/HTMLElementWrapper.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { struct SubmitEventInit : public DOM::EventInit { - RefPtr<HTMLElement> submitter { nullptr }; + JS::GCPtr<HTMLElement> submitter; }; class SubmitEvent final : public DOM::Event { - JS_OBJECT(SubmitEvent, DOM::Event); + WEB_PLATFORM_OBJECT(SubmitEvent, DOM::Event); public: - static SubmitEvent* create(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init); - static SubmitEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init); + static SubmitEvent* create(HTML::Window&, FlyString const& event_name, SubmitEventInit const& event_init); + static SubmitEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, SubmitEventInit const& event_init); virtual ~SubmitEvent() override; - SubmitEvent(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init); + SubmitEvent(HTML::Window&, FlyString const& event_name, SubmitEventInit const& event_init); - SubmitEvent& impl() { return *this; } - - RefPtr<HTMLElement> submitter() const { return m_submitter; } + JS::GCPtr<HTMLElement> submitter() const { return m_submitter; } private: - RefPtr<HTMLElement> m_submitter; + virtual void visit_edges(Cell::Visitor&) override; + + JS::GCPtr<HTMLElement> m_submitter; }; } diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 7c8227bf71..fd8b068f32 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -5,10 +5,32 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/Base64.h> +#include <AK/String.h> +#include <AK/Utf8View.h> #include <LibJS/Runtime/AbstractOperations.h> +#include <LibJS/Runtime/Completion.h> +#include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/FunctionObject.h> +#include <LibJS/Runtime/Shape.h> +#include <LibTextCodec/Decoder.h> +#include <LibWeb/Bindings/CSSNamespace.h> +#include <LibWeb/Bindings/CryptoWrapper.h> +#include <LibWeb/Bindings/EventTargetConstructor.h> +#include <LibWeb/Bindings/EventTargetPrototype.h> +#include <LibWeb/Bindings/ExceptionOrUtils.h> +#include <LibWeb/Bindings/HistoryWrapper.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> #include <LibWeb/Bindings/IdleDeadlineWrapper.h> +#include <LibWeb/Bindings/LocationObject.h> +#include <LibWeb/Bindings/NavigatorObject.h> +#include <LibWeb/Bindings/Replaceable.h> +#include <LibWeb/Bindings/ScreenWrapper.h> +#include <LibWeb/Bindings/SelectionWrapper.h> +#include <LibWeb/Bindings/StorageWrapper.h> +#include <LibWeb/Bindings/WindowObjectHelper.h> +#include <LibWeb/Bindings/WindowPrototype.h> +#include <LibWeb/CSS/MediaQueryList.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h> #include <LibWeb/Crypto/Crypto.h> @@ -16,10 +38,13 @@ #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/EventDispatcher.h> #include <LibWeb/HTML/BrowsingContext.h> +#include <LibWeb/HTML/EventHandler.h> #include <LibWeb/HTML/EventLoop/EventLoop.h> #include <LibWeb/HTML/MessageEvent.h> +#include <LibWeb/HTML/Origin.h> #include <LibWeb/HTML/PageTransitionEvent.h> #include <LibWeb/HTML/Scripting/ClassicScript.h> +#include <LibWeb/HTML/Scripting/Environments.h> #include <LibWeb/HTML/Scripting/ExceptionReporter.h> #include <LibWeb/HTML/Storage.h> #include <LibWeb/HTML/Timer.h> @@ -29,6 +54,7 @@ #include <LibWeb/Page/Page.h> #include <LibWeb/RequestIdleCallback/IdleDeadline.h> #include <LibWeb/Selection/Selection.h> +#include <LibWeb/WebAssembly/WebAssemblyObject.h> namespace Web::HTML { @@ -56,54 +82,68 @@ private: u32 m_handle { 0 }; }; -NonnullRefPtr<Window> Window::create() +JS::NonnullGCPtr<Window> Window::create(JS::Realm& realm) { - return adopt_ref(*new Window); + return *realm.heap().allocate<Window>(realm, realm); } -NonnullRefPtr<Window> Window::create_with_document(DOM::Document& document) +JS::NonnullGCPtr<Window> Window::create_with_document(DOM::Document& document) { - return adopt_ref(*new Window(document)); + return *document.heap().allocate<Window>(document.shape().realm(), document); } -Window::Window() - : DOM::EventTarget() - , m_performance(make<HighResolutionTime::Performance>(*this)) +Window::Window(JS::Realm& realm) + : DOM::EventTarget(realm) , m_crypto(Crypto::Crypto::create()) , m_screen(CSS::Screen::create({}, *this)) { + // FIXME: Should this be WindowPrototype? } Window::Window(DOM::Document& document) - : DOM::EventTarget() + : DOM::EventTarget(document.shape().realm()) , m_associated_document(document) - , m_performance(make<HighResolutionTime::Performance>(*this)) , m_crypto(Crypto::Crypto::create()) , m_screen(CSS::Screen::create({}, *this)) { } +void Window::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_associated_document.ptr()); + visitor.visit(m_current_event.ptr()); + visitor.visit(m_performance.ptr()); + visitor.visit(m_location_object); + for (auto& it : m_prototypes) + visitor.visit(it.value); + for (auto& it : m_constructors) + visitor.visit(it.value); +} + Window::~Window() = default; -void Window::set_wrapper(Badge<Bindings::WindowObject>, Bindings::WindowObject& wrapper) +HighResolutionTime::Performance& Window::performance() { - m_wrapper = wrapper.make_weak_ptr(); + if (!m_performance) + m_performance = heap().allocate<HighResolutionTime::Performance>(realm(), *this); + return *m_performance; } -void Window::alert(String const& message) +void Window::alert_impl(String const& message) { if (auto* page = this->page()) page->client().page_did_request_alert(message); } -bool Window::confirm(String const& message) +bool Window::confirm_impl(String const& message) { if (auto* page = this->page()) return page->client().page_did_request_confirm(message); return false; } -String Window::prompt(String const& message, String const& default_) +String Window::prompt_impl(String const& message, String const& default_) { if (auto* page = this->page()) return page->client().page_did_request_prompt(message, default_); @@ -111,25 +151,25 @@ String Window::prompt(String const& message, String const& default_) } // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout -i32 Window::set_timeout(Bindings::TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments) +i32 Window::set_timeout_impl(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments) { return run_timer_initialization_steps(move(handler), timeout, move(arguments), Repeat::No); } // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval -i32 Window::set_interval(Bindings::TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments) +i32 Window::set_interval_impl(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments) { return run_timer_initialization_steps(move(handler), timeout, move(arguments), Repeat::Yes); } // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-cleartimeout -void Window::clear_timeout(i32 id) +void Window::clear_timeout_impl(i32 id) { m_timers.remove(id); } // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-clearinterval -void Window::clear_interval(i32 id) +void Window::clear_interval_impl(i32 id) { m_timers.remove(id); } @@ -140,7 +180,7 @@ void Window::deallocate_timer_id(Badge<Timer>, i32 id) } // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps -i32 Window::run_timer_initialization_steps(Bindings::TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id) +i32 Window::run_timer_initialization_steps(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id) { // 1. Let thisArg be global if that is a WorkerGlobalScope object; otherwise let thisArg be the WindowProxy that corresponds to global. @@ -162,8 +202,8 @@ i32 Window::run_timer_initialization_steps(Bindings::TimerHandler handler, i32 t // 8. Assert: initiating script is not null, since this algorithm is always called from some script. // 9. Let task be a task that runs the following substeps: - auto task = [weak_window = make_weak_ptr(), handler = move(handler), timeout, arguments = move(arguments), repeat, id]() mutable { - auto window = weak_window.strong_ref(); + auto task = [weak_window = make_weak_ptr<Window>(), handler = move(handler), timeout, arguments = move(arguments), repeat, id]() mutable { + JS::GCPtr<Window> window = weak_window.ptr(); if (!window) return; @@ -174,7 +214,7 @@ i32 Window::run_timer_initialization_steps(Bindings::TimerHandler handler, i32 t handler.visit( // 2. If handler is a Function, then invoke handler given arguments with the callback this value set to thisArg. If this throws an exception, catch it, and report the exception. [&](JS::Handle<Bindings::CallbackType> callback) { - if (auto result = Bindings::IDL::invoke_callback(*callback, window->wrapper(), arguments); result.is_error()) + if (auto result = Bindings::IDL::invoke_callback(*callback, window.ptr(), arguments); result.is_error()) HTML::report_exception(result); }, // 3. Otherwise: @@ -219,12 +259,12 @@ i32 Window::run_timer_initialization_steps(Bindings::TimerHandler handler, i32 t // FIXME: 11. Set task's timer nesting level to nesting level. // 12. Let completionStep be an algorithm step which queues a global task on the timer task source given global to run task. - auto completion_step = [weak_window = make_weak_ptr(), task = move(task)]() mutable { - auto window = weak_window.strong_ref(); + auto completion_step = [weak_window = make_weak_ptr<Window>(), task = move(task)]() mutable { + JS::GCPtr<Window> window = weak_window.ptr(); if (!window) return; - HTML::queue_global_task(HTML::Task::Source::TimerTask, *window->wrapper(), move(task)); + HTML::queue_global_task(HTML::Task::Source::TimerTask, *window, move(task)); }; // 13. Run steps after a timeout given global, "setTimeout/setInterval", timeout, completionStep, and id. @@ -237,7 +277,7 @@ i32 Window::run_timer_initialization_steps(Bindings::TimerHandler handler, i32 t } // https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#run-the-animation-frame-callbacks -i32 Window::request_animation_frame(Bindings::CallbackType& js_callback) +i32 Window::request_animation_frame_impl(Bindings::CallbackType& js_callback) { return m_animation_frame_callback_driver.add([this, js_callback = JS::make_handle(js_callback)](auto) mutable { // 3. Invoke callback, passing now as the only argument, @@ -249,7 +289,7 @@ i32 Window::request_animation_frame(Bindings::CallbackType& js_callback) }); } -void Window::cancel_animation_frame(i32 id) +void Window::cancel_animation_frame_impl(i32 id) { m_animation_frame_callback_driver.remove(id); } @@ -284,11 +324,6 @@ bool Window::dispatch_event(DOM::Event& event) return DOM::EventDispatcher::dispatch(*this, event, true); } -JS::Object* Window::create_wrapper(JS::Realm& realm) -{ - return &realm.global_object(); -} - // https://www.w3.org/TR/cssom-view-1/#dom-window-innerwidth int Window::inner_width() const { @@ -319,15 +354,15 @@ Page const* Window::page() const return associated_document().page(); } -CSS::CSSStyleDeclaration* Window::get_computed_style(DOM::Element& element) const +CSS::CSSStyleDeclaration* Window::get_computed_style_impl(DOM::Element& element) const { return CSS::ResolvedCSSStyleDeclaration::create(element); } -NonnullRefPtr<CSS::MediaQueryList> Window::match_media(String media) +JS::NonnullGCPtr<CSS::MediaQueryList> Window::match_media_impl(String media) { auto media_query_list = CSS::MediaQueryList::create(associated_document(), parse_media_query_list(CSS::Parser::ParsingContext(associated_document()), media)); - associated_document().add_media_query_list(media_query_list); + associated_document().add_media_query_list(*media_query_list); return media_query_list; } @@ -458,7 +493,7 @@ void Window::fire_a_page_transition_event(FlyString const& event_name, bool pers // with the persisted attribute initialized to persisted, HTML::PageTransitionEventInit event_init {}; event_init.persisted = persisted; - auto event = HTML::PageTransitionEvent::create(associated_document().preferred_window_object(), event_name, event_init); + auto event = HTML::PageTransitionEvent::create(associated_document().window(), event_name, event_init); // ...the cancelable attribute initialized to true, event->set_cancelable(true); @@ -471,7 +506,7 @@ void Window::fire_a_page_transition_event(FlyString const& event_name, bool pers } // https://html.spec.whatwg.org/#dom-queuemicrotask -void Window::queue_microtask(Bindings::CallbackType& callback) +void Window::queue_microtask_impl(Bindings::CallbackType& callback) { // The queueMicrotask(callback) method must queue a microtask to invoke callback, HTML::queue_a_microtask(&associated_document(), [callback = JS::make_handle(callback)]() mutable { @@ -505,7 +540,7 @@ int Window::screen_y() const } // https://w3c.github.io/selection-api/#dom-window-getselection -Selection::Selection* Window::get_selection() +Selection::Selection* Window::get_selection_impl() { // FIXME: Implement. return nullptr; @@ -559,17 +594,15 @@ Window* Window::parent() } // https://html.spec.whatwg.org/multipage/web-messaging.html#window-post-message-steps -DOM::ExceptionOr<void> Window::post_message(JS::Value message, String const&) +DOM::ExceptionOr<void> Window::post_message_impl(JS::Value message, String const&) { // FIXME: This is an ad-hoc hack implementation instead, since we don't currently // have serialization and deserialization of messages. - HTML::queue_global_task(HTML::Task::Source::PostedMessage, *wrapper(), [strong_this = NonnullRefPtr(*this), message]() mutable { + HTML::queue_global_task(HTML::Task::Source::PostedMessage, *this, [strong_this = JS::make_handle(*this), message]() mutable { HTML::MessageEventInit event_init {}; event_init.data = message; event_init.origin = "<origin>"; - auto* wrapper = static_cast<Bindings::WindowObject*>(strong_this->wrapper()); - VERIFY(wrapper); - strong_this->dispatch_event(*HTML::MessageEvent::create(*wrapper, HTML::EventNames::message, event_init)); + strong_this->dispatch_event(*HTML::MessageEvent::create(*strong_this, HTML::EventNames::message, event_init)); }); return {}; } @@ -598,8 +631,7 @@ void Window::set_name(String const& name) void Window::start_an_idle_period() { // 1. Optionally, if the user agent determines the idle period should be delayed, return from this algorithm. - if (!wrapper()) - return; + // 2. Let pending_list be window's list of idle request callbacks. auto& pending_list = m_idle_request_callbacks; // 3. Let run_list be window's list of runnable idle callbacks. @@ -614,7 +646,7 @@ void Window::start_an_idle_period() // 5. Queue a task on the queue associated with the idle-task task source, // which performs the steps defined in the invoke idle callbacks algorithm with window and getDeadline as parameters. - HTML::queue_global_task(HTML::Task::Source::IdleTask, *wrapper(), [window = NonnullRefPtr(*this)]() mutable { + HTML::queue_global_task(HTML::Task::Source::IdleTask, *this, [window = JS::make_handle(*this)]() mutable { window->invoke_idle_callbacks(); }); } @@ -638,14 +670,14 @@ void Window::invoke_idle_callbacks() HTML::report_exception(result); // 4. If window's list of runnable idle callbacks is not empty, queue a task which performs the steps // in the invoke idle callbacks algorithm with getDeadline and window as a parameters and return from this algorithm - HTML::queue_global_task(HTML::Task::Source::IdleTask, *wrapper(), [window = NonnullRefPtr(*this)]() mutable { + HTML::queue_global_task(HTML::Task::Source::IdleTask, *this, [window = JS::make_handle(*this)]() mutable { window->invoke_idle_callbacks(); }); } } // https://w3c.github.io/requestidlecallback/#the-requestidlecallback-method -u32 Window::request_idle_callback(Bindings::CallbackType& callback) +u32 Window::request_idle_callback_impl(Bindings::CallbackType& callback) { // 1. Let window be this Window object. auto& window = *this; @@ -670,7 +702,7 @@ u32 Window::request_idle_callback(Bindings::CallbackType& callback) } // https://w3c.github.io/requestidlecallback/#the-cancelidlecallback-method -void Window::cancel_idle_callback(u32 handle) +void Window::cancel_idle_callback_impl(u32 handle) { // 1. Let window be this Window object. auto& window = *this; @@ -687,12 +719,728 @@ void Window::cancel_idle_callback(u32 handle) void Window::set_associated_document(DOM::Document& document) { - m_associated_document = document; + m_associated_document = &document; } void Window::set_current_event(DOM::Event* event) { - m_current_event = JS::make_handle(event); + m_current_event = event; +} + +HTML::BrowsingContext const* Window::browsing_context() const +{ + return m_associated_document->browsing_context(); +} + +HTML::BrowsingContext* Window::browsing_context() +{ + return m_associated_document->browsing_context(); +} + +void Window::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + + // FIXME: This is a hack.. + realm.set_global_object(this, this); + + ADD_WINDOW_OBJECT_INTERFACES; + + Object::set_prototype(&ensure_web_prototype<Bindings::WindowPrototype>("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<Bindings::CSSNamespace>(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<Bindings::LocationObject>(realm, realm); + + auto* m_navigator_object = heap().allocate<Bindings::NavigatorObject>(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<Bindings::WebAssemblyObject>(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 +} + +HTML::Origin Window::origin() const +{ + return impl().associated_document().origin(); +} + +// https://webidl.spec.whatwg.org/#platform-object-setprototypeof +JS::ThrowCompletionOr<bool> Window::internal_set_prototype_of(JS::Object* prototype) +{ + // 1. Return ? SetImmutablePrototype(O, V). + return set_immutable_prototype(prototype); +} + +static JS::ThrowCompletionOr<HTML::Window*> 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<Window>(*this_object)) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Window"); + return &static_cast<Window*>(this_object)->impl(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::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_impl(message); + return JS::js_undefined(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::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_impl(message)); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::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_impl(message, default_); + if (response.is_null()) + return JS::js_null(); + return JS::js_string(vm, response); +} + +static JS::ThrowCompletionOr<TimerHandler> make_timer_handler(JS::VM& vm, JS::Value handler) +{ + if (handler.is_function()) + return JS::make_handle(vm.heap().allocate_without_realm<Bindings::CallbackType>(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(Window::set_timeout) +{ + auto* impl = TRY(impl_from(vm)); + + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(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<JS::Value> arguments { vm.heap() }; + for (size_t i = 2; i < vm.argument_count(); ++i) + arguments.append(vm.argument(i)); + + auto id = impl->set_timeout_impl(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(Window::set_interval) +{ + auto* impl = TRY(impl_from(vm)); + + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(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<JS::Value> arguments { vm.heap() }; + for (size_t i = 2; i < vm.argument_count(); ++i) + arguments.append(vm.argument(i)); + + auto id = impl->set_interval_impl(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(Window::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_impl(id); + return JS::js_undefined(); +} + +// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-clearinterval +JS_DEFINE_NATIVE_FUNCTION(Window::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_impl(id); + return JS::js_undefined(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::request_animation_frame) +{ + auto* impl = TRY(impl_from(vm)); + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "requestAnimationFrame"); + auto* callback_object = TRY(vm.argument(0).to_object(vm)); + if (!callback_object->is_function()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); + auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*callback_object, HTML::incumbent_settings_object()); + return JS::Value(impl->request_animation_frame_impl(*callback)); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::cancel_animation_frame) +{ + auto* impl = TRY(impl_from(vm)); + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "cancelAnimationFrame"); + auto id = TRY(vm.argument(0).to_i32(vm)); + impl->cancel_animation_frame_impl(id); + return JS::js_undefined(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::queue_microtask) +{ + auto* impl = TRY(impl_from(vm)); + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountAtLeastOne, "queueMicrotask"); + auto* callback_object = TRY(vm.argument(0).to_object(vm)); + if (!callback_object->is_function()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); + + auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*callback_object, HTML::incumbent_settings_object()); + + impl->queue_microtask_impl(*callback); + return JS::js_undefined(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::request_idle_callback) +{ + auto* impl = TRY(impl_from(vm)); + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountAtLeastOne, "requestIdleCallback"); + auto* callback_object = TRY(vm.argument(0).to_object(vm)); + if (!callback_object->is_function()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); + // FIXME: accept options object + + auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*callback_object, HTML::incumbent_settings_object()); + + return JS::Value(impl->request_idle_callback_impl(*callback)); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::cancel_idle_callback) +{ + auto* impl = TRY(impl_from(vm)); + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "cancelIdleCallback"); + auto id = TRY(vm.argument(0).to_u32(vm)); + impl->cancel_idle_callback_impl(id); + return JS::js_undefined(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::atob) +{ + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(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::TypeError>(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(Window::btoa) +{ + if (!vm.argument_count()) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "btoa"); + auto string = TRY(vm.argument(0).to_string(vm)); + + Vector<u8> 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(Window::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; +} + +JS_DEFINE_NATIVE_FUNCTION(Window::parent_getter) +{ + auto* impl = TRY(impl_from(vm)); + auto* parent = impl->parent(); + if (!parent) + return JS::js_null(); + return parent; +} + +JS_DEFINE_NATIVE_FUNCTION(Window::document_getter) +{ + auto& realm = *vm.current_realm(); + auto* impl = TRY(impl_from(vm)); + return wrap(realm, impl->associated_document()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::performance_getter) +{ + auto& realm = *vm.current_realm(); + auto* impl = TRY(impl_from(vm)); + return wrap(realm, impl->performance()); } +JS_DEFINE_NATIVE_FUNCTION(Window::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::TypeError>(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). + TRY(impl->create_data_property("performance", vm.argument(0))); + + // 2. Return undefined. + return JS::js_undefined(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::screen_getter) +{ + auto& realm = *vm.current_realm(); + auto* impl = TRY(impl_from(vm)); + return wrap(realm, impl->screen()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::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<DOM::Event&>(*impl->current_event())); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::event_setter) +{ + REPLACEABLE_PROPERTY_SETTER(Window, event); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::location_getter) +{ + auto* impl = TRY(impl_from(vm)); + return impl->m_location_object; +} + +JS_DEFINE_NATIVE_FUNCTION(Window::location_setter) +{ + auto* impl = TRY(impl_from(vm)); + TRY(impl->m_location_object->set(JS::PropertyKey("href"), vm.argument(0), JS::Object::ShouldThrowExceptions::Yes)); + return JS::js_undefined(); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::crypto_getter) +{ + auto& realm = *vm.current_realm(); + auto* impl = TRY(impl_from(vm)); + return wrap(realm, impl->crypto()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::inner_width_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::Value(impl->inner_width()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::inner_height_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::Value(impl->inner_height()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::device_pixel_ratio_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::Value(impl->device_pixel_ratio()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::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<DOM::Element>(object)) + return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "DOM element"); + + return wrap(realm, *impl->get_computed_style_impl(*static_cast<DOM::Element*>(object))); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::get_selection) +{ + auto& realm = *vm.current_realm(); + auto* impl = TRY(impl_from(vm)); + auto* selection = impl->get_selection_impl(); + if (!selection) + return JS::js_null(); + return wrap(realm, *selection); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::match_media) +{ + auto* impl = TRY(impl_from(vm)); + auto media = TRY(vm.argument(0).to_string(vm)); + return impl->match_media_impl(move(media)); +} + +// https://www.w3.org/TR/cssom-view/#dom-window-scrollx +JS_DEFINE_NATIVE_FUNCTION(Window::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(Window::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(Window::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<JS::TypeError>("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(Window::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<JS::TypeError>("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(Window::history_getter) +{ + auto& realm = *vm.current_realm(); + auto* impl = TRY(impl_from(vm)); + return wrap(realm, impl->associated_document().history()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::screen_left_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::Value(impl->screen_x()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::screen_top_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::Value(impl->screen_y()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::screen_x_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::Value(impl->screen_x()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::screen_y_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::Value(impl->screen_y()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::post_message) +{ + auto* impl = TRY(impl_from(vm)); + auto target_origin = TRY(vm.argument(1).to_string(vm)); + impl->post_message_impl(vm.argument(0), target_origin); + return JS::js_undefined(); +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#dom-origin +JS_DEFINE_NATIVE_FUNCTION(Window::origin_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::js_string(vm, impl->associated_document().origin().serialize()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::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(Window::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(Window::name_getter) +{ + auto* impl = TRY(impl_from(vm)); + return JS::js_string(vm, impl->name()); +} + +JS_DEFINE_NATIVE_FUNCTION(Window::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(Window::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(Window::attribute##_setter) \ + { \ + auto* impl = TRY(impl_from(vm)); \ + auto value = vm.argument(0); \ + Bindings::CallbackType* cpp_value = nullptr; \ + if (value.is_object()) { \ + cpp_value = vm.heap().allocate_without_realm<Bindings::CallbackType>( \ + 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/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index a939846156..736bfdf5fd 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -8,18 +8,14 @@ #include <AK/Badge.h> #include <AK/IDAllocator.h> -#include <AK/RefCounted.h> #include <AK/RefPtr.h> -#include <AK/Weakable.h> -#include <LibWeb/Bindings/WindowObject.h> -#include <LibWeb/Bindings/Wrappable.h> -#include <LibWeb/CSS/MediaQueryList.h> +#include <AK/URL.h> +#include <LibJS/Heap/Heap.h> +#include <LibWeb/Bindings/CrossOriginAbstractOperations.h> #include <LibWeb/CSS/Screen.h> -#include <LibWeb/DOM/Document.h> -#include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/EventTarget.h> +#include <LibWeb/Forward.h> #include <LibWeb/HTML/AnimationFrameCallbackDriver.h> -#include <LibWeb/HTML/BrowsingContext.h> #include <LibWeb/HTML/GlobalEventHandlers.h> #include <LibWeb/HTML/WindowEventHandlers.h> @@ -27,24 +23,22 @@ namespace Web::HTML { class IdleCallback; +// https://html.spec.whatwg.org/#timerhandler +using TimerHandler = Variant<JS::Handle<Bindings::CallbackType>, String>; + class Window final - : public RefCounted<Window> - , public Weakable<Window> - , public DOM::EventTarget + : public DOM::EventTarget , public HTML::GlobalEventHandlers , public HTML::WindowEventHandlers { + WEB_PLATFORM_OBJECT(Window, DOM::EventTarget); + public: - static NonnullRefPtr<Window> create(); - static NonnullRefPtr<Window> create_with_document(DOM::Document&); - ~Window(); + static JS::NonnullGCPtr<Window> create(JS::Realm&); + static JS::NonnullGCPtr<Window> create_with_document(DOM::Document&); - using RefCounted::ref; - using RefCounted::unref; + ~Window(); - virtual void ref_event_target() override { RefCounted::ref(); } - virtual void unref_event_target() override { RefCounted::unref(); } virtual bool dispatch_event(DOM::Event&) override; - virtual JS::Object* create_wrapper(JS::Realm&) override; Page* page(); Page const* page() const; @@ -55,22 +49,22 @@ public: void set_associated_document(DOM::Document&); // https://html.spec.whatwg.org/multipage/window-object.html#window-bc - HTML::BrowsingContext const* browsing_context() const { return m_associated_document->browsing_context(); } - HTML::BrowsingContext* browsing_context() { return m_associated_document->browsing_context(); } - - void alert(String const&); - bool confirm(String const&); - String prompt(String const&, String const&); - i32 request_animation_frame(Bindings::CallbackType& js_callback); - void cancel_animation_frame(i32); + HTML::BrowsingContext const* browsing_context() const; + HTML::BrowsingContext* browsing_context(); + + void alert_impl(String const&); + bool confirm_impl(String const&); + String prompt_impl(String const&, String const&); + i32 request_animation_frame_impl(Bindings::CallbackType& js_callback); + void cancel_animation_frame_impl(i32); bool has_animation_frame_callbacks() const { return m_animation_frame_callback_driver.has_callbacks(); } - i32 set_timeout(Bindings::TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments); - i32 set_interval(Bindings::TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments); - void clear_timeout(i32); - void clear_interval(i32); + i32 set_timeout_impl(TimerHandler, i32 timeout, JS::MarkedVector<JS::Value> arguments); + i32 set_interval_impl(TimerHandler, i32 timeout, JS::MarkedVector<JS::Value> arguments); + void clear_timeout_impl(i32); + void clear_interval_impl(i32); - void queue_microtask(Bindings::CallbackType& callback); + void queue_microtask_impl(Bindings::CallbackType& callback); int inner_width() const; int inner_height() const; @@ -79,25 +73,20 @@ public: void did_call_location_reload(Badge<Bindings::LocationObject>); void did_call_location_replace(Badge<Bindings::LocationObject>, String url); - Bindings::WindowObject* wrapper() { return m_wrapper; } - Bindings::WindowObject const* wrapper() const { return m_wrapper; } - - void set_wrapper(Badge<Bindings::WindowObject>, Bindings::WindowObject&); - void deallocate_timer_id(Badge<Timer>, i32); - HighResolutionTime::Performance& performance() { return *m_performance; } + HighResolutionTime::Performance& performance(); Crypto::Crypto& crypto() { return *m_crypto; } CSS::Screen& screen() { return *m_screen; } - DOM::Event* current_event() { return m_current_event.cell(); } - DOM::Event const* current_event() const { return m_current_event.cell(); } + DOM::Event* current_event() { return m_current_event.ptr(); } + DOM::Event const* current_event() const { return m_current_event.ptr(); } void set_current_event(DOM::Event* event); - CSS::CSSStyleDeclaration* get_computed_style(DOM::Element&) const; - NonnullRefPtr<CSS::MediaQueryList> match_media(String); + CSS::CSSStyleDeclaration* get_computed_style_impl(DOM::Element&) const; + JS::NonnullGCPtr<CSS::MediaQueryList> match_media_impl(String); Optional<CSS::MediaFeatureValue> query_media_feature(CSS::MediaFeatureID) const; float scroll_x() const; @@ -110,28 +99,31 @@ public: int screen_x() const; int screen_y() const; - Selection::Selection* get_selection(); + Selection::Selection* get_selection_impl(); RefPtr<HTML::Storage> local_storage(); RefPtr<HTML::Storage> session_storage(); Window* parent(); - DOM::ExceptionOr<void> post_message(JS::Value, String const& target_origin); + DOM::ExceptionOr<void> post_message_impl(JS::Value, String const& target_origin); String name() const; void set_name(String const&); void start_an_idle_period(); - u32 request_idle_callback(Bindings::CallbackType& callback); - void cancel_idle_callback(u32); + u32 request_idle_callback_impl(Bindings::CallbackType& callback); + void cancel_idle_callback_impl(u32); AnimationFrameCallbackDriver& animation_frame_callback_driver() { return m_animation_frame_callback_driver; } private: - Window(); + explicit Window(JS::Realm&); explicit Window(DOM::Document&); + virtual void initialize(JS::Realm&) override; + + virtual void visit_edges(Cell::Visitor&) override; // ^HTML::GlobalEventHandlers virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const&) override { return *this; } @@ -143,22 +135,21 @@ private: Yes, No, }; - i32 run_timer_initialization_steps(Bindings::TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id = {}); + i32 run_timer_initialization_steps(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id = {}); void invoke_idle_callbacks(); // https://html.spec.whatwg.org/multipage/window-object.html#concept-document-window - WeakPtr<DOM::Document> m_associated_document; + JS::GCPtr<DOM::Document> m_associated_document; - WeakPtr<Bindings::WindowObject> m_wrapper; + JS::GCPtr<DOM::Event> m_current_event; IDAllocator m_timer_id_allocator; HashMap<int, NonnullRefPtr<Timer>> m_timers; - NonnullOwnPtr<HighResolutionTime::Performance> m_performance; + JS::GCPtr<HighResolutionTime::Performance> m_performance; NonnullRefPtr<Crypto::Crypto> m_crypto; NonnullOwnPtr<CSS::Screen> m_screen; - JS::Handle<DOM::Event> m_current_event; AnimationFrameCallbackDriver m_animation_frame_callback_driver; @@ -168,8 +159,130 @@ private: NonnullRefPtrVector<IdleCallback> m_runnable_idle_callbacks; // https://w3c.github.io/requestidlecallback/#dfn-idle-callback-identifier u32 m_idle_callback_identifier = 0; + +public: + HTML::Origin origin() const; + + Bindings::LocationObject* location_object() { return m_location_object; } + Bindings::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<typename T> + 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<T>(realm, realm); + m_prototypes.set(class_name, prototype); + return *prototype; + } + + template<typename T> + 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<T>(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<bool> internal_set_prototype_of(JS::Object* prototype) override; + + Bindings::CrossOriginPropertyDescriptorMap const& cross_origin_property_descriptor_map() const { return m_cross_origin_property_descriptor_map; } + Bindings::CrossOriginPropertyDescriptorMap& cross_origin_property_descriptor_map() { return m_cross_origin_property_descriptor_map; } + +private: + 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 + + Bindings::LocationObject* m_location_object { nullptr }; + + HashMap<String, JS::Object*> m_prototypes; + HashMap<String, JS::NativeFunction*> m_constructors; + + // [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap + Bindings::CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map; }; void run_animation_frame_callbacks(DOM::Document&, double now); } + +WRAPPER_HACK(Window, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/Worker.cpp b/Userland/Libraries/LibWeb/HTML/Worker.cpp index 438ec11308..ef6e1c66f9 100644 --- a/Userland/Libraries/LibWeb/HTML/Worker.cpp +++ b/Userland/Libraries/LibWeb/HTML/Worker.cpp @@ -8,7 +8,7 @@ #include <LibJS/Runtime/ConsoleObject.h> #include <LibJS/Runtime/Realm.h> #include <LibWeb/Bindings/MainThreadVM.h> -#include <LibWeb/Bindings/WorkerWrapper.h> +#include <LibWeb/Bindings/WorkerPrototype.h> #include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/HTML/Scripting/Environments.h> #include <LibWeb/HTML/Worker.h> @@ -18,19 +18,31 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface Worker::Worker(FlyString const& script_url, WorkerOptions const options, DOM::Document& document) - : m_script_url(script_url) + : DOM::EventTarget(document.realm()) + , m_script_url(script_url) , m_options(options) , m_document(&document) , m_custom_data() , m_worker_vm(JS::VM::create(adopt_own(m_custom_data))) , m_interpreter(JS::Interpreter::create<JS::GlobalObject>(m_worker_vm)) , m_interpreter_scope(*m_interpreter) - , m_implicit_port(MessagePort::create()) + , m_implicit_port(MessagePort::create(document.window())) { + set_prototype(&document.window().ensure_web_prototype<Bindings::WorkerPrototype>("Worker")); +} + +void Worker::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_document.ptr()); + visitor.visit(m_worker_realm.ptr()); + visitor.visit(m_worker_scope.ptr()); + visitor.visit(m_implicit_port.ptr()); + visitor.visit(m_outside_port.ptr()); } // https://html.spec.whatwg.org/multipage/workers.html#dom-worker -DOM::ExceptionOr<NonnullRefPtr<Worker>> Worker::create(FlyString const& script_url, WorkerOptions const options, DOM::Document& document) +DOM::ExceptionOr<JS::NonnullGCPtr<Worker>> Worker::create(FlyString const& script_url, WorkerOptions const options, DOM::Document& document) { dbgln_if(WEB_WORKER_DEBUG, "WebWorker: Creating worker with script_url = {}", script_url); @@ -60,20 +72,20 @@ DOM::ExceptionOr<NonnullRefPtr<Worker>> Worker::create(FlyString const& script_u // 5. Let worker URL be the resulting URL record. // 6. Let worker be a new Worker object. - auto worker = adopt_ref(*new Worker(script_url, options, document)); + auto worker = document.heap().allocate<Worker>(document.realm(), script_url, options, document); // 7. Let outside port be a new MessagePort in outside settings's Realm. - auto outside_port = MessagePort::create(); + auto outside_port = MessagePort::create(verify_cast<HTML::Window>(outside_settings.realm().global_object())); // 8. Associate the outside port with worker worker->m_outside_port = outside_port; // 9. Run this step in parallel: // 1. Run a worker given worker, worker URL, outside settings, outside port, and options. - worker->run_a_worker(url, outside_settings, outside_port, options); + worker->run_a_worker(url, outside_settings, *outside_port, options); // 10. Return worker - return worker; + return JS::NonnullGCPtr(*worker); } // https://html.spec.whatwg.org/multipage/workers.html#run-a-worker @@ -103,7 +115,7 @@ void Worker::run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_setti // 7. 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( *m_worker_vm, - [&](JS::Realm& realm) -> JS::GlobalObject* { + [&](JS::Realm& realm) -> JS::Object* { // 7a. For the global object, if is shared is true, create a new SharedWorkerGlobalScope object. // 7b. Otherwise, create a new DedicatedWorkerGlobalScope object. // FIXME: Proper support for both SharedWorkerGlobalScope and DedicatedWorkerGlobalScope @@ -112,7 +124,7 @@ void Worker::run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_setti // FIXME: Make and use subclasses of WorkerGlobalScope, however this requires JS::GlobalObject to // play nicely with the IDL interpreter, to make spec-compliant extensions, which it currently does not. m_worker_scope = m_worker_vm->heap().allocate_without_realm<JS::GlobalObject>(realm); - return m_worker_scope; + return m_worker_scope.ptr(); }, nullptr); @@ -148,8 +160,8 @@ void Worker::run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_setti MessageEventInit event_init {}; event_init.data = message; event_init.origin = "<origin>"; - // FIXME: The cast here is totally bogus, since workers don't have a WindowObject.. - dispatch_event(*MessageEvent::create(verify_cast<Bindings::WindowObject>(*m_worker_scope), HTML::EventNames::message, event_init)); + // FIXME: The cast here is totally bogus, since workers don't have a Window object.. + dispatch_event(*MessageEvent::create(verify_cast<HTML::Window>(*m_worker_scope), HTML::EventNames::message, event_init)); })); return JS::js_undefined(); @@ -246,7 +258,8 @@ void Worker::run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_setti // FIXME: Global scope association // 16. Let inside port be a new MessagePort object in inside settings's Realm. - auto inside_port = MessagePort::create(); + // FIXME: The cast here is totally bogus, since workers don't have a Window object.. + auto inside_port = MessagePort::create(verify_cast<HTML::Window>(*m_worker_scope)); // 17. Associate inside port with worker global scope. // FIXME: Global scope association @@ -319,11 +332,6 @@ void Worker::post_message(JS::Value message, JS::Value) target_port->post_message(message); } -JS::Object* Worker::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - #undef __ENUMERATE #define __ENUMERATE(attribute_name, event_name) \ void Worker::set_##attribute_name(Bindings::CallbackType* value) \ diff --git a/Userland/Libraries/LibWeb/HTML/Worker.h b/Userland/Libraries/LibWeb/HTML/Worker.h index eb7a56bf3f..833796d31c 100644 --- a/Userland/Libraries/LibWeb/HTML/Worker.h +++ b/Userland/Libraries/LibWeb/HTML/Worker.h @@ -32,19 +32,12 @@ struct WorkerOptions { }; // https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface -class Worker - : public RefCounted<Worker> - , public Weakable<Worker> - , public DOM::EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::WorkerWrapper; - - using RefCounted::ref; - using RefCounted::unref; +class Worker : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(Worker, DOM::EventTarget); - static DOM::ExceptionOr<NonnullRefPtr<Worker>> create(FlyString const& script_url, WorkerOptions const options, DOM::Document& document); - static DOM::ExceptionOr<NonnullRefPtr<Worker>> create_with_global_object(Bindings::WindowObject& window, FlyString const& script_url, WorkerOptions const options) +public: + static DOM::ExceptionOr<JS::NonnullGCPtr<Worker>> create(FlyString const& script_url, WorkerOptions const options, DOM::Document& document); + static DOM::ExceptionOr<JS::NonnullGCPtr<Worker>> create_with_global_object(HTML::Window& window, FlyString const& script_url, WorkerOptions const options) { return Worker::create(script_url, options, window.impl().associated_document()); } @@ -55,13 +48,8 @@ public: virtual ~Worker() = default; - // ^EventTarget - virtual void ref_event_target() override { ref(); } - virtual void unref_event_target() override { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; - - MessagePort* implicit_message_port() { return m_implicit_port; } - RefPtr<MessagePort> outside_message_port() { return m_outside_port; } + MessagePort* implicit_message_port() { return m_implicit_port.ptr(); } + JS::GCPtr<MessagePort> outside_message_port() { return m_outside_port; } #undef __ENUMERATE #define __ENUMERATE(attribute_name, event_name) \ @@ -79,29 +67,29 @@ private: return static_cast<Bindings::WebEngineCustomData*>(target_vm.custom_data())->event_loop; } + virtual void visit_edges(Cell::Visitor&) override; + FlyString m_script_url; WorkerOptions m_options; - WeakPtr<DOM::Document> m_document; + + JS::GCPtr<DOM::Document> m_document; + Bindings::WebEngineCustomData m_custom_data; NonnullRefPtr<JS::VM> m_worker_vm; NonnullOwnPtr<JS::Interpreter> m_interpreter; WeakPtr<WorkerEnvironmentSettingsObject> m_inner_settings; JS::VM::InterpreterExecutionScope m_interpreter_scope; - WeakPtr<JS::Realm> m_worker_realm; + JS::GCPtr<JS::Realm> m_worker_realm; RefPtr<WorkerDebugConsoleClient> m_console; - JS::GlobalObject* m_worker_scope; + JS::GCPtr<JS::Object> m_worker_scope; - NonnullRefPtr<MessagePort> m_implicit_port; - RefPtr<MessagePort> m_outside_port; + JS::NonnullGCPtr<MessagePort> m_implicit_port; + JS::GCPtr<MessagePort> m_outside_port; void run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_settings, MessagePort& outside_port, WorkerOptions const options); }; -} // namespace Web::HTML - -namespace Web::Bindings { - -WorkerWrapper* wrap(JS::Realm&, HTML::Worker&); - } + +WRAPPER_HACK(Worker, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp index 0da867be35..350e4ec11d 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp @@ -9,7 +9,7 @@ #include <AK/Utf8View.h> #include <AK/Vector.h> #include <LibTextCodec/Decoder.h> -#include <LibWeb/Bindings/WorkerGlobalScopeWrapper.h> +#include <LibWeb/Bindings/WorkerGlobalScopePrototype.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/Forward.h> #include <LibWeb/HTML/EventHandler.h> @@ -20,8 +20,9 @@ namespace Web::HTML { -WorkerGlobalScope::WorkerGlobalScope() - : m_navigator(make_ref_counted<WorkerNavigator>()) +WorkerGlobalScope::WorkerGlobalScope(JS::Realm& realm) + : DOM::EventTarget(realm) + , m_navigator(make_ref_counted<WorkerNavigator>()) { } @@ -54,11 +55,6 @@ DOM::ExceptionOr<void> WorkerGlobalScope::import_scripts(Vector<String> urls) return {}; } -JS::Object* WorkerGlobalScope::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-location NonnullRefPtr<WorkerLocation const> WorkerGlobalScope::location() const { diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h index d92358e0d1..269b9f1ab9 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h @@ -29,28 +29,17 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface // WorkerGlobalScope is the base class of each real WorkerGlobalScope that will be created when the // user agent runs the run a worker algorithm. -class WorkerGlobalScope - : public RefCounted<WorkerGlobalScope> - , public DOM::EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::WorkerGlobalScopeWrapper; - - using RefCounted::ref; - using RefCounted::unref; +class WorkerGlobalScope : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(WorkerGlobalScope, DOM::EventTarget); +public: virtual ~WorkerGlobalScope() override; - // ^EventTarget - virtual void ref_event_target() override { ref(); } - virtual void unref_event_target() override { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; - // Following methods are from the WorkerGlobalScope IDL definition // https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-self - NonnullRefPtr<WorkerGlobalScope const> self() const { return *this; } + JS::NonnullGCPtr<WorkerGlobalScope> self() const { return *this; } NonnullRefPtr<WorkerLocation const> location() const; NonnullRefPtr<WorkerNavigator const> navigator() const; @@ -82,7 +71,7 @@ public: void set_location(NonnullRefPtr<WorkerLocation> loc) { m_location = move(loc); } protected: - explicit WorkerGlobalScope(); + explicit WorkerGlobalScope(JS::Realm&); private: RefPtr<WorkerLocation> m_location; @@ -124,3 +113,5 @@ private: }; } + +WRAPPER_HACK(WorkerGlobalScope, Web::HTML) diff --git a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp index 071cae9d7f..6d99647275 100644 --- a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp +++ b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include <LibWeb/Bindings/PerformanceWrapper.h> +#include <LibWeb/Bindings/PerformancePrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/EventDispatcher.h> @@ -14,34 +14,26 @@ namespace Web::HighResolutionTime { Performance::Performance(HTML::Window& window) - : DOM::EventTarget() + : DOM::EventTarget(window.realm()) , m_window(window) , m_timing(make<NavigationTiming::PerformanceTiming>(window)) { + set_prototype(&window.ensure_web_prototype<Bindings::PerformancePrototype>("Performance")); m_timer.start(); } Performance::~Performance() = default; -double Performance::time_origin() const -{ - auto origin = m_timer.origin_time(); - return (origin.tv_sec * 1000.0) + (origin.tv_usec / 1000.0); -} - -void Performance::ref_event_target() +void Performance::visit_edges(Cell::Visitor& visitor) { - m_window.ref(); + Base::visit_edges(visitor); + visitor.visit(m_window.ptr()); } -void Performance::unref_event_target() -{ - m_window.unref(); -} - -JS::Object* Performance::create_wrapper(JS::Realm& realm) +double Performance::time_origin() const { - return Bindings::wrap(realm, *this); + auto origin = m_timer.origin_time(); + return (origin.tv_sec * 1000.0) + (origin.tv_usec / 1000.0); } } diff --git a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h index 39ae47f082..70ad0838f0 100644 --- a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h +++ b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h @@ -14,31 +14,29 @@ namespace Web::HighResolutionTime { -class Performance final - : public DOM::EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::PerformanceWrapper; - using AllowOwnPtr = TrueType; +class Performance final : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(Performance, DOM::EventTarget); - explicit Performance(HTML::Window&); - ~Performance(); +public: + virtual ~Performance() override; double now() const { return m_timer.elapsed(); } double time_origin() const; - RefPtr<NavigationTiming::PerformanceTiming> timing() { return *m_timing; } + JS::GCPtr<NavigationTiming::PerformanceTiming> timing() { return *m_timing; } + +private: + explicit Performance(HTML::Window&); - virtual void ref_event_target() override; - virtual void unref_event_target() override; + virtual void visit_edges(Cell::Visitor&) override; - virtual JS::Object* create_wrapper(JS::Realm&) override; + JS::NonnullGCPtr<HTML::Window> m_window; -private: - HTML::Window& m_window; Core::ElapsedTimer m_timer; OwnPtr<NavigationTiming::PerformanceTiming> m_timing; }; } + +WRAPPER_HACK(Performance, Web::HighResolutionTime) diff --git a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp index 25e37455e0..6880ff33cf 100644 --- a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp +++ b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp @@ -10,10 +10,9 @@ namespace Web::IntersectionObserver { // https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-intersectionobserver -NonnullRefPtr<IntersectionObserver> IntersectionObserver::create_with_global_object(JS::GlobalObject& global_object, Bindings::CallbackType* callback, IntersectionObserverInit const& options) +NonnullRefPtr<IntersectionObserver> IntersectionObserver::create_with_global_object(HTML::Window&, Bindings::CallbackType* callback, IntersectionObserverInit const& options) { // FIXME: Implement - (void)global_object; (void)callback; (void)options; diff --git a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h index d18594f1a4..97f775cb2b 100644 --- a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h +++ b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h @@ -8,12 +8,13 @@ #include <AK/NonnullRefPtr.h> #include <AK/RefCounted.h> +#include <LibJS/Heap/Handle.h> #include <LibWeb/Bindings/Wrappable.h> namespace Web::IntersectionObserver { struct IntersectionObserverInit { - Optional<Variant<NonnullRefPtr<DOM::Element>, NonnullRefPtr<DOM::Document>>> root; + Optional<Variant<JS::Handle<DOM::Element>, JS::Handle<DOM::Document>>> root; String root_margin { "0px"sv }; Variant<double, Vector<double>> threshold { 0 }; }; @@ -25,7 +26,7 @@ class IntersectionObserver public: using WrapperType = Bindings::IntersectionObserverWrapper; - static NonnullRefPtr<IntersectionObserver> create_with_global_object(JS::GlobalObject&, Bindings::CallbackType* callback, IntersectionObserverInit const& options = {}); + static NonnullRefPtr<IntersectionObserver> create_with_global_object(HTML::Window&, Bindings::CallbackType* callback, IntersectionObserverInit const& options = {}); void observe(DOM::Element& target); void unobserve(DOM::Element& target); diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 23402951e5..e71030e114 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -600,4 +600,29 @@ RefPtr<Painting::Paintable> Node::create_paintable() const return nullptr; } +bool Node::is_anonymous() const +{ + return !m_dom_node.ptr(); +} + +DOM::Node const* Node::dom_node() const +{ + return m_dom_node.ptr(); +} + +DOM::Node* Node::dom_node() +{ + return m_dom_node.ptr(); +} + +DOM::Document& Node::document() +{ + return *m_document; +} + +DOM::Document const& Node::document() const +{ + return *m_document; +} + } diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h index 974c1543fd..e551c1ba5e 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.h +++ b/Userland/Libraries/LibWeb/Layout/Node.h @@ -10,6 +10,7 @@ #include <AK/TypeCasts.h> #include <AK/Vector.h> #include <LibGfx/Rect.h> +#include <LibJS/Heap/Handle.h> #include <LibWeb/CSS/ComputedValues.h> #include <LibWeb/CSS/StyleProperties.h> #include <LibWeb/Forward.h> @@ -37,9 +38,9 @@ public: size_t serial_id() const { return m_serial_id; } - bool is_anonymous() const { return !m_dom_node; } - const DOM::Node* dom_node() const { return m_dom_node; } - DOM::Node* dom_node() { return m_dom_node; } + bool is_anonymous() const; + DOM::Node const* dom_node() const; + DOM::Node* dom_node(); Painting::Paintable* paintable() { return m_paintable; } Painting::Paintable const* paintable() const { return m_paintable; } @@ -47,8 +48,8 @@ public: virtual RefPtr<Painting::Paintable> create_paintable() const; - DOM::Document& document() { return m_document; } - const DOM::Document& document() const { return m_document; } + DOM::Document& document(); + DOM::Document const& document() const; HTML::BrowsingContext const& browsing_context() const; HTML::BrowsingContext& browsing_context(); @@ -140,8 +141,8 @@ protected: private: friend class NodeWithStyle; - NonnullRefPtr<DOM::Document> m_document; - RefPtr<DOM::Node> m_dom_node; + JS::Handle<DOM::Document> m_document; + JS::Handle<DOM::Node> m_dom_node; RefPtr<Painting::Paintable> m_paintable; size_t m_serial_id { 0 }; diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index 595030e9a3..8d21396ff4 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -219,15 +219,15 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& if (auto pseudo_element_node = DOM::Element::create_layout_node_for_display_type(document, pseudo_element_display, move(pseudo_element_style), nullptr)) { // FIXME: Handle images, and multiple values if (pseudo_element_content.type == CSS::ContentData::Type::String) { - auto text = adopt_ref(*new DOM::Text(document, pseudo_element_content.data)); - auto text_node = adopt_ref(*new TextNode(document, text)); + auto* text = document.heap().allocate<DOM::Text>(document.realm(), document, pseudo_element_content.data); + auto text_node = adopt_ref(*new TextNode(document, *text)); push_parent(verify_cast<NodeWithStyle>(*pseudo_element_node)); insert_node_into_inline_or_block_ancestor(text_node); pop_parent(); } else { TODO(); } - return pseudo_element_node; + return pseudo_element_node.ptr(); } return nullptr; @@ -235,11 +235,11 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& push_parent(verify_cast<NodeWithStyle>(*layout_node)); if (auto before_node = create_pseudo_element_if_needed(CSS::Selector::PseudoElement::Before)) { - element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::Before, before_node); + element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::Before, before_node.ptr()); insert_node_into_inline_or_block_ancestor(before_node, true); } if (auto after_node = create_pseudo_element_if_needed(CSS::Selector::PseudoElement::After)) { - element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::After, after_node); + element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::After, after_node.ptr()); insert_node_into_inline_or_block_ancestor(after_node); } pop_parent(); diff --git a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp index f22b75642a..dd16be17db 100644 --- a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp @@ -99,8 +99,8 @@ static bool build_image_document(DOM::Document& document, ByteBuffer const& data head_element->append_child(title_element); auto basename = LexicalPath::basename(document.url().path()); - auto title_text = adopt_ref(*new DOM::Text(document, String::formatted("{} [{}x{}]", basename, bitmap->width(), bitmap->height()))); - title_element->append_child(title_text); + auto title_text = document.heap().allocate<DOM::Text>(document.realm(), document, String::formatted("{} [{}x{}]", basename, bitmap->width(), bitmap->height())); + title_element->append_child(*title_text); auto body_element = document.create_element("body").release_value(); html_element->append_child(body_element); diff --git a/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.cpp b/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.cpp index f42280d449..6bb8a05525 100644 --- a/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.cpp +++ b/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.cpp @@ -9,7 +9,7 @@ namespace Web::NavigationTiming { PerformanceTiming::PerformanceTiming(HTML::Window& window) - : RefCountForwarder(window) + : m_window(JS::make_handle(window)) { } diff --git a/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.h b/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.h index 6ab59bbf33..ffdf6d569d 100644 --- a/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.h +++ b/Userland/Libraries/LibWeb/NavigationTiming/PerformanceTiming.h @@ -14,7 +14,7 @@ namespace Web::NavigationTiming { class PerformanceTiming final - : public RefCountForwarder<HTML::Window> + : public RefCounted<PerformanceTiming> , public Bindings::Wrappable { public: using WrapperType = Bindings::PerformanceTimingWrapper; @@ -44,6 +44,9 @@ public: u64 dom_complete() { return 0; } u64 load_event_start() { return 0; } u64 load_event_end() { return 0; } + +private: + JS::Handle<HTML::Window> m_window; }; } diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 383126c1a6..c812c1351b 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -180,7 +180,7 @@ bool EventHandler::handle_mouseup(Gfx::IntPoint const& position, unsigned button } if (paintable) { - RefPtr<DOM::Node> node = paintable->mouse_event_target(); + JS::GCPtr<DOM::Node> node = paintable->mouse_event_target(); if (!node) node = paintable->dom_node(); @@ -205,12 +205,12 @@ bool EventHandler::handle_mouseup(Gfx::IntPoint const& position, unsigned button } auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::mouseup, offset.x(), offset.y(), position.x(), position.y(), button)); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().window(), UIEvents::EventNames::mouseup, offset.x(), offset.y(), position.x(), position.y(), button)); handled_event = true; bool run_activation_behavior = true; if (node.ptr() == m_mousedown_target && button == GUI::MouseButton::Primary) { - run_activation_behavior = node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::click, offset.x(), offset.y(), position.x(), position.y(), button)); + run_activation_behavior = node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().window(), UIEvents::EventNames::click, offset.x(), offset.y(), position.x(), position.y(), button)); } if (run_activation_behavior) { @@ -228,8 +228,8 @@ bool EventHandler::handle_mouseup(Gfx::IntPoint const& position, unsigned button // implemented in BrowsingContext::choose_a_browsing_context: // // https://html.spec.whatwg.org/multipage/browsers.html#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name - if (RefPtr<HTML::HTMLAnchorElement> link = node->enclosing_link_element()) { - NonnullRefPtr document = *m_browsing_context.active_document(); + if (JS::GCPtr<HTML::HTMLAnchorElement> link = node->enclosing_link_element()) { + JS::NonnullGCPtr<DOM::Document> document = *m_browsing_context.active_document(); auto href = link->href(); auto url = document->parse_url(href); dbgln("Web::EventHandler: Clicking on a link to {}", url); @@ -279,8 +279,8 @@ bool EventHandler::handle_mousedown(Gfx::IntPoint const& position, unsigned butt if (!paint_root()) return false; - NonnullRefPtr document = *m_browsing_context.active_document(); - RefPtr<DOM::Node> node; + JS::NonnullGCPtr<DOM::Document> document = *m_browsing_context.active_document(); + JS::GCPtr<DOM::Node> node; { // TODO: Allow selecting element behind if one on top has pointer-events set to none. @@ -332,9 +332,9 @@ bool EventHandler::handle_mousedown(Gfx::IntPoint const& position, unsigned butt if (!node || !layout_node) return false; - m_mousedown_target = node; + m_mousedown_target = node.ptr(); auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::mousedown, offset.x(), offset.y(), position.x(), position.y(), button)); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().window(), UIEvents::EventNames::mousedown, offset.x(), offset.y(), position.x(), position.y(), button)); } // NOTE: Dispatching an event may have disturbed the world. @@ -405,7 +405,7 @@ bool EventHandler::handle_mousemove(Gfx::IntPoint const& position, unsigned butt page->client().page_did_request_cursor_change(Gfx::StandardCursor::None); } - RefPtr<DOM::Node> node = paintable->mouse_event_target(); + JS::GCPtr<DOM::Node> node = paintable->mouse_event_target(); if (!node) node = paintable->dom_node(); @@ -420,7 +420,7 @@ bool EventHandler::handle_mousemove(Gfx::IntPoint const& position, unsigned butt if (pointer_events == CSS::PointerEvents::None) return false; - hovered_node_changed = node != document.hovered_node(); + hovered_node_changed = node.ptr() != document.hovered_node(); document.set_hovered_node(node); if (node) { hovered_link_element = node->enclosing_link_element(); @@ -455,7 +455,7 @@ bool EventHandler::handle_mousemove(Gfx::IntPoint const& position, unsigned butt } auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::mousemove, offset.x(), offset.y(), position.x(), position.y())); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().window(), UIEvents::EventNames::mousemove, offset.x(), offset.y(), position.x(), position.y())); // NOTE: Dispatching an event may have disturbed the world. if (!paint_root() || paint_root() != node->document().paint_box()) return true; @@ -476,7 +476,7 @@ bool EventHandler::handle_mousemove(Gfx::IntPoint const& position, unsigned butt page->client().page_did_request_cursor_change(hovered_node_cursor); if (hovered_node_changed) { - RefPtr<HTML::HTMLElement> hovered_html_element = document.hovered_node() ? document.hovered_node()->enclosing_html_element_with_attribute(HTML::AttributeNames::title) : nullptr; + JS::GCPtr<HTML::HTMLElement> hovered_html_element = document.hovered_node() ? document.hovered_node()->enclosing_html_element_with_attribute(HTML::AttributeNames::title) : nullptr; if (hovered_html_element && !hovered_html_element->title().is_null()) { page->client().page_did_enter_tooltip_area(m_browsing_context.to_top_level_position(position), hovered_html_element->title()); } else { @@ -515,7 +515,7 @@ bool EventHandler::handle_doubleclick(Gfx::IntPoint const& position, unsigned bu if (pointer_events == CSS::PointerEvents::None) return false; - RefPtr<DOM::Node> node = paintable->mouse_event_target(); + JS::GCPtr<DOM::Node> node = paintable->mouse_event_target(); if (!node) node = paintable->dom_node(); @@ -543,7 +543,7 @@ bool EventHandler::handle_doubleclick(Gfx::IntPoint const& position, unsigned bu return false; auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::dblclick, offset.x(), offset.y(), position.x(), position.y(), button)); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().window(), UIEvents::EventNames::dblclick, offset.x(), offset.y(), position.x(), position.y(), button)); // NOTE: Dispatching an event may have disturbed the world. if (!paint_root() || paint_root() != node->document().paint_box()) @@ -639,7 +639,7 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin if (!m_browsing_context.active_document()) return false; - NonnullRefPtr<DOM::Document> document = *m_browsing_context.active_document(); + JS::NonnullGCPtr<DOM::Document> document = *m_browsing_context.active_document(); if (!document->layout_node()) return false; @@ -722,12 +722,12 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin return true; } - auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->preferred_window_object(), UIEvents::EventNames::keydown, key, modifiers, code_point); + auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->window(), UIEvents::EventNames::keydown, key, modifiers, code_point); - if (RefPtr<DOM::Element> focused_element = document->focused_element()) + if (JS::GCPtr<DOM::Element> focused_element = document->focused_element()) return focused_element->dispatch_event(*event); - if (RefPtr<HTML::HTMLElement> body = m_browsing_context.active_document()->body()) + if (JS::GCPtr<HTML::HTMLElement> body = m_browsing_context.active_document()->body()) return body->dispatch_event(*event); return document->root().dispatch_event(*event); @@ -735,16 +735,16 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin bool EventHandler::handle_keyup(KeyCode key, unsigned modifiers, u32 code_point) { - RefPtr<DOM::Document> document = m_browsing_context.active_document(); + JS::GCPtr<DOM::Document> document = m_browsing_context.active_document(); if (!document) return false; - auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->preferred_window_object(), UIEvents::EventNames::keyup, key, modifiers, code_point); + auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->window(), UIEvents::EventNames::keyup, key, modifiers, code_point); - if (RefPtr<DOM::Element> focused_element = document->focused_element()) + if (JS::GCPtr<DOM::Element> focused_element = document->focused_element()) return document->focused_element()->dispatch_event(*event); - if (RefPtr<HTML::HTMLElement> body = document->body()) + if (JS::GCPtr<HTML::HTMLElement> body = document->body()) return body->dispatch_event(*event); return document->root().dispatch_event(*event); diff --git a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp index 32e7cf5afd..2b2484b6cd 100644 --- a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp +++ b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp @@ -10,10 +10,9 @@ namespace Web::ResizeObserver { // https://drafts.csswg.org/resize-observer/#dom-resizeobserver-resizeobserver -NonnullRefPtr<ResizeObserver> ResizeObserver::create_with_global_object(JS::GlobalObject& global_object, Bindings::CallbackType* callback) +NonnullRefPtr<ResizeObserver> ResizeObserver::create_with_global_object(HTML::Window&, Bindings::CallbackType* callback) { // FIXME: Implement - (void)global_object; (void)callback; return adopt_ref(*new ResizeObserver); } diff --git a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h index d7675dc347..4dfb60d0da 100644 --- a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h +++ b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h @@ -24,7 +24,7 @@ class ResizeObserver public: using WrapperType = Bindings::ResizeObserverWrapper; - static NonnullRefPtr<ResizeObserver> create_with_global_object(JS::GlobalObject&, Bindings::CallbackType* callback); + static NonnullRefPtr<ResizeObserver> create_with_global_object(HTML::Window&, Bindings::CallbackType* callback); void observe(DOM::Element& target, ResizeObserverOptions); void unobserve(DOM::Element& target); diff --git a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp index 265d362541..b2c1af6143 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp @@ -4,15 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "SVGCircleElement.h" +#include <LibWeb/Bindings/SVGCircleElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/AttributeNames.h> #include <LibWeb/SVG/AttributeParser.h> +#include <LibWeb/SVG/SVGCircleElement.h> namespace Web::SVG { SVGCircleElement::SVGCircleElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGeometryElement(document, qualified_name) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGCircleElementPrototype>("SVGCircleElement")); } void SVGCircleElement::parse_attribute(FlyString const& name, String const& value) diff --git a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h index 4899a59cf6..4d8a940118 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h @@ -12,10 +12,9 @@ namespace Web::SVG { class SVGCircleElement final : public SVGGeometryElement { -public: - using WrapperType = Bindings::SVGCircleElementWrapper; + WEB_PLATFORM_OBJECT(SVGCircleElement, SVGGraphicsElement); - SVGCircleElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGCircleElement() override = default; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -27,6 +26,8 @@ public: NonnullRefPtr<SVGAnimatedLength> r() const; private: + SVGCircleElement(DOM::Document&, DOM::QualifiedName); + Optional<Gfx::Path> m_path; Optional<float> m_center_x; @@ -35,3 +36,5 @@ private: }; } + +WRAPPER_HACK(SVGCircleElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp index c1a9f0f1a8..0fd5659009 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/SVGClipPathElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/SVGClipPathElement.h> namespace Web::SVG { @@ -11,6 +13,7 @@ namespace Web::SVG { SVGClipPathElement::SVGClipPathElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGClipPathElementPrototype>("SVGClipPathElement")); } SVGClipPathElement::~SVGClipPathElement() diff --git a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h index 20755d6842..ed74886993 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h @@ -11,13 +11,17 @@ namespace Web::SVG { class SVGClipPathElement final : public SVGElement { -public: - using WrapperType = Bindings::SVGClipPathElementWrapper; + WEB_PLATFORM_OBJECT(SVGClipPathElement, SVGElement); - SVGClipPathElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGClipPathElement(); virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override; + +private: + SVGClipPathElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(SVGClipPathElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp index edf4297a09..9787a68df8 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/SVGDefsElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/SVGDefsElement.h> namespace Web::SVG { @@ -11,6 +13,7 @@ namespace Web::SVG { SVGDefsElement::SVGDefsElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGraphicsElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGDefsElementPrototype>("SVGDefsElement")); } SVGDefsElement::~SVGDefsElement() diff --git a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h index f3aef6c206..dd4e79f2df 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h @@ -11,13 +11,17 @@ namespace Web::SVG { class SVGDefsElement final : public SVGGraphicsElement { -public: - using WrapperType = Bindings::SVGDefsElementWrapper; + WEB_PLATFORM_OBJECT(SVGDefsElement, SVGGraphicsElement); - SVGDefsElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGDefsElement(); virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override; + +private: + SVGDefsElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(SVGDefsElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGElement.cpp index 301231367a..e4dac180cc 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGElement.cpp @@ -4,14 +4,23 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/SVGElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/SVGElement.h> namespace Web::SVG { SVGElement::SVGElement(DOM::Document& document, DOM::QualifiedName qualified_name) : Element(document, move(qualified_name)) - , m_dataset(JS::make_handle(HTML::DOMStringMap::create(*this))) + , m_dataset(HTML::DOMStringMap::create(*this)) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGElementPrototype>("SVGElement")); +} + +void SVGElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_dataset.ptr()); } } diff --git a/Userland/Libraries/LibWeb/SVG/SVGElement.h b/Userland/Libraries/LibWeb/SVG/SVGElement.h index af47434fb4..a998e053be 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGElement.h @@ -12,18 +12,22 @@ namespace Web::SVG { class SVGElement : public DOM::Element { -public: - using WrapperType = Bindings::SVGElementWrapper; + WEB_PLATFORM_OBJECT(SVGElement, DOM::Element); +public: virtual bool requires_svg_container() const override { return true; } - HTML::DOMStringMap* dataset() { return m_dataset.cell(); } - HTML::DOMStringMap const* dataset() const { return m_dataset.cell(); } + HTML::DOMStringMap* dataset() { return m_dataset.ptr(); } + HTML::DOMStringMap const* dataset() const { return m_dataset.ptr(); } protected: SVGElement(DOM::Document&, DOM::QualifiedName); - JS::Handle<HTML::DOMStringMap> m_dataset; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr<HTML::DOMStringMap> m_dataset; }; } + +WRAPPER_HACK(SVGElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp index 13fe18332c..2a906800e9 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp @@ -4,15 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "SVGEllipseElement.h" +#include <LibWeb/Bindings/SVGEllipseElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/AttributeNames.h> #include <LibWeb/SVG/AttributeParser.h> +#include <LibWeb/SVG/SVGEllipseElement.h> namespace Web::SVG { SVGEllipseElement::SVGEllipseElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGeometryElement(document, qualified_name) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGEllipseElementPrototype>("SVGEllipseElement")); } void SVGEllipseElement::parse_attribute(FlyString const& name, String const& value) diff --git a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h index 6975476a07..af6fbf6eae 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h @@ -12,10 +12,9 @@ namespace Web::SVG { class SVGEllipseElement final : public SVGGeometryElement { -public: - using WrapperType = Bindings::SVGEllipseElementWrapper; + WEB_PLATFORM_OBJECT(SVGEllipseElement, SVGGraphicsElement); - SVGEllipseElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGEllipseElement() override = default; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -28,6 +27,8 @@ public: NonnullRefPtr<SVGAnimatedLength> ry() const; private: + SVGEllipseElement(DOM::Document&, DOM::QualifiedName); + Optional<Gfx::Path> m_path; Optional<float> m_center_x; @@ -37,3 +38,5 @@ private: }; } + +WRAPPER_HACK(SVGEllipseElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGGElement.h b/Userland/Libraries/LibWeb/SVG/SVGGElement.h index c9cbbecc7a..2942c88088 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGGElement.h @@ -11,13 +11,17 @@ namespace Web::SVG { class SVGGElement final : public SVGGraphicsElement { -public: - using WrapperType = Bindings::SVGPathElementWrapper; + WEB_PLATFORM_OBJECT(SVGGElement, SVGGraphicsElement); - SVGGElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGGElement() override = default; virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override; + +private: + SVGGElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(SVGGElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp index 40c035ebed..51292000f5 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/SVGGeometryElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/Layout/SVGGeometryBox.h> #include <LibWeb/SVG/SVGGeometryElement.h> @@ -12,6 +14,7 @@ namespace Web::SVG { SVGGeometryElement::SVGGeometryElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGraphicsElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGGeometryElementPrototype>("SVGGeometryElement")); } RefPtr<Layout::Node> SVGGeometryElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style) diff --git a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h index dc52eb7d68..f72ef382fe 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h @@ -13,9 +13,9 @@ namespace Web::SVG { // https://svgwg.org/svg2-draft/types.html#InterfaceSVGGeometryElement class SVGGeometryElement : public SVGGraphicsElement { -public: - using WrapperType = Bindings::SVGGeometryElementWrapper; + WEB_PLATFORM_OBJECT(SVGGeometryElement, SVGGraphicsElement); +public: virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override; virtual Gfx::Path& get_path() = 0; @@ -28,3 +28,5 @@ protected: }; } + +WRAPPER_HACK(SVGGeometryElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp index 9aeac268c9..fc938c062a 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp @@ -5,7 +5,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/SVGGraphicsElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/Layout/Node.h> #include <LibWeb/SVG/SVGGraphicsElement.h> #include <LibWeb/SVG/SVGSVGElement.h> @@ -15,6 +17,7 @@ namespace Web::SVG { SVGGraphicsElement::SVGGraphicsElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGGraphicsElementPrototype>("SVGGraphicsElement")); } void SVGGraphicsElement::apply_presentational_hints(CSS::StyleProperties& style) const diff --git a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h index 1443d530dd..7fcb5a1155 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h @@ -15,16 +15,19 @@ namespace Web::SVG { class SVGGraphicsElement : public SVGElement { -public: - using WrapperType = Bindings::SVGGraphicsElementWrapper; - - SVGGraphicsElement(DOM::Document&, DOM::QualifiedName); + WEB_PLATFORM_OBJECT(SVGGraphicsElement, SVGElement); +public: virtual void apply_presentational_hints(CSS::StyleProperties&) const override; Optional<Gfx::Color> fill_color() const; Optional<Gfx::Color> stroke_color() const; Optional<float> stroke_width() const; + +protected: + SVGGraphicsElement(DOM::Document&, DOM::QualifiedName); }; } + +WRAPPER_HACK(SVGGraphicsElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp index cb40d5c9f7..3a78b4a006 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp @@ -4,15 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "SVGLineElement.h" +#include <LibWeb/Bindings/SVGLineElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/AttributeNames.h> #include <LibWeb/SVG/AttributeParser.h> +#include <LibWeb/SVG/SVGLineElement.h> namespace Web::SVG { SVGLineElement::SVGLineElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGeometryElement(document, qualified_name) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGLineElementPrototype>("SVGLineElement")); } void SVGLineElement::parse_attribute(FlyString const& name, String const& value) diff --git a/Userland/Libraries/LibWeb/SVG/SVGLineElement.h b/Userland/Libraries/LibWeb/SVG/SVGLineElement.h index 6078272d0a..cf87b85c05 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGLineElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGLineElement.h @@ -12,10 +12,9 @@ namespace Web::SVG { class SVGLineElement final : public SVGGeometryElement { -public: - using WrapperType = Bindings::SVGLineElementWrapper; + WEB_PLATFORM_OBJECT(SVGLineElement, SVGGraphicsElement); - SVGLineElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGLineElement() override = default; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -28,6 +27,8 @@ public: NonnullRefPtr<SVGAnimatedLength> y2() const; private: + SVGLineElement(DOM::Document&, DOM::QualifiedName); + Optional<Gfx::Path> m_path; Optional<float> m_x1; @@ -37,3 +38,5 @@ private: }; } + +WRAPPER_HACK(SVGLineElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp index 0419dbf527..48867f7e8c 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp @@ -8,6 +8,7 @@ #include <AK/ExtraMathConstants.h> #include <LibGfx/Painter.h> #include <LibGfx/Path.h> +#include <LibWeb/Bindings/SVGPathElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/Layout/SVGGeometryBox.h> @@ -86,6 +87,7 @@ namespace Web::SVG { SVGPathElement::SVGPathElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGeometryElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGPathElementPrototype>("SVGPathElement")); } void SVGPathElement::parse_attribute(FlyString const& name, String const& value) diff --git a/Userland/Libraries/LibWeb/SVG/SVGPathElement.h b/Userland/Libraries/LibWeb/SVG/SVGPathElement.h index 1b3ff0a2aa..4e8131a1cb 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPathElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGPathElement.h @@ -14,10 +14,9 @@ namespace Web::SVG { class SVGPathElement final : public SVGGeometryElement { -public: - using WrapperType = Bindings::SVGPathElementWrapper; + WEB_PLATFORM_OBJECT(SVGPathElement, SVGGeometryElement); - SVGPathElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGPathElement() override = default; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -25,9 +24,13 @@ public: virtual Gfx::Path& get_path() override; private: + SVGPathElement(DOM::Document&, DOM::QualifiedName); + Vector<PathInstruction> m_instructions; Gfx::FloatPoint m_previous_control_point = {}; Optional<Gfx::Path> m_path; }; } + +WRAPPER_HACK(SVGPathElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp index 16701fb122..a38fc7240a 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp @@ -4,15 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "SVGPolygonElement.h" +#include <LibWeb/Bindings/SVGPolygonElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/AttributeNames.h> #include <LibWeb/SVG/AttributeParser.h> +#include <LibWeb/SVG/SVGPolygonElement.h> namespace Web::SVG { SVGPolygonElement::SVGPolygonElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGeometryElement(document, qualified_name) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGPolygonElementPrototype>("SVGPolygonElement")); } void SVGPolygonElement::parse_attribute(FlyString const& name, String const& value) diff --git a/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.h b/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.h index 626b6ee361..c1384d2f64 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.h @@ -11,10 +11,9 @@ namespace Web::SVG { class SVGPolygonElement final : public SVGGeometryElement { -public: - using WrapperType = Bindings::SVGPolygonElementWrapper; + WEB_PLATFORM_OBJECT(SVGPolygonElement, SVGGeometryElement); - SVGPolygonElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGPolygonElement() override = default; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -22,9 +21,13 @@ public: virtual Gfx::Path& get_path() override; private: + SVGPolygonElement(DOM::Document&, DOM::QualifiedName); + Optional<Gfx::Path> m_path; Vector<Gfx::FloatPoint> m_points; }; } + +WRAPPER_HACK(SVGPolygonElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp index 68e8d0e23b..0b43e1b118 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp @@ -4,15 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "SVGPolylineElement.h" +#include <LibWeb/Bindings/SVGPolylineElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/AttributeNames.h> #include <LibWeb/SVG/AttributeParser.h> +#include <LibWeb/SVG/SVGPolylineElement.h> namespace Web::SVG { SVGPolylineElement::SVGPolylineElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGeometryElement(document, qualified_name) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGPolylineElementPrototype>("SVGPolylineElement")); } void SVGPolylineElement::parse_attribute(FlyString const& name, String const& value) diff --git a/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.h b/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.h index 396f7873b7..24b9d9cb53 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.h @@ -11,10 +11,9 @@ namespace Web::SVG { class SVGPolylineElement final : public SVGGeometryElement { -public: - using WrapperType = Bindings::SVGPolylineElementWrapper; + WEB_PLATFORM_OBJECT(SVGPolylineElement, SVGGeometryElement); - SVGPolylineElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGPolylineElement() override = default; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -22,9 +21,13 @@ public: virtual Gfx::Path& get_path() override; private: + SVGPolylineElement(DOM::Document&, DOM::QualifiedName); + Optional<Gfx::Path> m_path; Vector<Gfx::FloatPoint> m_points; }; } + +WRAPPER_HACK(SVGPolylineElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp index eeefaac8a8..7dfe0757aa 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp @@ -5,6 +5,8 @@ */ #include "SVGRectElement.h" +#include <LibWeb/Bindings/SVGRectElementPrototype.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/SVG/AttributeNames.h> #include <LibWeb/SVG/AttributeParser.h> #include <LibWeb/SVG/SVGAnimatedLength.h> @@ -15,6 +17,7 @@ namespace Web::SVG { SVGRectElement::SVGRectElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGeometryElement(document, qualified_name) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGRectElementPrototype>("SVGRectElement")); } void SVGRectElement::parse_attribute(FlyString const& name, String const& value) diff --git a/Userland/Libraries/LibWeb/SVG/SVGRectElement.h b/Userland/Libraries/LibWeb/SVG/SVGRectElement.h index 22f6726b7f..9e647accf7 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGRectElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGRectElement.h @@ -12,10 +12,9 @@ namespace Web::SVG { // https://www.w3.org/TR/SVG11/shapes.html#RectElement class SVGRectElement final : public SVGGeometryElement { -public: - using WrapperType = Bindings::SVGRectElementWrapper; + WEB_PLATFORM_OBJECT(SVGRectElement, SVGGeometryElement); - SVGRectElement(DOM::Document&, DOM::QualifiedName); +public: virtual ~SVGRectElement() override = default; virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -30,6 +29,8 @@ public: NonnullRefPtr<SVGAnimatedLength> ry() const; private: + SVGRectElement(DOM::Document&, DOM::QualifiedName); + Gfx::FloatPoint calculate_used_corner_radius_values(); Optional<Gfx::Path> m_path; @@ -43,3 +44,5 @@ private: }; } + +WRAPPER_HACK(SVGRectElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp index ebd0e709f4..e0d5bd64f2 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp @@ -6,6 +6,7 @@ */ #include <LibGfx/Painter.h> +#include <LibWeb/Bindings/SVGSVGElementPrototype.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/CSS/StyleComputer.h> #include <LibWeb/DOM/Document.h> @@ -20,6 +21,7 @@ namespace Web::SVG { SVGSVGElement::SVGSVGElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGraphicsElement(document, qualified_name) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGSVGElementPrototype>("SVGSVGElement")); } RefPtr<Layout::Node> SVGSVGElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style) diff --git a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h index f81726c01e..2d0e9fbc2b 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h @@ -13,11 +13,9 @@ namespace Web::SVG { class SVGSVGElement final : public SVGGraphicsElement { -public: - using WrapperType = Bindings::SVGSVGElementWrapper; - - SVGSVGElement(DOM::Document&, DOM::QualifiedName); + WEB_PLATFORM_OBJECT(SVGSVGElement, SVGGraphicsElement); +public: virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override; virtual void apply_presentational_hints(CSS::StyleProperties&) const override; @@ -28,6 +26,8 @@ public: Optional<ViewBox> const& view_box() const { return m_view_box; } private: + SVGSVGElement(DOM::Document&, DOM::QualifiedName); + virtual bool is_svg_svg_element() const override { return true; } virtual void parse_attribute(FlyString const& name, String const& value) override; @@ -43,3 +43,5 @@ template<> inline bool Node::fast_is<SVG::SVGSVGElement>() const { return is_svg_svg_element(); } } + +WRAPPER_HACK(SVGSVGElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp index b71329c634..89eca8deab 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp @@ -5,6 +5,7 @@ */ #include <AK/Utf16View.h> +#include <LibWeb/Bindings/SVGTextContentElementPrototype.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/SVG/SVGTextContentElement.h> @@ -13,6 +14,7 @@ namespace Web::SVG { SVGTextContentElement::SVGTextContentElement(DOM::Document& document, DOM::QualifiedName qualified_name) : SVGGraphicsElement(document, move(qualified_name)) { + set_prototype(&window().ensure_web_prototype<Bindings::SVGTextContentElementPrototype>("SVGTextContentElement")); } // https://svgwg.org/svg2-draft/text.html#__svg__SVGTextContentElement__getNumberOfChars diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h index e80708bbf5..fc87f69d1a 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h @@ -12,12 +12,15 @@ namespace Web::SVG { // https://svgwg.org/svg2-draft/text.html#InterfaceSVGTextContentElement class SVGTextContentElement : public SVGGraphicsElement { + WEB_PLATFORM_OBJECT(SVGTextContentElement, SVGGraphicsElement); + public: - using WrapperType = Bindings::SVGTextContentElementWrapper; + int get_number_of_chars() const; +protected: SVGTextContentElement(DOM::Document&, DOM::QualifiedName); - - int get_number_of_chars() const; }; } + +WRAPPER_HACK(SVGTextContentElement, Web::SVG) diff --git a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp index f052059b8a..31c1085383 100644 --- a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp @@ -5,17 +5,17 @@ */ #include <LibWeb/Bindings/FocusEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/UIEvents/FocusEvent.h> namespace Web::UIEvents { -FocusEvent* FocusEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, FocusEventInit const& event_init) +FocusEvent* FocusEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, FocusEventInit const& event_init) { return window_object.heap().allocate<FocusEvent>(window_object.realm(), window_object, event_name, event_init); } -FocusEvent::FocusEvent(Bindings::WindowObject& window_object, FlyString const& event_name, FocusEventInit const& event_init) +FocusEvent::FocusEvent(HTML::Window& window_object, FlyString const& event_name, FocusEventInit const& event_init) : UIEvent(window_object, event_name) { set_prototype(&window_object.ensure_web_prototype<Bindings::FocusEventPrototype>("FocusEvent")); diff --git a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h index 544748dea6..40da1d4c78 100644 --- a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h @@ -11,19 +11,17 @@ namespace Web::UIEvents { struct FocusEventInit : public UIEventInit { - RefPtr<DOM::EventTarget> related_target; + JS::GCPtr<DOM::EventTarget> related_target; }; class FocusEvent final : public UIEvent { - JS_OBJECT(FocusEvent, UIEvent); + WEB_PLATFORM_OBJECT(FocusEvent, UIEvent); public: - static FocusEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const& event_init); + static FocusEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, FocusEventInit const& event_init); - FocusEvent(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const&); + FocusEvent(HTML::Window&, FlyString const& event_name, FocusEventInit const&); virtual ~FocusEvent() override; - - FocusEvent& impl() { return *this; } }; } diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp index 6f41ef8207..6aceb57223 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp @@ -6,7 +6,7 @@ #include <AK/CharacterTypes.h> #include <LibWeb/Bindings/KeyboardEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/UIEvents/KeyboardEvent.h> namespace Web::UIEvents { @@ -67,7 +67,7 @@ static unsigned long determine_key_code(KeyCode platform_key, u32 code_point) return platform_key; } -KeyboardEvent* KeyboardEvent::create_from_platform_event(Bindings::WindowObject& window_object, FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point) +KeyboardEvent* KeyboardEvent::create_from_platform_event(HTML::Window& window_object, FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point) { // FIXME: Figure out what these should actually contain. String event_key = key_code_to_string(platform_key); @@ -105,17 +105,17 @@ bool KeyboardEvent::get_modifier_state(String const& key_arg) return false; } -KeyboardEvent* KeyboardEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, KeyboardEventInit const& event_init) +KeyboardEvent* KeyboardEvent::create(HTML::Window& window_object, FlyString const& event_name, KeyboardEventInit const& event_init) { return window_object.heap().allocate<KeyboardEvent>(window_object.realm(), window_object, event_name, event_init); } -KeyboardEvent* KeyboardEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, KeyboardEventInit const& event_init) +KeyboardEvent* KeyboardEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, KeyboardEventInit const& event_init) { return create(window_object, event_name, event_init); } -KeyboardEvent::KeyboardEvent(Bindings::WindowObject& window_object, FlyString const& event_name, KeyboardEventInit const& event_init) +KeyboardEvent::KeyboardEvent(HTML::Window& window_object, FlyString const& event_name, KeyboardEventInit const& event_init) : UIEvent(window_object, event_name, event_init) , m_key(event_init.key) , m_code(event_init.code) diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h index c5e618585e..dc5452ebd8 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h @@ -25,19 +25,17 @@ struct KeyboardEventInit : public EventModifierInit { // https://www.w3.org/TR/uievents/#interface-keyboardevent class KeyboardEvent final : public UIEvent { - JS_OBJECT(KeyboardEvent, UIEvent); + WEB_PLATFORM_OBJECT(KeyboardEvent, UIEvent); public: - static KeyboardEvent* create(Bindings::WindowObject&, FlyString const& event_name, KeyboardEventInit const& event_init = {}); - static KeyboardEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, KeyboardEventInit const& event_init); - static KeyboardEvent* create_from_platform_event(Bindings::WindowObject&, FlyString const& event_name, KeyCode, unsigned modifiers, u32 code_point); + static KeyboardEvent* create(HTML::Window&, FlyString const& event_name, KeyboardEventInit const& event_init = {}); + static KeyboardEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, KeyboardEventInit const& event_init); + static KeyboardEvent* create_from_platform_event(HTML::Window&, FlyString const& event_name, KeyCode, unsigned modifiers, u32 code_point); - KeyboardEvent(Bindings::WindowObject&, FlyString const& event_name, KeyboardEventInit const& event_init); + KeyboardEvent(HTML::Window&, FlyString const& event_name, KeyboardEventInit const& event_init); virtual ~KeyboardEvent() override; - KeyboardEvent& impl() { return *this; } - u32 key_code() const { return m_key_code; } u32 char_code() const { return m_char_code; } diff --git a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp index 4528497823..6b09d4947e 100644 --- a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp @@ -7,14 +7,14 @@ #include <LibGUI/Event.h> #include <LibWeb/Bindings/MouseEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/EventNames.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/UIEvents/EventNames.h> #include <LibWeb/UIEvents/MouseEvent.h> namespace Web::UIEvents { -MouseEvent::MouseEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MouseEventInit const& event_init) +MouseEvent::MouseEvent(HTML::Window& window_object, FlyString const& event_name, MouseEventInit const& event_init) : UIEvent(window_object, event_name, event_init) , m_offset_x(event_init.offset_x) , m_offset_y(event_init.offset_y) @@ -47,12 +47,12 @@ static i16 determine_button(unsigned mouse_button) } } -MouseEvent* MouseEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MouseEventInit const& event_init) +MouseEvent* MouseEvent::create(HTML::Window& window_object, FlyString const& event_name, MouseEventInit const& event_init) { return window_object.heap().allocate<MouseEvent>(window_object.realm(), window_object, event_name, event_init); } -MouseEvent* MouseEvent::create_from_platform_event(Bindings::WindowObject& window_object, FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button) +MouseEvent* MouseEvent::create_from_platform_event(HTML::Window& window_object, FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button) { MouseEventInit event_init {}; event_init.offset_x = offset_x; diff --git a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h index 01b6778be5..9e52fb7cd2 100644 --- a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h @@ -22,18 +22,16 @@ struct MouseEventInit : public EventModifierInit { }; class MouseEvent final : public UIEvent { - JS_OBJECT(MouseEvent, UIEvent); + WEB_PLATFORM_OBJECT(MouseEvent, UIEvent); public: - static MouseEvent* create(Bindings::WindowObject&, FlyString const& event_name, MouseEventInit const& event_init = {}); - static MouseEvent* create_from_platform_event(Bindings::WindowObject&, FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button = 1); + static MouseEvent* create(HTML::Window&, FlyString const& event_name, MouseEventInit const& event_init = {}); + static MouseEvent* create_from_platform_event(HTML::Window&, FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button = 1); - MouseEvent(Bindings::WindowObject&, FlyString const& event_name, MouseEventInit const& event_init); + MouseEvent(HTML::Window&, FlyString const& event_name, MouseEventInit const& event_init); virtual ~MouseEvent() override; - MouseEvent& impl() { return *this; } - double offset_x() const { return m_offset_x; } double offset_y() const { return m_offset_y; } diff --git a/Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp index d7762b25bc..48f3cb6424 100644 --- a/Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp @@ -5,28 +5,28 @@ */ #include <LibWeb/Bindings/UIEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/UIEvents/UIEvent.h> namespace Web::UIEvents { -UIEvent* UIEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name) +UIEvent* UIEvent::create(HTML::Window& window_object, FlyString const& event_name) { return window_object.heap().allocate<UIEvent>(window_object.realm(), window_object, event_name); } -UIEvent* UIEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, UIEventInit const& event_init) +UIEvent* UIEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, UIEventInit const& event_init) { return window_object.heap().allocate<UIEvent>(window_object.realm(), window_object, event_name, event_init); } -UIEvent::UIEvent(Bindings::WindowObject& window_object, FlyString const& event_name) +UIEvent::UIEvent(HTML::Window& window_object, FlyString const& event_name) : Event(window_object, event_name) { set_prototype(&window_object.ensure_web_prototype<Bindings::UIEventPrototype>("UIEvent")); } -UIEvent::UIEvent(Bindings::WindowObject& window_object, FlyString const& event_name, UIEventInit const& event_init) +UIEvent::UIEvent(HTML::Window& window_object, FlyString const& event_name, UIEventInit const& event_init) : Event(window_object, event_name, event_init) , m_view(event_init.view) , m_detail(event_init.detail) @@ -36,4 +36,10 @@ UIEvent::UIEvent(Bindings::WindowObject& window_object, FlyString const& event_n UIEvent::~UIEvent() = default; +void UIEvent::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_view.ptr()); +} + } diff --git a/Userland/Libraries/LibWeb/UIEvents/UIEvent.h b/Userland/Libraries/LibWeb/UIEvents/UIEvent.h index dd044d233a..0f04a0cca0 100644 --- a/Userland/Libraries/LibWeb/UIEvents/UIEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/UIEvent.h @@ -13,25 +13,23 @@ namespace Web::UIEvents { struct UIEventInit : public DOM::EventInit { - RefPtr<HTML::Window> view { nullptr }; + JS::GCPtr<HTML::Window> view; int detail { 0 }; }; class UIEvent : public DOM::Event { - JS_OBJECT(UIEvent, DOM::Event); + WEB_PLATFORM_OBJECT(UIEvent, DOM::Event); public: - static UIEvent* create(Bindings::WindowObject&, FlyString const& type); - static UIEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, UIEventInit const& event_init); + static UIEvent* create(HTML::Window&, FlyString const& type); + static UIEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, UIEventInit const& event_init); - UIEvent(Bindings::WindowObject&, FlyString const& event_name); - UIEvent(Bindings::WindowObject&, FlyString const& event_name, UIEventInit const& event_init); + UIEvent(HTML::Window&, FlyString const& event_name); + UIEvent(HTML::Window&, FlyString const& event_name, UIEventInit const& event_init); virtual ~UIEvent() override; - UIEvent& impl() { return *this; } - - HTML::Window const* view() const { return m_view; } + HTML::Window const* view() const { return m_view.ptr(); } int detail() const { return m_detail; } virtual u32 which() const { return 0; } @@ -43,7 +41,9 @@ public: } protected: - RefPtr<HTML::Window> m_view; + virtual void visit_edges(Cell::Visitor&) override; + + JS::GCPtr<HTML::Window> m_view; int m_detail { 0 }; }; diff --git a/Userland/Libraries/LibWeb/URL/URL.cpp b/Userland/Libraries/LibWeb/URL/URL.cpp index 0470e86f1c..8878ca32a2 100644 --- a/Userland/Libraries/LibWeb/URL/URL.cpp +++ b/Userland/Libraries/LibWeb/URL/URL.cpp @@ -10,7 +10,7 @@ namespace Web::URL { -DOM::ExceptionOr<NonnullRefPtr<URL>> URL::create_with_global_object(Bindings::WindowObject& window_object, String const& url, String const& base) +DOM::ExceptionOr<NonnullRefPtr<URL>> URL::create_with_global_object(HTML::Window& window_object, String const& url, String const& base) { // 1. Let parsedBase be null. Optional<AK::URL> parsed_base; diff --git a/Userland/Libraries/LibWeb/URL/URL.h b/Userland/Libraries/LibWeb/URL/URL.h index 15bea032cb..c5e59e272e 100644 --- a/Userland/Libraries/LibWeb/URL/URL.h +++ b/Userland/Libraries/LibWeb/URL/URL.h @@ -26,7 +26,7 @@ public: return adopt_ref(*new URL(move(url), move(query))); } - static DOM::ExceptionOr<NonnullRefPtr<URL>> create_with_global_object(Bindings::WindowObject&, String const& url, String const& base); + static DOM::ExceptionOr<NonnullRefPtr<URL>> create_with_global_object(HTML::Window&, String const& url, String const& base); String href() const; DOM::ExceptionOr<void> set_href(String const&); diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp b/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp index fccdc8a801..1c0d82927d 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp +++ b/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp @@ -68,7 +68,7 @@ Vector<QueryParam> url_decode(StringView input) // https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams // https://url.spec.whatwg.org/#urlsearchparams-initialize -DOM::ExceptionOr<NonnullRefPtr<URLSearchParams>> URLSearchParams::create_with_global_object(Bindings::WindowObject&, Variant<Vector<Vector<String>>, OrderedHashMap<String, String>, String> const& init) +DOM::ExceptionOr<NonnullRefPtr<URLSearchParams>> URLSearchParams::create_with_global_object(HTML::Window&, Variant<Vector<Vector<String>>, OrderedHashMap<String, String>, String> const& init) { // 1. If init is a string and starts with U+003F (?), then remove the first code point from init. // NOTE: We do this when we know that it's a string on step 3 of initialization. diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParams.h b/Userland/Libraries/LibWeb/URL/URLSearchParams.h index 50ea3e4e83..15f45ea7b1 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParams.h +++ b/Userland/Libraries/LibWeb/URL/URLSearchParams.h @@ -30,7 +30,7 @@ public: return adopt_ref(*new URLSearchParams(move(list))); } - static DOM::ExceptionOr<NonnullRefPtr<URLSearchParams>> create_with_global_object(Bindings::WindowObject&, Variant<Vector<Vector<String>>, OrderedHashMap<String, String>, String> const& init); + static DOM::ExceptionOr<NonnullRefPtr<URLSearchParams>> create_with_global_object(HTML::Window&, Variant<Vector<Vector<String>>, OrderedHashMap<String, String>, String> const& init); void append(String const& name, String const& value); void delete_(String const& name); diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp index bcb42d8a04..6cce454127 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp @@ -5,7 +5,7 @@ */ #include <LibJS/Runtime/GlobalObject.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/WebAssembly/WebAssemblyInstanceConstructor.h> #include <LibWeb/WebAssembly/WebAssemblyInstanceObject.h> #include <LibWeb/WebAssembly/WebAssemblyInstanceObjectPrototype.h> @@ -42,7 +42,7 @@ JS::ThrowCompletionOr<JS::Object*> WebAssemblyInstanceConstructor::construct(Fun void WebAssemblyInstanceConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<WebAssemblyInstancePrototype>("WebAssemblyInstancePrototype"), 0); diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceObject.cpp index 80eb85391f..821fe58480 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceObject.cpp @@ -10,7 +10,7 @@ #include <LibJS/Runtime/BigInt.h> #include <LibJS/Runtime/TypedArray.h> #include <LibWasm/AbstractMachine/Interpreter.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/WebAssembly/WebAssemblyInstanceObject.h> #include <LibWeb/WebAssembly/WebAssemblyMemoryPrototype.h> #include <LibWeb/WebAssembly/WebAssemblyObject.h> @@ -18,7 +18,7 @@ namespace Web::Bindings { WebAssemblyInstanceObject::WebAssemblyInstanceObject(JS::Realm& realm, size_t index) - : Object(static_cast<Web::Bindings::WindowObject&>(realm.global_object()).ensure_web_prototype<WebAssemblyInstancePrototype>("WebAssemblyInstancePrototype")) + : Object(static_cast<Web::HTML::Window&>(realm.global_object()).ensure_web_prototype<WebAssemblyInstancePrototype>("WebAssemblyInstancePrototype")) , m_index(index) { } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp index 35f38465ea..78068af3e4 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp @@ -5,7 +5,7 @@ */ #include <LibJS/Runtime/GlobalObject.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/WebAssembly/WebAssemblyMemoryConstructor.h> #include <LibWeb/WebAssembly/WebAssemblyMemoryPrototype.h> #include <LibWeb/WebAssembly/WebAssemblyObject.h> @@ -53,7 +53,7 @@ JS::ThrowCompletionOr<JS::Object*> WebAssemblyMemoryConstructor::construct(Funct void WebAssemblyMemoryConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<WebAssemblyMemoryPrototype>("WebAssemblyMemoryPrototype"), 0); diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryPrototype.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryPrototype.h index c9b8aa03e3..563148fffa 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryPrototype.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryPrototype.h @@ -10,8 +10,8 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/VM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Forward.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp index 71a24e7694..217d22a2ea 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp @@ -6,7 +6,7 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/TypedArray.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/WebAssembly/WebAssemblyModuleConstructor.h> #include <LibWeb/WebAssembly/WebAssemblyModuleObject.h> #include <LibWeb/WebAssembly/WebAssemblyModulePrototype.h> @@ -40,7 +40,7 @@ JS::ThrowCompletionOr<JS::Object*> WebAssemblyModuleConstructor::construct(Funct void WebAssemblyModuleConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<WebAssemblyModulePrototype>("WebAssemblyModulePrototype"), 0); diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.cpp index de74c2d31a..8613837f0f 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.cpp @@ -10,7 +10,7 @@ namespace Web::Bindings { WebAssemblyModuleObject::WebAssemblyModuleObject(JS::Realm& realm, size_t index) - : Object(static_cast<WindowObject&>(realm.global_object()).ensure_web_prototype<WebAssemblyModulePrototype>("WebAssemblyModulePrototype")) + : Object(verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<WebAssemblyModulePrototype>("WebAssemblyModulePrototype")) , m_index(index) { } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModulePrototype.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModulePrototype.h index 33890534c7..a0526edd90 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModulePrototype.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModulePrototype.h @@ -10,8 +10,8 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/VM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Forward.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp index 5be142435f..9a7b78a522 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp @@ -19,7 +19,7 @@ #include <LibJS/Runtime/TypedArray.h> #include <LibWasm/AbstractMachine/Interpreter.h> #include <LibWasm/AbstractMachine/Validator.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/WebAssembly/WebAssemblyInstanceConstructor.h> #include <LibWeb/WebAssembly/WebAssemblyObject.h> @@ -42,7 +42,7 @@ void WebAssemblyObject::initialize(JS::Realm& realm) auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); auto& memory_constructor = window.ensure_web_constructor<WebAssemblyMemoryConstructor>("WebAssembly.Memory"); memory_constructor.define_direct_property(vm.names.name, js_string(vm, "WebAssembly.Memory"), JS::Attribute::Configurable); auto& memory_prototype = window.ensure_web_prototype<WebAssemblyMemoryPrototype>("WebAssemblyMemoryPrototype"); @@ -482,7 +482,7 @@ JS::NativeFunction* create_native_function(JS::VM& vm, Wasm::FunctionAddress add } WebAssemblyMemoryObject::WebAssemblyMemoryObject(JS::Realm& realm, Wasm::MemoryAddress address) - : Object(static_cast<WindowObject&>(realm.global_object()).ensure_web_prototype<WebAssemblyMemoryPrototype>("WebAssemblyMemoryPrototype")) + : Object(verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<WebAssemblyMemoryPrototype>("WebAssemblyMemoryPrototype")) , m_address(address) { } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp index 0698f06be5..e581ed01da 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp @@ -6,7 +6,7 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/TypedArray.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/WebAssembly/WebAssemblyObject.h> #include <LibWeb/WebAssembly/WebAssemblyTableConstructor.h> #include <LibWeb/WebAssembly/WebAssemblyTableObject.h> @@ -83,7 +83,7 @@ JS::ThrowCompletionOr<JS::Object*> WebAssemblyTableConstructor::construct(Functi void WebAssemblyTableConstructor::initialize(JS::Realm& realm) { auto& vm = this->vm(); - auto& window = static_cast<WindowObject&>(realm.global_object()); + auto& window = verify_cast<HTML::Window>(realm.global_object()); NativeFunction::initialize(realm); define_direct_property(vm.names.prototype, &window.ensure_web_prototype<WebAssemblyTablePrototype>("WebAssemblyTablePrototype"), 0); diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp index e8fe1a3e28..030eed5b8d 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp @@ -10,7 +10,7 @@ namespace Web::Bindings { WebAssemblyTableObject::WebAssemblyTableObject(JS::Realm& realm, Wasm::TableAddress address) - : Object(static_cast<WindowObject&>(realm.global_object()).ensure_web_prototype<WebAssemblyTablePrototype>("WebAssemblyTablePrototype")) + : Object(verify_cast<HTML::Window>(realm.global_object()).ensure_web_prototype<WebAssemblyTablePrototype>("WebAssemblyTablePrototype")) , m_address(address) { } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h index d5616de191..2f2706a856 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h @@ -10,8 +10,8 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/VM.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Forward.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp index f90a738d52..78fab5996c 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp +++ b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/WebGLContextEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/WebGL/WebGLContextEvent.h> namespace Web::WebGL { -WebGLContextEvent* WebGLContextEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init) +WebGLContextEvent* WebGLContextEvent::create(HTML::Window& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init) { return window_object.heap().allocate<WebGLContextEvent>(window_object.realm(), window_object, event_name, event_init); } -WebGLContextEvent* WebGLContextEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init) +WebGLContextEvent* WebGLContextEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init) { return create(window_object, event_name, event_init); } -WebGLContextEvent::WebGLContextEvent(Bindings::WindowObject& window_object, FlyString const& type, WebGLContextEventInit const& event_init) +WebGLContextEvent::WebGLContextEvent(HTML::Window& window_object, FlyString const& type, WebGLContextEventInit const& event_init) : DOM::Event(window_object, type, event_init) , m_status_message(event_init.status_message) { diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h index 9404cc93f8..e42c4fd47c 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h +++ b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h @@ -16,18 +16,16 @@ struct WebGLContextEventInit final : public DOM::EventInit { }; class WebGLContextEvent final : public DOM::Event { - JS_OBJECT(WebGLContextEvent, DOM::Event); + WEB_PLATFORM_OBJECT(WebGLContextEvent, DOM::Event); public: - static WebGLContextEvent* create(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init); - static WebGLContextEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init); + static WebGLContextEvent* create(HTML::Window&, FlyString const& type, WebGLContextEventInit const& event_init); + static WebGLContextEvent* create_with_global_object(HTML::Window&, FlyString const& type, WebGLContextEventInit const& event_init); - WebGLContextEvent(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init); + WebGLContextEvent(HTML::Window&, FlyString const& type, WebGLContextEventInit const& event_init); virtual ~WebGLContextEvent() override; - WebGLContextEvent& impl() { return *this; } - String const& status_message() const { return m_status_message; } private: diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp index 85fb40bfd4..5848200053 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp +++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp @@ -17,7 +17,7 @@ static void fire_webgl_context_event(HTML::HTMLCanvasElement& canvas_element, Fl { // To fire a WebGL context event named e means that an event using the WebGLContextEvent interface, with its type attribute [DOM4] initialized to e, its cancelable attribute initialized to true, and its isTrusted attribute [DOM4] initialized to true, is to be dispatched at the given object. // FIXME: Consider setting a status message. - auto event = WebGLContextEvent::create(canvas_element.document().preferred_window_object(), type, WebGLContextEventInit {}); + auto event = WebGLContextEvent::create(canvas_element.document().window(), type, WebGLContextEventInit {}); event->set_is_trusted(true); event->set_cancelable(true); canvas_element.dispatch_event(*event); @@ -33,8 +33,7 @@ static void fire_webgl_context_creation_error(HTML::HTMLCanvasElement& canvas_el JS::ThrowCompletionOr<RefPtr<WebGLRenderingContext>> WebGLRenderingContext::create(HTML::HTMLCanvasElement& canvas_element, JS::Value options) { // We should be coming here from getContext being called on a wrapped <canvas> element. - VERIFY(canvas_element.wrapper()); - auto context_attributes = TRY(convert_value_to_context_attributes_dictionary(canvas_element.wrapper()->vm(), options)); + auto context_attributes = TRY(convert_value_to_context_attributes_dictionary(canvas_element.vm(), options)); bool created_bitmap = canvas_element.create_bitmap(/* minimum_width= */ 1, /* minimum_height= */ 1); if (!created_bitmap) { diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp index aaf6ffe8cf..3ed7f77264 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp +++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp @@ -12,7 +12,7 @@ namespace Web::WebGL { WebGLRenderingContextBase::WebGLRenderingContextBase(HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<GL::GLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters) - : RefCountForwarder(canvas_element) + : m_canvas_element(canvas_element) , m_context(move(context)) , m_context_creation_parameters(move(context_creation_parameters)) , m_actual_context_parameters(move(actual_context_parameters)) @@ -69,17 +69,17 @@ void WebGLRenderingContextBase::present() HTML::HTMLCanvasElement& WebGLRenderingContextBase::canvas_element() { - return ref_count_target(); + return *m_canvas_element; } HTML::HTMLCanvasElement const& WebGLRenderingContextBase::canvas_element() const { - return ref_count_target(); + return *m_canvas_element; } -NonnullRefPtr<HTML::HTMLCanvasElement> WebGLRenderingContextBase::canvas_for_binding() const +JS::NonnullGCPtr<HTML::HTMLCanvasElement> WebGLRenderingContextBase::canvas_for_binding() const { - return canvas_element(); + return *m_canvas_element; } void WebGLRenderingContextBase::needs_to_present() diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h index 927d7af669..7a5b74c8ee 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h +++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h @@ -16,14 +16,14 @@ namespace Web::WebGL { class WebGLRenderingContextBase - : public RefCountForwarder<HTML::HTMLCanvasElement> + : public RefCounted<WebGLRenderingContextBase> , public Weakable<WebGLRenderingContextBase> { public: virtual ~WebGLRenderingContextBase(); void present(); - NonnullRefPtr<HTML::HTMLCanvasElement> canvas_for_binding() const; + JS::NonnullGCPtr<HTML::HTMLCanvasElement> canvas_for_binding() const; bool is_context_lost() const; @@ -65,6 +65,8 @@ protected: WebGLRenderingContextBase(HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<GL::GLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters); private: + JS::Handle<HTML::HTMLCanvasElement> m_canvas_element; + NonnullOwnPtr<GL::GLContext> m_context; // https://www.khronos.org/registry/webgl/specs/latest/1.0/#context-creation-parameters diff --git a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp index 211d82aae2..69e0ba1548 100644 --- a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp +++ b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp @@ -8,7 +8,7 @@ #include <LibJS/Parser.h> #include <LibJS/Runtime/ArrayBuffer.h> #include <LibJS/Runtime/FunctionObject.h> -#include <LibWeb/Bindings/WebSocketWrapper.h> +#include <LibWeb/Bindings/WebSocketPrototype.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> @@ -48,7 +48,7 @@ WebSocketClientSocket::~WebSocketClientSocket() = default; WebSocketClientManager::WebSocketClientManager() = default; // https://websockets.spec.whatwg.org/#dom-websocket-websocket -DOM::ExceptionOr<NonnullRefPtr<WebSocket>> WebSocket::create_with_global_object(Bindings::WindowObject& window, String const& url) +DOM::ExceptionOr<JS::NonnullGCPtr<WebSocket>> WebSocket::create_with_global_object(HTML::Window& window, String const& url) { AK::URL url_record(url); if (!url_record.is_valid()) @@ -59,35 +59,37 @@ DOM::ExceptionOr<NonnullRefPtr<WebSocket>> WebSocket::create_with_global_object( return DOM::SyntaxError::create("Presence of URL fragment is invalid"); // 5. If `protocols` is a string, set `protocols` to a sequence consisting of just that string // 6. If any of the values in `protocols` occur more than once or otherwise fail to match the requirements, throw SyntaxError - return WebSocket::create(window.impl(), url_record); + return JS::NonnullGCPtr(*window.heap().allocate<WebSocket>(window.realm(), window.impl(), url_record)); } WebSocket::WebSocket(HTML::Window& window, AK::URL& url) - : EventTarget() + : EventTarget(window.realm()) , m_window(window) { + set_prototype(&window.ensure_web_prototype<Bindings::WebSocketPrototype>("WebSocket")); + // FIXME: Integrate properly with FETCH as per https://fetch.spec.whatwg.org/#websocket-opening-handshake auto origin_string = m_window->associated_document().origin().serialize(); m_websocket = WebSocketClientManager::the().connect(url, origin_string); - m_websocket->on_open = [weak_this = make_weak_ptr()] { + m_websocket->on_open = [weak_this = make_weak_ptr<WebSocket>()] { if (!weak_this) return; auto& websocket = const_cast<WebSocket&>(*weak_this); websocket.on_open(); }; - m_websocket->on_message = [weak_this = make_weak_ptr()](auto message) { + m_websocket->on_message = [weak_this = make_weak_ptr<WebSocket>()](auto message) { if (!weak_this) return; auto& websocket = const_cast<WebSocket&>(*weak_this); websocket.on_message(move(message.data), message.is_text); }; - m_websocket->on_close = [weak_this = make_weak_ptr()](auto code, auto reason, bool was_clean) { + m_websocket->on_close = [weak_this = make_weak_ptr<WebSocket>()](auto code, auto reason, bool was_clean) { if (!weak_this) return; auto& websocket = const_cast<WebSocket&>(*weak_this); websocket.on_close(code, reason, was_clean); }; - m_websocket->on_error = [weak_this = make_weak_ptr()](auto) { + m_websocket->on_error = [weak_this = make_weak_ptr<WebSocket>()](auto) { if (!weak_this) return; auto& websocket = const_cast<WebSocket&>(*weak_this); @@ -97,6 +99,12 @@ WebSocket::WebSocket(HTML::Window& window, AK::URL& url) WebSocket::~WebSocket() = default; +void WebSocket::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_window.ptr()); +} + // https://websockets.spec.whatwg.org/#dom-websocket-readystate WebSocket::ReadyState WebSocket::ready_state() const { @@ -172,13 +180,13 @@ void WebSocket::on_open() // 1. Change the readyState attribute's value to OPEN (1). // 2. Change the extensions attribute's value to the extensions in use, if it is not the null value. [WSP] // 3. Change the protocol attribute's value to the subprotocol in use, if it is not the null value. [WSP] - dispatch_event(*DOM::Event::create(*m_window->wrapper(), HTML::EventNames::open)); + dispatch_event(*DOM::Event::create(*m_window, HTML::EventNames::open)); } // https://websockets.spec.whatwg.org/#feedback-from-the-protocol void WebSocket::on_error() { - dispatch_event(*DOM::Event::create(*m_window->wrapper(), HTML::EventNames::error)); + dispatch_event(*DOM::Event::create(*m_window, HTML::EventNames::error)); } // https://websockets.spec.whatwg.org/#feedback-from-the-protocol @@ -190,7 +198,7 @@ void WebSocket::on_close(u16 code, String reason, bool was_clean) event_init.was_clean = was_clean; event_init.code = code; event_init.reason = move(reason); - dispatch_event(*HTML::CloseEvent::create(*m_window->wrapper(), HTML::EventNames::close, event_init)); + dispatch_event(*HTML::CloseEvent::create(*m_window, HTML::EventNames::close, event_init)); } // https://websockets.spec.whatwg.org/#feedback-from-the-protocol @@ -201,9 +209,9 @@ void WebSocket::on_message(ByteBuffer message, bool is_text) if (is_text) { auto text_message = String(ReadonlyBytes(message)); HTML::MessageEventInit event_init; - event_init.data = JS::js_string(wrapper()->vm(), text_message); + event_init.data = JS::js_string(vm(), text_message); event_init.origin = url(); - dispatch_event(*HTML::MessageEvent::create(*m_window->wrapper(), HTML::EventNames::message, event_init)); + dispatch_event(*HTML::MessageEvent::create(*m_window, HTML::EventNames::message, event_init)); return; } @@ -212,12 +220,10 @@ void WebSocket::on_message(ByteBuffer message, bool is_text) TODO(); } else if (m_binary_type == "arraybuffer") { // type indicates that the data is Binary and binaryType is "arraybuffer" - auto& vm = wrapper()->vm(); - auto& realm = *vm.current_realm(); HTML::MessageEventInit event_init; - event_init.data = JS::ArrayBuffer::create(realm, message); + event_init.data = JS::ArrayBuffer::create(realm(), message); event_init.origin = url(); - dispatch_event(*HTML::MessageEvent::create(*m_window->wrapper(), HTML::EventNames::message, event_init)); + dispatch_event(*HTML::MessageEvent::create(*m_window, HTML::EventNames::message, event_init)); return; } @@ -225,11 +231,6 @@ void WebSocket::on_message(ByteBuffer message, bool is_text) TODO(); } -JS::Object* WebSocket::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - #undef __ENUMERATE #define __ENUMERATE(attribute_name, event_name) \ void WebSocket::set_##attribute_name(Bindings::CallbackType* value) \ diff --git a/Userland/Libraries/LibWeb/WebSockets/WebSocket.h b/Userland/Libraries/LibWeb/WebSockets/WebSocket.h index f082d28424..363eca5f46 100644 --- a/Userland/Libraries/LibWeb/WebSockets/WebSocket.h +++ b/Userland/Libraries/LibWeb/WebSockets/WebSocket.h @@ -7,15 +7,13 @@ #pragma once #include <AK/ByteBuffer.h> -#include <AK/RefCounted.h> #include <AK/URL.h> -#include <AK/Weakable.h> #include <LibCore/Object.h> -#include <LibWeb/Bindings/WindowObject.h> -#include <LibWeb/Bindings/Wrappable.h> +#include <LibWeb/Bindings/PlatformObject.h> #include <LibWeb/DOM/EventTarget.h> #include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/Forward.h> +#include <LibWeb/HTML/Window.h> #define ENUMERATE_WEBSOCKET_EVENT_HANDLERS(E) \ E(onerror, HTML::EventNames::error) \ @@ -28,11 +26,9 @@ namespace Web::WebSockets { class WebSocketClientSocket; class WebSocketClientManager; -class WebSocket final - : public RefCounted<WebSocket> - , public Weakable<WebSocket> - , public DOM::EventTarget - , public Bindings::Wrappable { +class WebSocket final : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(WebSocket, DOM::EventTarget); + public: enum class ReadyState : u16 { Connecting = 0, @@ -41,20 +37,10 @@ public: Closed = 3, }; - using WrapperType = Bindings::WebSocketWrapper; - - static NonnullRefPtr<WebSocket> create(HTML::Window& window, AK::URL& url) - { - return adopt_ref(*new WebSocket(window, url)); - } - - static DOM::ExceptionOr<NonnullRefPtr<WebSocket>> create_with_global_object(Bindings::WindowObject& window, String const& url); + static DOM::ExceptionOr<JS::NonnullGCPtr<WebSocket>> create_with_global_object(HTML::Window&, String const& url); virtual ~WebSocket() override; - using RefCounted::ref; - using RefCounted::unref; - String url() const { return m_url.to_string(); } #undef __ENUMERATE @@ -75,10 +61,6 @@ public: DOM::ExceptionOr<void> send(String const& data); private: - virtual void ref_event_target() override { ref(); } - virtual void unref_event_target() override { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; - void on_open(); void on_message(ByteBuffer message, bool is_text); void on_error(); @@ -86,7 +68,9 @@ private: explicit WebSocket(HTML::Window&, AK::URL&); - NonnullRefPtr<HTML::Window> m_window; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr<HTML::Window> m_window; AK::URL m_url; String m_binary_type { "blob" }; @@ -142,3 +126,5 @@ protected: }; } + +WRAPPER_HACK(WebSocket, Web::WebSockets) diff --git a/Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp b/Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp index 975c69aff7..7157babd19 100644 --- a/Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp +++ b/Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp @@ -5,22 +5,22 @@ */ #include <LibWeb/Bindings/ProgressEventPrototype.h> -#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/XHR/ProgressEvent.h> namespace Web::XHR { -ProgressEvent* ProgressEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init) +ProgressEvent* ProgressEvent::create(HTML::Window& window_object, FlyString const& event_name, ProgressEventInit const& event_init) { return window_object.heap().allocate<ProgressEvent>(window_object.realm(), window_object, event_name, event_init); } -ProgressEvent* ProgressEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init) +ProgressEvent* ProgressEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, ProgressEventInit const& event_init) { return create(window_object, event_name, event_init); } -ProgressEvent::ProgressEvent(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init) +ProgressEvent::ProgressEvent(HTML::Window& window_object, FlyString const& event_name, ProgressEventInit const& event_init) : Event(window_object, event_name, event_init) , m_length_computable(event_init.length_computable) , m_loaded(event_init.loaded) diff --git a/Userland/Libraries/LibWeb/XHR/ProgressEvent.h b/Userland/Libraries/LibWeb/XHR/ProgressEvent.h index 1c284f01c0..44d8312b17 100644 --- a/Userland/Libraries/LibWeb/XHR/ProgressEvent.h +++ b/Userland/Libraries/LibWeb/XHR/ProgressEvent.h @@ -20,18 +20,16 @@ struct ProgressEventInit : public DOM::EventInit { }; class ProgressEvent final : public DOM::Event { - JS_OBJECT(ProgressEvent, DOM::Event); + WEB_PLATFORM_OBJECT(ProgressEvent, DOM::Event); public: - static ProgressEvent* create(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init); - static ProgressEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init); + static ProgressEvent* create(HTML::Window&, FlyString const& event_name, ProgressEventInit const& event_init); + static ProgressEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, ProgressEventInit const& event_init); - ProgressEvent(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init); + ProgressEvent(HTML::Window&, FlyString const& event_name, ProgressEventInit const& event_init); virtual ~ProgressEvent() override; - ProgressEvent& impl() { return *this; } - bool length_computable() const { return m_length_computable; } u64 loaded() const { return m_loaded; } u64 total() const { return m_total; } diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index d17665b99a..c2738a4ba1 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -16,8 +16,9 @@ #include <LibJS/Runtime/FunctionObject.h> #include <LibJS/Runtime/GlobalObject.h> #include <LibTextCodec/Decoder.h> +#include <LibWeb/Bindings/BlobWrapper.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> -#include <LibWeb/Bindings/XMLHttpRequestWrapper.h> +#include <LibWeb/Bindings/XMLHttpRequestPrototype.h> #include <LibWeb/DOM/DOMException.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> @@ -40,19 +41,31 @@ namespace Web::XHR { +JS::NonnullGCPtr<XMLHttpRequest> XMLHttpRequest::create_with_global_object(HTML::Window& window) +{ + return *window.heap().allocate<XMLHttpRequest>(window.realm(), window); +} + XMLHttpRequest::XMLHttpRequest(HTML::Window& window) - : XMLHttpRequestEventTarget() + : XMLHttpRequestEventTarget(window.realm()) , m_window(window) , m_response_type(Bindings::XMLHttpRequestResponseType::Empty) { + set_prototype(&window.ensure_web_prototype<Bindings::XMLHttpRequestPrototype>("XMLHttpRequest")); } XMLHttpRequest::~XMLHttpRequest() = default; +void XMLHttpRequest::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_window.ptr()); +} + void XMLHttpRequest::set_ready_state(ReadyState ready_state) { m_ready_state = ready_state; - dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), EventNames::readystatechange)); + dispatch_event(*DOM::Event::create(global_object(), EventNames::readystatechange)); } void XMLHttpRequest::fire_progress_event(String const& event_name, u64 transmitted, u64 length) @@ -61,7 +74,7 @@ void XMLHttpRequest::fire_progress_event(String const& event_name, u64 transmitt event_init.length_computable = true; event_init.loaded = transmitted; event_init.total = length; - dispatch_event(*ProgressEvent::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), event_name, event_init)); + dispatch_event(*ProgressEvent::create(global_object(), event_name, event_init)); } // https://xhr.spec.whatwg.org/#dom-xmlhttprequest-responsetext @@ -81,17 +94,14 @@ DOM::ExceptionOr<String> XMLHttpRequest::response_text() const // https://xhr.spec.whatwg.org/#response DOM::ExceptionOr<JS::Value> XMLHttpRequest::response() { - auto& vm = wrapper()->vm(); - auto& realm = *vm.current_realm(); - // 1. If this’s response type is the empty string or "text", then: if (m_response_type == Bindings::XMLHttpRequestResponseType::Empty || m_response_type == Bindings::XMLHttpRequestResponseType::Text) { // 1. If this’s state is not loading or done, then return the empty string. if (m_ready_state != ReadyState::Loading && m_ready_state != ReadyState::Done) - return JS::Value(JS::js_string(vm, "")); + return JS::Value(JS::js_string(vm(), "")); // 2. Return the result of getting a text response for this. - return JS::Value(JS::js_string(vm, get_text_response())); + return JS::Value(JS::js_string(vm(), get_text_response())); } // 2. If this’s state is not done, then return null. if (m_ready_state != ReadyState::Done) @@ -108,7 +118,7 @@ DOM::ExceptionOr<JS::Value> XMLHttpRequest::response() // 5. If this’s response type is "arraybuffer", if (m_response_type == Bindings::XMLHttpRequestResponseType::Arraybuffer) { // then set this’s response object to a new ArrayBuffer object representing this’s received bytes. If this throws an exception, then set this’s response object to failure and return null. - auto buffer_result = JS::ArrayBuffer::create(realm, m_received_bytes.size()); + auto buffer_result = JS::ArrayBuffer::create(realm(), m_received_bytes.size()); if (buffer_result.is_error()) { m_response_object = Failure(); return JS::js_null(); @@ -122,7 +132,7 @@ DOM::ExceptionOr<JS::Value> XMLHttpRequest::response() else if (m_response_type == Bindings::XMLHttpRequestResponseType::Blob) { auto blob_part = TRY_OR_RETURN_OOM(try_make_ref_counted<FileAPI::Blob>(m_received_bytes, get_final_mime_type().type())); auto blob = TRY(FileAPI::Blob::create(Vector<FileAPI::BlobPart> { move(blob_part) })); - m_response_object = JS::make_handle(JS::Value(blob->create_wrapper(realm))); + m_response_object = JS::make_handle(JS::Value(wrap(realm(), *blob))); } // 7. Otherwise, if this’s response type is "document", set a document response for this. else if (m_response_type == Bindings::XMLHttpRequestResponseType::Document) { @@ -142,7 +152,7 @@ DOM::ExceptionOr<JS::Value> XMLHttpRequest::response() // 3. Let jsonObject be the result of running parse JSON from bytes on this’s received bytes. If that threw an exception, then return null. TextCodec::UTF8Decoder decoder; - auto json_object_result = JS::call(vm, realm.intrinsics().json_parse_function(), JS::js_undefined(), JS::js_string(vm, decoder.to_utf8({ m_received_bytes.data(), m_received_bytes.size() }))); + auto json_object_result = JS::call(vm(), realm().intrinsics().json_parse_function(), JS::js_undefined(), JS::js_string(vm(), decoder.to_utf8({ m_received_bytes.data(), m_received_bytes.size() }))); if (json_object_result.is_error()) return JS::Value(JS::js_null()); @@ -372,7 +382,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::open(String const& method_string, String auto& settings_object = m_window->associated_document().relevant_settings_object(); // 2. If settingsObject has a responsible document and it is not fully active, then throw an "InvalidStateError" DOMException. - if (!settings_object.responsible_document().is_null() && !settings_object.responsible_document()->is_active()) + if (settings_object.responsible_document() && !settings_object.responsible_document()->is_active()) return DOM::InvalidStateError::create("Invalid state: Responsible document is not fully active."); // 3. If method is not a method, then throw a "SyntaxError" DOMException. @@ -468,7 +478,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod if (should_enforce_same_origin_policy && !m_window->associated_document().origin().is_same_origin(request_url_origin)) { dbgln("XHR failed to load: Same-Origin Policy violation: {} may not load {}", m_window->associated_document().url(), request_url); set_ready_state(ReadyState::Done); - dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), HTML::EventNames::error)); + dispatch_event(*DOM::Event::create(global_object(), HTML::EventNames::error)); return {}; } @@ -518,8 +528,8 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod // See: https://github.com/whatwg/fetch/issues/1142 ResourceLoader::the().load( request, - [weak_this = make_weak_ptr()](auto data, auto& response_headers, auto status_code) { - auto strong_this = weak_this.strong_ref(); + [weak_this = make_weak_ptr<XMLHttpRequest>()](auto data, auto& response_headers, auto status_code) { + JS::GCPtr<XMLHttpRequest> strong_this = weak_this.ptr(); if (!strong_this) return; auto& xhr = const_cast<XMLHttpRequest&>(*weak_this); @@ -538,27 +548,27 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod xhr.m_status = status_code.value_or(0); xhr.m_response_headers = move(response_headers); xhr.m_send = false; - xhr.dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(xhr.wrapper()->global_object()), EventNames::readystatechange)); + xhr.dispatch_event(*DOM::Event::create(xhr.global_object(), EventNames::readystatechange)); xhr.fire_progress_event(EventNames::load, transmitted, length); xhr.fire_progress_event(EventNames::loadend, transmitted, length); }, - [weak_this = make_weak_ptr()](auto& error, auto status_code) { + [weak_this = make_weak_ptr<XMLHttpRequest>()](auto& error, auto status_code) { dbgln("XHR failed to load: {}", error); - auto strong_this = weak_this.strong_ref(); + JS::GCPtr<XMLHttpRequest> strong_this = weak_this.ptr(); if (!strong_this) return; auto& xhr = const_cast<XMLHttpRequest&>(*strong_this); xhr.set_ready_state(ReadyState::Done); xhr.set_status(status_code.value_or(0)); - xhr.dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(xhr.wrapper()->global_object()), HTML::EventNames::error)); + xhr.dispatch_event(*DOM::Event::create(xhr.global_object(), HTML::EventNames::error)); }, m_timeout, - [weak_this = make_weak_ptr()] { - auto strong_this = weak_this.strong_ref(); + [weak_this = make_weak_ptr<XMLHttpRequest>()] { + JS::GCPtr<XMLHttpRequest> strong_this = weak_this.ptr(); if (!strong_this) return; auto& xhr = const_cast<XMLHttpRequest&>(*strong_this); - xhr.dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(xhr.wrapper()->global_object()), EventNames::timeout)); + xhr.dispatch_event(*DOM::Event::create(xhr.global_object(), EventNames::timeout)); }); } else { TODO(); @@ -566,11 +576,6 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod return {}; } -JS::Object* XMLHttpRequest::create_wrapper(JS::Realm& realm) -{ - return wrap(realm, *this); -} - Bindings::CallbackType* XMLHttpRequest::onreadystatechange() { return event_handler_attribute(Web::XHR::EventNames::readystatechange); @@ -621,7 +626,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::set_timeout(u32 timeout) { // 1. If the current global object is a Window object and this’s synchronous flag is set, // then throw an "InvalidAccessError" DOMException. - if (is<Bindings::WindowObject>(HTML::current_global_object()) && m_synchronous) + if (is<HTML::Window>(HTML::current_global_object()) && m_synchronous) return DOM::InvalidAccessError::create("Use of XMLHttpRequest's timeout attribute is not supported in the synchronous mode in window context."); // 2. Set this’s timeout to the given value. diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h index bba94589bf..efd29f8cf8 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h @@ -11,12 +11,12 @@ #include <AK/RefCounted.h> #include <AK/URL.h> #include <AK/Weakable.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/Bindings/Wrappable.h> #include <LibWeb/DOM/EventTarget.h> #include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h> #include <LibWeb/Fetch/Infrastructure/HTTP/Statuses.h> +#include <LibWeb/HTML/Window.h> #include <LibWeb/MimeSniff/MimeType.h> #include <LibWeb/URL/URLSearchParams.h> #include <LibWeb/XHR/XMLHttpRequestEventTarget.h> @@ -26,10 +26,9 @@ namespace Web::XHR { // https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit using XMLHttpRequestBodyInit = Variant<NonnullRefPtr<FileAPI::Blob>, JS::Handle<JS::Object>, NonnullRefPtr<URL::URLSearchParams>, String>; -class XMLHttpRequest final - : public RefCounted<XMLHttpRequest> - , public Weakable<XMLHttpRequest> - , public XMLHttpRequestEventTarget { +class XMLHttpRequest final : public XMLHttpRequestEventTarget { + WEB_PLATFORM_OBJECT(XMLHttpRequest, XMLHttpRequestEventTarget); + public: enum class ReadyState : u16 { Unsent = 0, @@ -39,22 +38,10 @@ public: Done = 4, }; - using WrapperType = Bindings::XMLHttpRequestWrapper; - - static NonnullRefPtr<XMLHttpRequest> create(HTML::Window& window) - { - return adopt_ref(*new XMLHttpRequest(window)); - } - static NonnullRefPtr<XMLHttpRequest> create_with_global_object(Bindings::WindowObject& window) - { - return XMLHttpRequest::create(window.impl()); - } + static JS::NonnullGCPtr<XMLHttpRequest> create_with_global_object(HTML::Window&); virtual ~XMLHttpRequest() override; - using RefCounted::ref; - using RefCounted::unref; - ReadyState ready_state() const { return m_ready_state; }; Fetch::Infrastructure::Status status() const { return m_status; }; DOM::ExceptionOr<String> response_text() const; @@ -80,9 +67,7 @@ public: u32 timeout() const; private: - virtual void ref_event_target() override { ref(); } - virtual void unref_event_target() override { unref(); } - virtual JS::Object* create_wrapper(JS::Realm&) override; + virtual void visit_edges(Cell::Visitor&) override; void set_ready_state(ReadyState); void set_status(Fetch::Infrastructure::Status status) { m_status = status; } @@ -96,7 +81,7 @@ private: explicit XMLHttpRequest(HTML::Window&); - NonnullRefPtr<HTML::Window> m_window; + JS::NonnullGCPtr<HTML::Window> m_window; ReadyState m_ready_state { ReadyState::Unsent }; Fetch::Infrastructure::Status m_status { 0 }; @@ -128,3 +113,5 @@ private: }; } + +WRAPPER_HACK(XMLHttpRequest, Web::XHR) diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h b/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h index 5307dd558d..41e4c456da 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h @@ -6,7 +6,6 @@ #pragma once -#include <LibWeb/Bindings/EventTargetWrapperFactory.h> #include <LibWeb/DOM/EventDispatcher.h> #include <LibWeb/DOM/EventTarget.h> @@ -21,12 +20,10 @@ namespace Web::XHR { E(ontimeout, XHR::EventNames::timeout) \ E(onloadend, XHR::EventNames::loadend) -class XMLHttpRequestEventTarget - : public DOM::EventTarget - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::XMLHttpRequestEventTargetWrapper; +class XMLHttpRequestEventTarget : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(XMLHttpRequestEventTarget, DOM::EventTarget); +public: virtual ~XMLHttpRequestEventTarget() override {}; #undef __ENUMERATE @@ -37,16 +34,12 @@ public: #undef __ENUMERATE protected: - XMLHttpRequestEventTarget() - : DOM::EventTarget() - { - } - -private: - virtual JS::Object* create_wrapper(JS::Realm& realm) override + XMLHttpRequestEventTarget(JS::Realm& realm) + : DOM::EventTarget(realm) { - return wrap(realm, *this); } }; } + +WRAPPER_HACK(XMLHttpRequestEventTarget, Web::XHR) diff --git a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp index 6f92886970..067bb0fb93 100644 --- a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp +++ b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/DOM/Event.h> #include <LibWeb/HTML/HTMLTemplateElement.h> #include <LibWeb/HTML/Window.h> #include <LibWeb/XML/XMLDocumentBuilder.h> @@ -160,22 +161,22 @@ void XMLDocumentBuilder::document_end() // 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. HTML::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(); }); // 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(); // 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(); } // 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 = NonnullRefPtr(m_document)]() mutable { + old_queue_global_task_with_document(HTML::Task::Source::DOMManipulation, m_document, [document = JS::make_handle(m_document)]() mutable { // FIXME: 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. // 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); @@ -197,7 +198,7 @@ void XMLDocumentBuilder::document_end() }); // 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 = NonnullRefPtr(m_document)]() mutable { + old_queue_global_task_with_document(HTML::Task::Source::DOMManipulation, m_document, [document = JS::make_handle(m_document)]() mutable { // Update the current document readiness to "complete". document->update_readiness(HTML::DocumentReadyState::Complete); @@ -206,14 +207,14 @@ void XMLDocumentBuilder::document_end() return; // Let window be the Document's relevant global object. - NonnullRefPtr<HTML::Window> window = document->window(); + JS::NonnullGCPtr<HTML::Window> window = document->window(); // FIXME: Set the Document's load timing info's load event start time to the current high resolution time given window. // 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: 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. diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index ac5ad86e92..4a9626be54 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -15,40 +15,40 @@ libweb_js_wrapper(CSS/CSSStyleRule NO_INSTANCE) libweb_js_wrapper(CSS/CSSStyleSheet NO_INSTANCE) libweb_js_wrapper(CSS/CSSSupportsRule NO_INSTANCE) libweb_js_wrapper(CSS/MediaList NO_INSTANCE) -libweb_js_wrapper(CSS/MediaQueryList) +libweb_js_wrapper(CSS/MediaQueryList NO_INSTANCE) libweb_js_wrapper(CSS/MediaQueryListEvent NO_INSTANCE) libweb_js_wrapper(CSS/Screen) libweb_js_wrapper(CSS/StyleSheet NO_INSTANCE) libweb_js_wrapper(CSS/StyleSheetList NO_INSTANCE) libweb_js_wrapper(DOM/AbstractRange NO_INSTANCE) -libweb_js_wrapper(DOM/Attribute) +libweb_js_wrapper(DOM/Attribute NO_INSTANCE) libweb_js_wrapper(DOM/AbortController) -libweb_js_wrapper(DOM/AbortSignal) -libweb_js_wrapper(DOM/CDATASection) -libweb_js_wrapper(DOM/CharacterData) -libweb_js_wrapper(DOM/Comment) +libweb_js_wrapper(DOM/AbortSignal NO_INSTANCE) +libweb_js_wrapper(DOM/CDATASection NO_INSTANCE) +libweb_js_wrapper(DOM/CharacterData NO_INSTANCE) +libweb_js_wrapper(DOM/Comment NO_INSTANCE) libweb_js_wrapper(DOM/CustomEvent NO_INSTANCE) -libweb_js_wrapper(DOM/Document) -libweb_js_wrapper(DOM/DocumentFragment) -libweb_js_wrapper(DOM/DocumentType) +libweb_js_wrapper(DOM/Document NO_INSTANCE) +libweb_js_wrapper(DOM/DocumentFragment NO_INSTANCE) +libweb_js_wrapper(DOM/DocumentType NO_INSTANCE) libweb_js_wrapper(DOM/DOMException) libweb_js_wrapper(DOM/DOMImplementation NO_INSTANCE) libweb_js_wrapper(DOM/DOMTokenList NO_INSTANCE) -libweb_js_wrapper(DOM/Element) +libweb_js_wrapper(DOM/Element NO_INSTANCE) libweb_js_wrapper(DOM/Event NO_INSTANCE) -libweb_js_wrapper(DOM/EventTarget) +libweb_js_wrapper(DOM/EventTarget NO_INSTANCE) libweb_js_wrapper(DOM/HTMLCollection) libweb_js_wrapper(DOM/MutationRecord) libweb_js_wrapper(DOM/MutationObserver) libweb_js_wrapper(DOM/NamedNodeMap NO_INSTANCE) -libweb_js_wrapper(DOM/Node) +libweb_js_wrapper(DOM/Node NO_INSTANCE) libweb_js_wrapper(DOM/NodeIterator NO_INSTANCE) libweb_js_wrapper(DOM/NodeList) -libweb_js_wrapper(DOM/ProcessingInstruction) +libweb_js_wrapper(DOM/ProcessingInstruction NO_INSTANCE) libweb_js_wrapper(DOM/Range NO_INSTANCE) -libweb_js_wrapper(DOM/ShadowRoot) +libweb_js_wrapper(DOM/ShadowRoot NO_INSTANCE) libweb_js_wrapper(DOM/StaticRange NO_INSTANCE) -libweb_js_wrapper(DOM/Text) +libweb_js_wrapper(DOM/Text NO_INSTANCE) libweb_js_wrapper(DOM/TreeWalker NO_INSTANCE) libweb_js_wrapper(DOMParsing/XMLSerializer) libweb_js_wrapper(Encoding/TextDecoder) @@ -68,113 +68,113 @@ libweb_js_wrapper(HTML/DOMParser) libweb_js_wrapper(HTML/DOMStringMap NO_INSTANCE) libweb_js_wrapper(HTML/ErrorEvent NO_INSTANCE) libweb_js_wrapper(HTML/History) -libweb_js_wrapper(HTML/HTMLAnchorElement) -libweb_js_wrapper(HTML/HTMLAreaElement) -libweb_js_wrapper(HTML/HTMLAudioElement) -libweb_js_wrapper(HTML/HTMLBaseElement) -libweb_js_wrapper(HTML/HTMLBodyElement) -libweb_js_wrapper(HTML/HTMLBRElement) -libweb_js_wrapper(HTML/HTMLButtonElement) -libweb_js_wrapper(HTML/HTMLCanvasElement) -libweb_js_wrapper(HTML/HTMLDataElement) -libweb_js_wrapper(HTML/HTMLDataListElement) -libweb_js_wrapper(HTML/HTMLDetailsElement) -libweb_js_wrapper(HTML/HTMLDialogElement) -libweb_js_wrapper(HTML/HTMLDirectoryElement) -libweb_js_wrapper(HTML/HTMLDivElement) -libweb_js_wrapper(HTML/HTMLDListElement) -libweb_js_wrapper(HTML/HTMLElement) -libweb_js_wrapper(HTML/HTMLEmbedElement) -libweb_js_wrapper(HTML/HTMLFieldSetElement) -libweb_js_wrapper(HTML/HTMLFontElement) -libweb_js_wrapper(HTML/HTMLFormElement) -libweb_js_wrapper(HTML/HTMLFrameElement) -libweb_js_wrapper(HTML/HTMLFrameSetElement) -libweb_js_wrapper(HTML/HTMLHeadElement) -libweb_js_wrapper(HTML/HTMLHeadingElement) -libweb_js_wrapper(HTML/HTMLHRElement) -libweb_js_wrapper(HTML/HTMLHtmlElement) -libweb_js_wrapper(HTML/HTMLIFrameElement) -libweb_js_wrapper(HTML/HTMLImageElement) -libweb_js_wrapper(HTML/HTMLInputElement) -libweb_js_wrapper(HTML/HTMLLabelElement) -libweb_js_wrapper(HTML/HTMLLegendElement) -libweb_js_wrapper(HTML/HTMLLIElement) -libweb_js_wrapper(HTML/HTMLLinkElement) -libweb_js_wrapper(HTML/HTMLMapElement) -libweb_js_wrapper(HTML/HTMLMarqueeElement) -libweb_js_wrapper(HTML/HTMLMediaElement) -libweb_js_wrapper(HTML/HTMLMenuElement) -libweb_js_wrapper(HTML/HTMLMetaElement) -libweb_js_wrapper(HTML/HTMLMeterElement) -libweb_js_wrapper(HTML/HTMLModElement) -libweb_js_wrapper(HTML/HTMLObjectElement) -libweb_js_wrapper(HTML/HTMLOListElement) -libweb_js_wrapper(HTML/HTMLOptGroupElement) -libweb_js_wrapper(HTML/HTMLOptionElement) +libweb_js_wrapper(HTML/HTMLAnchorElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLAreaElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLAudioElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLBaseElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLBodyElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLBRElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLButtonElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLCanvasElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLDataElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLDataListElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLDetailsElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLDialogElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLDirectoryElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLDivElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLDListElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLEmbedElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLFieldSetElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLFontElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLFormElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLFrameElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLFrameSetElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLHeadElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLHeadingElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLHRElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLHtmlElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLIFrameElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLImageElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLInputElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLLabelElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLLegendElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLLIElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLLinkElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLMapElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLMarqueeElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLMediaElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLMenuElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLMetaElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLMeterElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLModElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLObjectElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLOListElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLOptGroupElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLOptionElement NO_INSTANCE) libweb_js_wrapper(HTML/HTMLOptionsCollection) -libweb_js_wrapper(HTML/HTMLOutputElement) -libweb_js_wrapper(HTML/HTMLParagraphElement) -libweb_js_wrapper(HTML/HTMLParamElement) -libweb_js_wrapper(HTML/HTMLPictureElement) -libweb_js_wrapper(HTML/HTMLPreElement) -libweb_js_wrapper(HTML/HTMLProgressElement) -libweb_js_wrapper(HTML/HTMLQuoteElement) -libweb_js_wrapper(HTML/HTMLScriptElement) -libweb_js_wrapper(HTML/HTMLSelectElement) -libweb_js_wrapper(HTML/HTMLSlotElement) -libweb_js_wrapper(HTML/HTMLSourceElement) -libweb_js_wrapper(HTML/HTMLSpanElement) -libweb_js_wrapper(HTML/HTMLStyleElement) -libweb_js_wrapper(HTML/HTMLTableCaptionElement) -libweb_js_wrapper(HTML/HTMLTableCellElement) -libweb_js_wrapper(HTML/HTMLTableColElement) -libweb_js_wrapper(HTML/HTMLTableElement) -libweb_js_wrapper(HTML/HTMLTableRowElement) -libweb_js_wrapper(HTML/HTMLTableSectionElement) -libweb_js_wrapper(HTML/HTMLTemplateElement) -libweb_js_wrapper(HTML/HTMLTextAreaElement) -libweb_js_wrapper(HTML/HTMLTimeElement) -libweb_js_wrapper(HTML/HTMLTitleElement) -libweb_js_wrapper(HTML/HTMLTrackElement) -libweb_js_wrapper(HTML/HTMLUListElement) -libweb_js_wrapper(HTML/HTMLUnknownElement) -libweb_js_wrapper(HTML/HTMLVideoElement) +libweb_js_wrapper(HTML/HTMLOutputElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLParagraphElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLParamElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLPictureElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLPreElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLProgressElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLQuoteElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLScriptElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLSelectElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLSlotElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLSourceElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLSpanElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLStyleElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTableCaptionElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTableCellElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTableColElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTableElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTableRowElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTableSectionElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTemplateElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTextAreaElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTimeElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTitleElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLTrackElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLUListElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLUnknownElement NO_INSTANCE) +libweb_js_wrapper(HTML/HTMLVideoElement NO_INSTANCE) libweb_js_wrapper(HTML/ImageData) libweb_js_wrapper(HTML/MessageChannel) libweb_js_wrapper(HTML/MessageEvent NO_INSTANCE) -libweb_js_wrapper(HTML/MessagePort) +libweb_js_wrapper(HTML/MessagePort NO_INSTANCE) libweb_js_wrapper(HTML/PageTransitionEvent NO_INSTANCE) libweb_js_wrapper(HTML/Path2D) libweb_js_wrapper(HTML/PromiseRejectionEvent NO_INSTANCE) libweb_js_wrapper(HTML/Storage) libweb_js_wrapper(HTML/SubmitEvent NO_INSTANCE) libweb_js_wrapper(HTML/TextMetrics) -libweb_js_wrapper(HTML/Worker) -libweb_js_wrapper(HTML/WorkerGlobalScope) +libweb_js_wrapper(HTML/Worker NO_INSTANCE) +libweb_js_wrapper(HTML/WorkerGlobalScope NO_INSTANCE) libweb_js_wrapper(HTML/WorkerLocation) libweb_js_wrapper(HTML/WorkerNavigator) -libweb_js_wrapper(HighResolutionTime/Performance) +libweb_js_wrapper(HighResolutionTime/Performance NO_INSTANCE) libweb_js_wrapper(IntersectionObserver/IntersectionObserver) libweb_js_wrapper(NavigationTiming/PerformanceTiming) libweb_js_wrapper(RequestIdleCallback/IdleDeadline) libweb_js_wrapper(ResizeObserver/ResizeObserver) libweb_js_wrapper(SVG/SVGAnimatedLength) -libweb_js_wrapper(SVG/SVGClipPathElement) -libweb_js_wrapper(SVG/SVGDefsElement) -libweb_js_wrapper(SVG/SVGElement) -libweb_js_wrapper(SVG/SVGGeometryElement) -libweb_js_wrapper(SVG/SVGGraphicsElement) -libweb_js_wrapper(SVG/SVGCircleElement) -libweb_js_wrapper(SVG/SVGEllipseElement) +libweb_js_wrapper(SVG/SVGClipPathElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGDefsElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGGeometryElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGGraphicsElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGCircleElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGEllipseElement NO_INSTANCE) libweb_js_wrapper(SVG/SVGLength) -libweb_js_wrapper(SVG/SVGLineElement) -libweb_js_wrapper(SVG/SVGPathElement) -libweb_js_wrapper(SVG/SVGPolygonElement) -libweb_js_wrapper(SVG/SVGPolylineElement) -libweb_js_wrapper(SVG/SVGRectElement) -libweb_js_wrapper(SVG/SVGSVGElement) -libweb_js_wrapper(SVG/SVGTextContentElement) +libweb_js_wrapper(SVG/SVGLineElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGPathElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGPolygonElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGPolylineElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGRectElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGSVGElement NO_INSTANCE) +libweb_js_wrapper(SVG/SVGTextContentElement NO_INSTANCE) libweb_js_wrapper(Selection/Selection) libweb_js_wrapper(UIEvents/FocusEvent NO_INSTANCE) libweb_js_wrapper(UIEvents/KeyboardEvent NO_INSTANCE) @@ -184,7 +184,7 @@ libweb_js_wrapper(URL/URL) libweb_js_wrapper(URL/URLSearchParams ITERABLE) libweb_js_wrapper(WebGL/WebGLContextEvent NO_INSTANCE) libweb_js_wrapper(WebGL/WebGLRenderingContext) -libweb_js_wrapper(WebSockets/WebSocket) +libweb_js_wrapper(WebSockets/WebSocket NO_INSTANCE) libweb_js_wrapper(XHR/ProgressEvent NO_INSTANCE) -libweb_js_wrapper(XHR/XMLHttpRequest) -libweb_js_wrapper(XHR/XMLHttpRequestEventTarget) +libweb_js_wrapper(XHR/XMLHttpRequest NO_INSTANCE) +libweb_js_wrapper(XHR/XMLHttpRequestEventTarget NO_INSTANCE) diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.cpp b/Userland/Services/WebContent/ConsoleGlobalObject.cpp index 785c1e1855..1402f4a12f 100644 --- a/Userland/Services/WebContent/ConsoleGlobalObject.cpp +++ b/Userland/Services/WebContent/ConsoleGlobalObject.cpp @@ -6,15 +6,12 @@ #include "ConsoleGlobalObject.h" #include <LibJS/Runtime/Completion.h> -#include <LibWeb/Bindings/NodeWrapper.h> -#include <LibWeb/Bindings/NodeWrapperFactory.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/Window.h> namespace WebContent { -ConsoleGlobalObject::ConsoleGlobalObject(JS::Realm& realm, Web::Bindings::WindowObject& parent_object) +ConsoleGlobalObject::ConsoleGlobalObject(JS::Realm& realm, Web::HTML::Window& parent_object) : GlobalObject(realm) , m_window_object(&parent_object) { diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.h b/Userland/Services/WebContent/ConsoleGlobalObject.h index 49118ac68d..10e14b1cf9 100644 --- a/Userland/Services/WebContent/ConsoleGlobalObject.h +++ b/Userland/Services/WebContent/ConsoleGlobalObject.h @@ -9,6 +9,7 @@ #include <LibJS/Forward.h> #include <LibJS/Runtime/Completion.h> #include <LibJS/Runtime/GlobalObject.h> +#include <LibWeb/HTML/Window.h> namespace Web::Bindings { class WindowObject; @@ -20,7 +21,7 @@ class ConsoleGlobalObject final : public JS::GlobalObject { JS_OBJECT(ConsoleGlobalObject, JS::GlobalObject); public: - ConsoleGlobalObject(JS::Realm&, Web::Bindings::WindowObject&); + ConsoleGlobalObject(JS::Realm&, Web::HTML::Window&); virtual void initialize(JS::Realm&) override; virtual ~ConsoleGlobalObject() override = default; @@ -42,7 +43,7 @@ private: // Because $0 is not a nice C++ function name JS_DECLARE_NATIVE_FUNCTION(inspected_node_getter); - Web::Bindings::WindowObject* m_window_object; + Web::HTML::Window* m_window_object; }; } diff --git a/Userland/Services/WebContent/WebContentConsoleClient.cpp b/Userland/Services/WebContent/WebContentConsoleClient.cpp index 1e2218537b..9b4a30b0a4 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.cpp +++ b/Userland/Services/WebContent/WebContentConsoleClient.cpp @@ -9,9 +9,9 @@ #include "WebContentConsoleClient.h" #include <LibJS/Interpreter.h> #include <LibJS/MarkupGenerator.h> -#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/HTML/Scripting/ClassicScript.h> #include <LibWeb/HTML/Scripting/Environments.h> +#include <LibWeb/HTML/Window.h> #include <WebContent/ConsoleGlobalObject.h> namespace WebContent { @@ -25,7 +25,7 @@ WebContentConsoleClient::WebContentConsoleClient(JS::Console& console, WeakPtr<J auto& vm = m_interpreter->vm(); auto& realm = m_interpreter->realm(); - auto& window = static_cast<Web::Bindings::WindowObject&>(realm.global_object()); + auto& window = static_cast<Web::HTML::Window&>(realm.global_object()); auto console_global_object = m_interpreter->heap().allocate_without_realm<ConsoleGlobalObject>(realm, window); |