瀏覽代碼

LibWeb: Make DOMTokenList GC-allocated

Andreas Kling 2 年之前
父節點
當前提交
0176d42f49

+ 17 - 3
Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp

@@ -1,13 +1,17 @@
 /*
 /*
  * Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org>
  * Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org>
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  *
  *
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
 
 
 #include <AK/CharacterTypes.h>
 #include <AK/CharacterTypes.h>
 #include <AK/StringBuilder.h>
 #include <AK/StringBuilder.h>
+#include <LibWeb/Bindings/DOMTokenListPrototype.h>
+#include <LibWeb/Bindings/WindowObject.h>
 #include <LibWeb/DOM/DOMException.h>
 #include <LibWeb/DOM/DOMException.h>
 #include <LibWeb/DOM/DOMTokenList.h>
 #include <LibWeb/DOM/DOMTokenList.h>
+#include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Element.h>
 #include <LibWeb/DOM/Element.h>
 
 
 namespace {
 namespace {
@@ -50,14 +54,16 @@ inline void replace_in_ordered_set(Vector<String>& set, StringView item, String
 
 
 namespace Web::DOM {
 namespace Web::DOM {
 
 
-NonnullRefPtr<DOMTokenList> DOMTokenList::create(Element const& associated_element, FlyString associated_attribute)
+DOMTokenList* DOMTokenList::create(Element const& associated_element, FlyString associated_attribute)
 {
 {
-    return adopt_ref(*new DOMTokenList(associated_element, move(associated_attribute)));
+    auto& realm = associated_element.document().preferred_window_object().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
 // https://dom.spec.whatwg.org/#ref-for-domtokenlist%E2%91%A0%E2%91%A2
 DOMTokenList::DOMTokenList(Element const& associated_element, FlyString associated_attribute)
 DOMTokenList::DOMTokenList(Element const& associated_element, FlyString associated_attribute)
-    : m_associated_element(associated_element)
+    : Bindings::LegacyPlatformObject(associated_element.document().preferred_window_object().ensure_web_prototype<Bindings::DOMTokenListPrototype>("DOMTokenList"))
+    , m_associated_element(associated_element)
     , m_associated_attribute(move(associated_attribute))
     , m_associated_attribute(move(associated_attribute))
 {
 {
     auto value = associated_element.get_attribute(m_associated_attribute);
     auto value = associated_element.get_attribute(m_associated_attribute);
@@ -250,4 +256,12 @@ void DOMTokenList::run_update_steps()
     associated_element->set_attribute(m_associated_attribute, value());
     associated_element->set_attribute(m_associated_attribute, value());
 }
 }
 
 
+JS::Value DOMTokenList::item_value(size_t index) const
+{
+    auto const& string = item(index);
+    if (string.is_null())
+        return JS::js_undefined();
+    return JS::js_string(vm(), string);
+}
+
 }
 }

+ 13 - 14
Userland/Libraries/LibWeb/DOM/DOMTokenList.h

@@ -1,5 +1,6 @@
 /*
 /*
  * Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org>
  * Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org>
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  *
  *
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
@@ -8,29 +9,30 @@
 
 
 #include <AK/FlyString.h>
 #include <AK/FlyString.h>
 #include <AK/Optional.h>
 #include <AK/Optional.h>
-#include <AK/RefCounted.h>
 #include <AK/String.h>
 #include <AK/String.h>
 #include <AK/StringView.h>
 #include <AK/StringView.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
-#include <LibWeb/Bindings/Wrappable.h>
+#include <LibWeb/Bindings/LegacyPlatformObject.h>
 #include <LibWeb/DOM/ExceptionOr.h>
 #include <LibWeb/DOM/ExceptionOr.h>
 #include <LibWeb/Forward.h>
 #include <LibWeb/Forward.h>
 
 
 namespace Web::DOM {
 namespace Web::DOM {
 
 
 // https://dom.spec.whatwg.org/#domtokenlist
 // https://dom.spec.whatwg.org/#domtokenlist
-class DOMTokenList final
-    : public RefCounted<DOMTokenList>
-    , public Bindings::Wrappable {
+class DOMTokenList final : public Bindings::LegacyPlatformObject {
+    JS_OBJECT(DOMTokenList, Bindings::LegacyPlatformObject);
 
 
 public:
 public:
-    using WrapperType = Bindings::DOMTokenListWrapper;
-
-    static NonnullRefPtr<DOMTokenList> create(Element const& associated_element, FlyString associated_attribute);
+    static DOMTokenList* create(Element const& associated_element, FlyString associated_attribute);
+    DOMTokenList(Element const& associated_element, FlyString associated_attribute);
     ~DOMTokenList() = default;
     ~DOMTokenList() = default;
 
 
+    DOMTokenList& impl() { return *this; }
+
     void associated_attribute_changed(StringView value);
     void associated_attribute_changed(StringView value);
-    bool is_supported_property_index(u32 index) const;
+
+    virtual bool is_supported_property_index(u32 index) const override;
+    virtual JS::Value item_value(size_t index) const override;
 
 
     size_t length() const { return m_token_set.size(); }
     size_t length() const { return m_token_set.size(); }
     String const& item(size_t index) const;
     String const& item(size_t index) const;
@@ -44,8 +46,6 @@ public:
     void set_value(String value);
     void set_value(String value);
 
 
 private:
 private:
-    DOMTokenList(Element const& associated_element, FlyString associated_attribute);
-
     ExceptionOr<void> validate_token(StringView token) const;
     ExceptionOr<void> validate_token(StringView token) const;
     void run_update_steps();
     void run_update_steps();
 
 
@@ -57,7 +57,6 @@ private:
 }
 }
 
 
 namespace Web::Bindings {
 namespace Web::Bindings {
-
-DOMTokenListWrapper* wrap(JS::Realm&, DOM::DOMTokenList&);
-
+inline JS::Object* wrap(JS::Realm&, Web::DOM::DOMTokenList& object) { return &object; }
+using DOMTokenListWrapper = Web::DOM::DOMTokenList;
 }
 }

+ 1 - 0
Userland/Libraries/LibWeb/DOM/DOMTokenList.idl

@@ -1,3 +1,4 @@
+[NoInstanceWrapper]
 interface DOMTokenList {
 interface DOMTokenList {
     readonly attribute unsigned long length;
     readonly attribute unsigned long length;
     getter DOMString? item(unsigned long index);
     getter DOMString? item(unsigned long index);

+ 5 - 5
Userland/Libraries/LibWeb/DOM/Element.cpp

@@ -307,7 +307,7 @@ void Element::parse_attribute(FlyString const& name, String const& value)
         for (auto& new_class : new_classes) {
         for (auto& new_class : new_classes) {
             m_classes.unchecked_append(new_class);
             m_classes.unchecked_append(new_class);
         }
         }
-        if (m_class_list)
+        if (m_class_list.cell())
             m_class_list->associated_attribute_changed(value);
             m_class_list->associated_attribute_changed(value);
     } else if (name == HTML::AttributeNames::style) {
     } else if (name == HTML::AttributeNames::style) {
         // https://drafts.csswg.org/cssom/#ref-for-cssstyledeclaration-updating-flag
         // https://drafts.csswg.org/cssom/#ref-for-cssstyledeclaration-updating-flag
@@ -412,11 +412,11 @@ NonnullRefPtr<CSS::StyleProperties> Element::resolved_css_values()
     return properties;
     return properties;
 }
 }
 
 
-RefPtr<DOMTokenList> const& Element::class_list()
+DOMTokenList* Element::class_list()
 {
 {
-    if (!m_class_list)
-        m_class_list = DOMTokenList::create(*this, HTML::AttributeNames::class_);
-    return m_class_list;
+    if (!m_class_list.cell())
+        m_class_list = JS::make_handle(DOMTokenList::create(*this, HTML::AttributeNames::class_));
+    return m_class_list.cell();
 }
 }
 
 
 // https://dom.spec.whatwg.org/#dom-element-matches
 // https://dom.spec.whatwg.org/#dom-element-matches

+ 2 - 2
Userland/Libraries/LibWeb/DOM/Element.h

@@ -62,7 +62,7 @@ public:
     NamedNodeMap const* attributes() const { return m_attributes.cell(); }
     NamedNodeMap const* attributes() const { return m_attributes.cell(); }
     Vector<String> get_attribute_names() const;
     Vector<String> get_attribute_names() const;
 
 
-    RefPtr<DOMTokenList> const& class_list();
+    DOMTokenList* class_list();
 
 
     DOM::ExceptionOr<bool> matches(StringView selectors) const;
     DOM::ExceptionOr<bool> matches(StringView selectors) const;
     DOM::ExceptionOr<DOM::Element const*> closest(StringView selectors) const;
     DOM::ExceptionOr<DOM::Element const*> closest(StringView selectors) const;
@@ -157,7 +157,7 @@ private:
     RefPtr<CSS::StyleProperties> m_computed_css_values;
     RefPtr<CSS::StyleProperties> m_computed_css_values;
     HashMap<FlyString, CSS::StyleProperty> m_custom_properties;
     HashMap<FlyString, CSS::StyleProperty> m_custom_properties;
 
 
-    RefPtr<DOMTokenList> m_class_list;
+    JS::Handle<DOMTokenList> m_class_list;
     Vector<FlyString> m_classes;
     Vector<FlyString> m_classes;
 
 
     RefPtr<ShadowRoot> m_shadow_root;
     RefPtr<ShadowRoot> m_shadow_root;

+ 0 - 1
Userland/Libraries/LibWeb/Forward.h

@@ -471,7 +471,6 @@ class DOMPointReadOnlyWrapper;
 class DOMRectListWrapper;
 class DOMRectListWrapper;
 class DOMRectReadOnlyWrapper;
 class DOMRectReadOnlyWrapper;
 class DOMRectWrapper;
 class DOMRectWrapper;
-class DOMTokenListWrapper;
 class ElementWrapper;
 class ElementWrapper;
 class ErrorEventWrapper;
 class ErrorEventWrapper;
 class EventListenerWrapper;
 class EventListenerWrapper;

+ 1 - 1
Userland/Libraries/LibWeb/idl_files.cmake

@@ -33,7 +33,7 @@ libweb_js_wrapper(DOM/DocumentFragment)
 libweb_js_wrapper(DOM/DocumentType)
 libweb_js_wrapper(DOM/DocumentType)
 libweb_js_wrapper(DOM/DOMException)
 libweb_js_wrapper(DOM/DOMException)
 libweb_js_wrapper(DOM/DOMImplementation)
 libweb_js_wrapper(DOM/DOMImplementation)
-libweb_js_wrapper(DOM/DOMTokenList)
+libweb_js_wrapper(DOM/DOMTokenList NO_INSTANCE)
 libweb_js_wrapper(DOM/Element)
 libweb_js_wrapper(DOM/Element)
 libweb_js_wrapper(DOM/Event)
 libweb_js_wrapper(DOM/Event)
 libweb_js_wrapper(DOM/EventTarget)
 libweb_js_wrapper(DOM/EventTarget)