mirror of
https://github.com/RGBCube/serenity
synced 2025-05-16 19:15:07 +00:00
LibWeb: Make HTMLCollection faster when it only cares about children
Some of the live HTMLCollection only ever contain children of their root node. When we know that's the case, we can avoid doing a full subtree traversal of all descendants and only visit children. This cuts the ECMA262 spec loading time by over 10 seconds. :^)
This commit is contained in:
parent
e31f696ee6
commit
df1bb0ff49
10 changed files with 54 additions and 41 deletions
|
@ -1054,7 +1054,7 @@ void Document::set_hovered_node(Node* node)
|
||||||
|
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::get_elements_by_name(DeprecatedString const& name)
|
JS::NonnullGCPtr<HTMLCollection> Document::get_elements_by_name(DeprecatedString const& name)
|
||||||
{
|
{
|
||||||
return HTMLCollection::create(*this, [name](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [name](Element const& element) {
|
||||||
return element.name() == name;
|
return element.name() == name;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1065,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::get_elements_by_class_name(Deprecated
|
||||||
for (auto& name : class_names.view().split_view(' ')) {
|
for (auto& name : class_names.view().split_view(' ')) {
|
||||||
list_of_class_names.append(FlyString::from_utf8(name).release_value_but_fixme_should_propagate_errors());
|
list_of_class_names.append(FlyString::from_utf8(name).release_value_but_fixme_should_propagate_errors());
|
||||||
}
|
}
|
||||||
return HTMLCollection::create(*this, [list_of_class_names = move(list_of_class_names), quirks_mode = document().in_quirks_mode()](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [list_of_class_names = move(list_of_class_names), quirks_mode = document().in_quirks_mode()](Element const& element) {
|
||||||
for (auto& name : list_of_class_names) {
|
for (auto& name : list_of_class_names) {
|
||||||
if (!element.has_class(name, quirks_mode ? CaseSensitivity::CaseInsensitive : CaseSensitivity::CaseSensitive))
|
if (!element.has_class(name, quirks_mode ? CaseSensitivity::CaseInsensitive : CaseSensitivity::CaseSensitive))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1078,7 +1078,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::get_elements_by_class_name(Deprecated
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::applets()
|
JS::NonnullGCPtr<HTMLCollection> Document::applets()
|
||||||
{
|
{
|
||||||
if (!m_applets)
|
if (!m_applets)
|
||||||
m_applets = HTMLCollection::create(*this, [](auto&) { return false; }).release_value_but_fixme_should_propagate_errors();
|
m_applets = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](auto&) { return false; }).release_value_but_fixme_should_propagate_errors();
|
||||||
return *m_applets;
|
return *m_applets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,7 +1086,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::applets()
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::anchors()
|
JS::NonnullGCPtr<HTMLCollection> Document::anchors()
|
||||||
{
|
{
|
||||||
if (!m_anchors) {
|
if (!m_anchors) {
|
||||||
m_anchors = HTMLCollection::create(*this, [](Element const& element) {
|
m_anchors = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
return is<HTML::HTMLAnchorElement>(element) && element.has_attribute(HTML::AttributeNames::name);
|
return is<HTML::HTMLAnchorElement>(element) && element.has_attribute(HTML::AttributeNames::name);
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -1097,7 +1097,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::anchors()
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::images()
|
JS::NonnullGCPtr<HTMLCollection> Document::images()
|
||||||
{
|
{
|
||||||
if (!m_images) {
|
if (!m_images) {
|
||||||
m_images = HTMLCollection::create(*this, [](Element const& element) {
|
m_images = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
return is<HTML::HTMLImageElement>(element);
|
return is<HTML::HTMLImageElement>(element);
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -1108,7 +1108,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::images()
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::embeds()
|
JS::NonnullGCPtr<HTMLCollection> Document::embeds()
|
||||||
{
|
{
|
||||||
if (!m_embeds) {
|
if (!m_embeds) {
|
||||||
m_embeds = HTMLCollection::create(*this, [](Element const& element) {
|
m_embeds = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
return is<HTML::HTMLEmbedElement>(element);
|
return is<HTML::HTMLEmbedElement>(element);
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -1125,7 +1125,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::plugins()
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::links()
|
JS::NonnullGCPtr<HTMLCollection> Document::links()
|
||||||
{
|
{
|
||||||
if (!m_links) {
|
if (!m_links) {
|
||||||
m_links = HTMLCollection::create(*this, [](Element const& element) {
|
m_links = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
return (is<HTML::HTMLAnchorElement>(element) || is<HTML::HTMLAreaElement>(element)) && element.has_attribute(HTML::AttributeNames::href);
|
return (is<HTML::HTMLAnchorElement>(element) || is<HTML::HTMLAreaElement>(element)) && element.has_attribute(HTML::AttributeNames::href);
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -1136,7 +1136,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::links()
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::forms()
|
JS::NonnullGCPtr<HTMLCollection> Document::forms()
|
||||||
{
|
{
|
||||||
if (!m_forms) {
|
if (!m_forms) {
|
||||||
m_forms = HTMLCollection::create(*this, [](Element const& element) {
|
m_forms = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
return is<HTML::HTMLFormElement>(element);
|
return is<HTML::HTMLFormElement>(element);
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -1147,7 +1147,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::forms()
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::scripts()
|
JS::NonnullGCPtr<HTMLCollection> Document::scripts()
|
||||||
{
|
{
|
||||||
if (!m_scripts) {
|
if (!m_scripts) {
|
||||||
m_scripts = HTMLCollection::create(*this, [](Element const& element) {
|
m_scripts = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
return is<HTML::HTMLScriptElement>(element);
|
return is<HTML::HTMLScriptElement>(element);
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -1158,7 +1158,7 @@ JS::NonnullGCPtr<HTMLCollection> Document::scripts()
|
||||||
JS::NonnullGCPtr<HTMLCollection> Document::all()
|
JS::NonnullGCPtr<HTMLCollection> Document::all()
|
||||||
{
|
{
|
||||||
if (!m_all) {
|
if (!m_all) {
|
||||||
m_all = HTMLCollection::create(*this, [](Element const&) {
|
m_all = HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const&) {
|
||||||
return true;
|
return true;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -2092,7 +2092,7 @@ void Document::check_favicon_after_loading_link_resource()
|
||||||
if (!head_element)
|
if (!head_element)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto favicon_link_elements = HTMLCollection::create(*head_element, [](Element const& element) {
|
auto favicon_link_elements = HTMLCollection::create(*head_element, HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
if (!is<HTML::HTMLLinkElement>(element))
|
if (!is<HTML::HTMLLinkElement>(element))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -631,7 +631,7 @@ JS::NonnullGCPtr<HTMLCollection> Element::get_elements_by_class_name(DeprecatedF
|
||||||
for (auto& name : class_names.view().split_view_if(Infra::is_ascii_whitespace)) {
|
for (auto& name : class_names.view().split_view_if(Infra::is_ascii_whitespace)) {
|
||||||
list_of_class_names.append(FlyString::from_utf8(name).release_value_but_fixme_should_propagate_errors());
|
list_of_class_names.append(FlyString::from_utf8(name).release_value_but_fixme_should_propagate_errors());
|
||||||
}
|
}
|
||||||
return HTMLCollection::create(*this, [list_of_class_names = move(list_of_class_names), quirks_mode = document().in_quirks_mode()](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [list_of_class_names = move(list_of_class_names), quirks_mode = document().in_quirks_mode()](Element const& element) {
|
||||||
for (auto& name : list_of_class_names) {
|
for (auto& name : list_of_class_names) {
|
||||||
if (!element.has_class(name, quirks_mode ? CaseSensitivity::CaseInsensitive : CaseSensitivity::CaseSensitive))
|
if (!element.has_class(name, quirks_mode ? CaseSensitivity::CaseInsensitive : CaseSensitivity::CaseSensitive))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -13,15 +13,16 @@
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
|
||||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLCollection>> HTMLCollection::create(ParentNode& root, Function<bool(Element const&)> filter)
|
WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLCollection>> HTMLCollection::create(ParentNode& root, Scope scope, Function<bool(Element const&)> filter)
|
||||||
{
|
{
|
||||||
return MUST_OR_THROW_OOM(root.heap().allocate<HTMLCollection>(root.realm(), root, move(filter)));
|
return MUST_OR_THROW_OOM(root.heap().allocate<HTMLCollection>(root.realm(), root, scope, move(filter)));
|
||||||
}
|
}
|
||||||
|
|
||||||
HTMLCollection::HTMLCollection(ParentNode& root, Function<bool(Element const&)> filter)
|
HTMLCollection::HTMLCollection(ParentNode& root, Scope scope, Function<bool(Element const&)> filter)
|
||||||
: LegacyPlatformObject(root.realm())
|
: LegacyPlatformObject(root.realm())
|
||||||
, m_root(root)
|
, m_root(root)
|
||||||
, m_filter(move(filter))
|
, m_filter(move(filter))
|
||||||
|
, m_scope(scope)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,11 +45,19 @@ void HTMLCollection::visit_edges(Cell::Visitor& visitor)
|
||||||
JS::MarkedVector<Element*> HTMLCollection::collect_matching_elements() const
|
JS::MarkedVector<Element*> HTMLCollection::collect_matching_elements() const
|
||||||
{
|
{
|
||||||
JS::MarkedVector<Element*> elements(m_root->heap());
|
JS::MarkedVector<Element*> elements(m_root->heap());
|
||||||
m_root->for_each_in_subtree_of_type<Element>([&](auto& element) {
|
if (m_scope == Scope::Descendants) {
|
||||||
if (m_filter(element))
|
m_root->for_each_in_subtree_of_type<Element>([&](auto& element) {
|
||||||
elements.append(const_cast<Element*>(&element));
|
if (m_filter(element))
|
||||||
return IterationDecision::Continue;
|
elements.append(const_cast<Element*>(&element));
|
||||||
});
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
m_root->for_each_child_of_type<Element>([&](auto& element) {
|
||||||
|
if (m_filter(element))
|
||||||
|
elements.append(const_cast<Element*>(&element));
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,11 @@ class HTMLCollection : public Bindings::LegacyPlatformObject {
|
||||||
WEB_PLATFORM_OBJECT(HTMLCollection, Bindings::LegacyPlatformObject);
|
WEB_PLATFORM_OBJECT(HTMLCollection, Bindings::LegacyPlatformObject);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLCollection>> create(ParentNode& root, Function<bool(Element const&)> filter);
|
enum class Scope {
|
||||||
|
Children,
|
||||||
|
Descendants,
|
||||||
|
};
|
||||||
|
static WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLCollection>> create(ParentNode& root, Scope, Function<bool(Element const&)> filter);
|
||||||
|
|
||||||
virtual ~HTMLCollection() override;
|
virtual ~HTMLCollection() override;
|
||||||
|
|
||||||
|
@ -46,7 +50,7 @@ public:
|
||||||
virtual bool is_supported_property_index(u32) const override;
|
virtual bool is_supported_property_index(u32) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HTMLCollection(ParentNode& root, Function<bool(Element const&)> filter);
|
HTMLCollection(ParentNode& root, Scope, Function<bool(Element const&)> filter);
|
||||||
|
|
||||||
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
|
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
@ -70,6 +74,8 @@ private:
|
||||||
|
|
||||||
JS::NonnullGCPtr<ParentNode> m_root;
|
JS::NonnullGCPtr<ParentNode> m_root;
|
||||||
Function<bool(Element const&)> m_filter;
|
Function<bool(Element const&)> m_filter;
|
||||||
|
|
||||||
|
Scope m_scope { Scope::Descendants };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,8 +113,8 @@ JS::NonnullGCPtr<HTMLCollection> ParentNode::children()
|
||||||
{
|
{
|
||||||
// The children getter steps are to return an HTMLCollection collection rooted at this matching only element children.
|
// The children getter steps are to return an HTMLCollection collection rooted at this matching only element children.
|
||||||
if (!m_children) {
|
if (!m_children) {
|
||||||
m_children = HTMLCollection::create(*this, [this](Element const& element) {
|
m_children = HTMLCollection::create(*this, HTMLCollection::Scope::Children, [](Element const&) {
|
||||||
return is_parent_of(element);
|
return true;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
return *m_children;
|
return *m_children;
|
||||||
|
@ -126,14 +126,14 @@ JS::NonnullGCPtr<HTMLCollection> ParentNode::get_elements_by_tag_name(Deprecated
|
||||||
{
|
{
|
||||||
// 1. If qualifiedName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches only descendant elements.
|
// 1. If qualifiedName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches only descendant elements.
|
||||||
if (qualified_name == "*") {
|
if (qualified_name == "*") {
|
||||||
return HTMLCollection::create(*this, [](Element const&) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const&) {
|
||||||
return true;
|
return true;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Otherwise, if root’s node document is an HTML document, return a HTMLCollection rooted at root, whose filter matches the following descendant elements:
|
// 2. Otherwise, if root’s node document is an HTML document, return a HTMLCollection rooted at root, whose filter matches the following descendant elements:
|
||||||
if (root().document().document_type() == Document::Type::HTML) {
|
if (root().document().document_type() == Document::Type::HTML) {
|
||||||
return HTMLCollection::create(*this, [qualified_name](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [qualified_name](Element const& element) {
|
||||||
// - Whose namespace is the HTML namespace and whose qualified name is qualifiedName, in ASCII lowercase.
|
// - Whose namespace is the HTML namespace and whose qualified name is qualifiedName, in ASCII lowercase.
|
||||||
if (element.namespace_() == Namespace::HTML)
|
if (element.namespace_() == Namespace::HTML)
|
||||||
return element.qualified_name().to_lowercase() == qualified_name.to_lowercase();
|
return element.qualified_name().to_lowercase() == qualified_name.to_lowercase();
|
||||||
|
@ -144,7 +144,7 @@ JS::NonnullGCPtr<HTMLCollection> ParentNode::get_elements_by_tag_name(Deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Otherwise, return a HTMLCollection rooted at root, whose filter matches descendant elements whose qualified name is qualifiedName.
|
// 3. Otherwise, return a HTMLCollection rooted at root, whose filter matches descendant elements whose qualified name is qualifiedName.
|
||||||
return HTMLCollection::create(*this, [qualified_name](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [qualified_name](Element const& element) {
|
||||||
return element.qualified_name() == qualified_name;
|
return element.qualified_name() == qualified_name;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -160,27 +160,27 @@ JS::NonnullGCPtr<HTMLCollection> ParentNode::get_elements_by_tag_name_ns(Depreca
|
||||||
|
|
||||||
// 2. If both namespace and localName are "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements.
|
// 2. If both namespace and localName are "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements.
|
||||||
if (namespace_ == "*" && local_name == "*") {
|
if (namespace_ == "*" && local_name == "*") {
|
||||||
return HTMLCollection::create(*this, [](Element const&) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [](Element const&) {
|
||||||
return true;
|
return true;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Otherwise, if namespace is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements whose local name is localName.
|
// 3. Otherwise, if namespace is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements whose local name is localName.
|
||||||
if (namespace_ == "*") {
|
if (namespace_ == "*") {
|
||||||
return HTMLCollection::create(*this, [local_name](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [local_name](Element const& element) {
|
||||||
return element.local_name() == local_name;
|
return element.local_name() == local_name;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Otherwise, if localName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements whose namespace is namespace.
|
// 4. Otherwise, if localName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements whose namespace is namespace.
|
||||||
if (local_name == "*") {
|
if (local_name == "*") {
|
||||||
return HTMLCollection::create(*this, [namespace_](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [namespace_](Element const& element) {
|
||||||
return element.namespace_() == namespace_;
|
return element.namespace_() == namespace_;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Otherwise, return a HTMLCollection rooted at root, whose filter matches descendant elements whose namespace is namespace and local name is localName.
|
// 5. Otherwise, return a HTMLCollection rooted at root, whose filter matches descendant elements whose namespace is namespace and local name is localName.
|
||||||
return HTMLCollection::create(*this, [namespace_, local_name](Element const& element) {
|
return HTMLCollection::create(*this, HTMLCollection::Scope::Descendants, [namespace_, local_name](Element const& element) {
|
||||||
return element.namespace_() == namespace_ && element.local_name() == local_name;
|
return element.namespace_() == namespace_ && element.local_name() == local_name;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,7 +244,7 @@ static bool is_form_control(DOM::Element const& element)
|
||||||
JS::NonnullGCPtr<DOM::HTMLCollection> HTMLFormElement::elements() const
|
JS::NonnullGCPtr<DOM::HTMLCollection> HTMLFormElement::elements() const
|
||||||
{
|
{
|
||||||
if (!m_elements) {
|
if (!m_elements) {
|
||||||
m_elements = DOM::HTMLCollection::create(const_cast<HTMLFormElement&>(*this), [](Element const& element) {
|
m_elements = DOM::HTMLCollection::create(const_cast<HTMLFormElement&>(*this), DOM::HTMLCollection::Scope::Descendants, [](Element const& element) {
|
||||||
return is_form_control(element);
|
return is_form_control(element);
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLOptionsCollection>> HTMLOptionsCollecti
|
||||||
}
|
}
|
||||||
|
|
||||||
HTMLOptionsCollection::HTMLOptionsCollection(DOM::ParentNode& root, Function<bool(DOM::Element const&)> filter)
|
HTMLOptionsCollection::HTMLOptionsCollection(DOM::ParentNode& root, Function<bool(DOM::Element const&)> filter)
|
||||||
: DOM::HTMLCollection(root, move(filter))
|
: DOM::HTMLCollection(root, Scope::Descendants, move(filter))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,7 @@ JS::NonnullGCPtr<DOM::HTMLCollection> HTMLTableElement::t_bodies()
|
||||||
// The tBodies attribute must return an HTMLCollection rooted at the table node,
|
// The tBodies attribute must return an HTMLCollection rooted at the table node,
|
||||||
// whose filter matches only tbody elements that are children of the table element.
|
// whose filter matches only tbody elements that are children of the table element.
|
||||||
if (!m_t_bodies) {
|
if (!m_t_bodies) {
|
||||||
m_t_bodies = DOM::HTMLCollection::create(*this, [](DOM::Element const& element) {
|
m_t_bodies = DOM::HTMLCollection::create(*this, DOM::HTMLCollection::Scope::Children, [](DOM::Element const& element) {
|
||||||
return element.local_name() == TagNames::tbody;
|
return element.local_name() == TagNames::tbody;
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ JS::NonnullGCPtr<DOM::HTMLCollection> HTMLTableElement::rows()
|
||||||
// How do you sort HTMLCollection?
|
// How do you sort HTMLCollection?
|
||||||
|
|
||||||
if (!m_rows) {
|
if (!m_rows) {
|
||||||
m_rows = DOM::HTMLCollection::create(*this, [table_node](DOM::Element const& element) {
|
m_rows = DOM::HTMLCollection::create(*this, DOM::HTMLCollection::Scope::Descendants, [table_node](DOM::Element const& element) {
|
||||||
// Only match TR elements which are:
|
// Only match TR elements which are:
|
||||||
// * children of the table element
|
// * children of the table element
|
||||||
// * children of the thead, tbody, or tfoot elements that are themselves children of the table element
|
// * children of the thead, tbody, or tfoot elements that are themselves children of the table element
|
||||||
|
|
|
@ -42,9 +42,8 @@ JS::NonnullGCPtr<DOM::HTMLCollection> HTMLTableRowElement::cells() const
|
||||||
// The cells attribute must return an HTMLCollection rooted at this tr element,
|
// The cells attribute must return an HTMLCollection rooted at this tr element,
|
||||||
// whose filter matches only td and th elements that are children of the tr element.
|
// whose filter matches only td and th elements that are children of the tr element.
|
||||||
if (!m_cells) {
|
if (!m_cells) {
|
||||||
m_cells = DOM::HTMLCollection::create(const_cast<HTMLTableRowElement&>(*this), [this](Element const& element) {
|
m_cells = DOM::HTMLCollection::create(const_cast<HTMLTableRowElement&>(*this), DOM::HTMLCollection::Scope::Children, [](Element const& element) {
|
||||||
return element.parent() == this
|
return is<HTMLTableCellElement>(element);
|
||||||
&& is<HTMLTableCellElement>(element);
|
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
return *m_cells;
|
return *m_cells;
|
||||||
|
|
|
@ -41,9 +41,8 @@ JS::NonnullGCPtr<DOM::HTMLCollection> HTMLTableSectionElement::rows() const
|
||||||
// The rows attribute must return an HTMLCollection rooted at this element,
|
// The rows attribute must return an HTMLCollection rooted at this element,
|
||||||
// whose filter matches only tr elements that are children of this element.
|
// whose filter matches only tr elements that are children of this element.
|
||||||
if (!m_rows) {
|
if (!m_rows) {
|
||||||
m_rows = DOM::HTMLCollection::create(const_cast<HTMLTableSectionElement&>(*this), [this](Element const& element) {
|
m_rows = DOM::HTMLCollection::create(const_cast<HTMLTableSectionElement&>(*this), DOM::HTMLCollection::Scope::Children, [](Element const& element) {
|
||||||
return element.parent() == this
|
return is<HTMLTableRowElement>(element);
|
||||||
&& is<HTMLTableRowElement>(element);
|
|
||||||
}).release_value_but_fixme_should_propagate_errors();
|
}).release_value_but_fixme_should_propagate_errors();
|
||||||
}
|
}
|
||||||
return *m_rows;
|
return *m_rows;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue