mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 11:36:10 +00:00
LibWeb: Make Node::parent_element return GC::Ptr
This is useful for people like myself who run with debug mode to more reliably get stacktraces without spinning up a debugger.
This commit is contained in:
parent
a14481ee05
commit
3e17b1c9ae
Notes:
github-actions[bot]
2025-04-18 09:08:36 +00:00
Author: https://github.com/shannonbooth Commit: https://github.com/LadybirdBrowser/ladybird/commit/3e17b1c9ae8 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4393
18 changed files with 48 additions and 54 deletions
|
@ -42,84 +42,84 @@ Optional<Role> ARIAMixin::role_from_role_attribute_value() const
|
|||
// without the required accessible parent of role list), User Agents MUST ignore the role token, and return the
|
||||
// computedrole as if the ignored role token had not been included.
|
||||
if (role == ARIA::Role::columnheader) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->role_or_default() == ARIA::Role::row)
|
||||
return ARIA::Role::columnheader;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::gridcell) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->role_or_default() == ARIA::Role::row)
|
||||
return ARIA::Role::gridcell;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::listitem) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::directory, ARIA::Role::list))
|
||||
return ARIA::Role::listitem;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::menuitem) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::menu, ARIA::Role::menubar))
|
||||
return ARIA::Role::menuitem;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::menuitemcheckbox) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::menu, ARIA::Role::menubar))
|
||||
return ARIA::Role::menuitemcheckbox;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::menuitemradio) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::menu, ARIA::Role::menubar))
|
||||
return ARIA::Role::menuitemradio;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::option) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->role_or_default() == ARIA::Role::listbox)
|
||||
return ARIA::Role::option;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::row) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::table, ARIA::Role::grid, ARIA::Role::treegrid))
|
||||
return ARIA::Role::row;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::rowgroup) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::table, ARIA::Role::grid, ARIA::Role::treegrid))
|
||||
return ARIA::Role::rowgroup;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::rowheader) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->role_or_default() == ARIA::Role::row)
|
||||
return ARIA::Role::rowheader;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::tab) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->role_or_default() == ARIA::Role::tablist)
|
||||
return ARIA::Role::tab;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (role == ARIA::Role::treeitem) {
|
||||
for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->role_or_default() == ARIA::Role::tree)
|
||||
return ARIA::Role::treeitem;
|
||||
}
|
||||
|
|
|
@ -973,7 +973,7 @@ void KeyframeEffect::update_computed_properties()
|
|||
if (invalidation.rebuild_layout_tree) {
|
||||
// We mark layout tree for rebuild starting from parent element to correctly invalidate
|
||||
// "display" property change to/from "contents" value.
|
||||
if (auto* parent_element = target->parent_element()) {
|
||||
if (auto parent_element = target->parent_element()) {
|
||||
parent_element->set_needs_layout_tree_update(true);
|
||||
} else {
|
||||
target->set_needs_layout_tree_update(true);
|
||||
|
|
|
@ -2280,7 +2280,7 @@ static BoxTypeTransformation required_box_type_transformation(ComputedProperties
|
|||
// FIXME: Containment in a ruby container inlinifies the box’s display type, as described in [CSS-RUBY-1].
|
||||
|
||||
// NOTE: If we're computing style for a pseudo-element, the effective parent will be the originating element itself, not its parent.
|
||||
auto const* parent = pseudo_element.has_value() ? &element : element.parent_element();
|
||||
auto parent = pseudo_element.has_value() ? GC::Ptr<DOM::Element const> { &element } : element.parent_element();
|
||||
|
||||
// A parent with a grid or flex display value blockifies the box’s display type. [CSS-GRID-1] [CSS-FLEXBOX-1]
|
||||
if (parent && parent->computed_properties()) {
|
||||
|
@ -2505,7 +2505,7 @@ RefPtr<CSSStyleValue const> StyleComputer::recascade_font_size_if_needed(
|
|||
Vector<DOM::Element&> ancestors;
|
||||
if (pseudo_element.has_value())
|
||||
ancestors.append(element);
|
||||
for (auto* ancestor = element.parent_element(); ancestor; ancestor = ancestor->parent_element())
|
||||
for (auto ancestor = element.parent_element(); ancestor; ancestor = ancestor->parent_element())
|
||||
ancestors.append(*ancestor);
|
||||
|
||||
NonnullRefPtr<CSSStyleValue const> new_font_size = CSS::LengthStyleValue::create(CSS::Length::make_px(default_monospace_font_size_in_px));
|
||||
|
|
|
@ -1440,7 +1440,7 @@ void Document::update_layout(UpdateLayoutReason reason)
|
|||
if (node_invalidation.rebuild_layout_tree) {
|
||||
// We mark layout tree for rebuild starting from parent element to correctly invalidate
|
||||
// "display" property change to/from "contents" value.
|
||||
if (auto* parent_element = node.parent_element()) {
|
||||
if (auto parent_element = node.parent_element()) {
|
||||
parent_element->set_needs_layout_tree_update(true);
|
||||
} else {
|
||||
node.set_needs_layout_tree_update(true);
|
||||
|
|
|
@ -2626,7 +2626,7 @@ Optional<String> Element::locate_a_namespace_prefix(Optional<String> const& name
|
|||
}
|
||||
|
||||
// 3. If element’s parent element is not null, then return the result of running locate a namespace prefix on that element using namespace.
|
||||
if (auto* parent = this->parent_element())
|
||||
if (auto parent = this->parent_element())
|
||||
return parent->locate_a_namespace_prefix(namespace_);
|
||||
|
||||
// 4. Return null
|
||||
|
@ -2881,7 +2881,7 @@ bool Element::check_visibility(Optional<CheckVisibilityOptions> options)
|
|||
return false;
|
||||
|
||||
// 2. If an ancestor of this in the flat tree has content-visibility: hidden, return false.
|
||||
for (auto* element = parent_element(); element; element = element->parent_element()) {
|
||||
for (auto element = parent_element(); element; element = element->parent_element()) {
|
||||
if (element->computed_properties()->content_visibility() == CSS::ContentVisibility::Hidden)
|
||||
return false;
|
||||
}
|
||||
|
@ -3151,7 +3151,7 @@ Element const* Element::list_owner() const
|
|||
return nullptr;
|
||||
|
||||
// 2. Let ancestor be the element's parent.
|
||||
auto const* ancestor = parent_element();
|
||||
auto ancestor = parent_element();
|
||||
|
||||
// AC-HOC: There may not be any parent element in a shadow tree.
|
||||
if (!ancestor)
|
||||
|
@ -3692,7 +3692,7 @@ void Element::inherit_counters()
|
|||
{
|
||||
// 1. If element is the root of its document tree, the element has an initially-empty CSS counters set.
|
||||
// Return.
|
||||
auto* parent = parent_element();
|
||||
auto parent = parent_element();
|
||||
if (parent == nullptr) {
|
||||
// NOTE: We represent an empty counters set with `m_counters_set = nullptr`.
|
||||
m_counters_set = nullptr;
|
||||
|
@ -3765,14 +3765,14 @@ Optional<String> Element::lang() const
|
|||
|
||||
// 3. If the node's parent is a shadow root
|
||||
// Use the language of that shadow root's host.
|
||||
if (auto const* parent = parent_element()) {
|
||||
if (auto parent = parent_element()) {
|
||||
if (parent->is_shadow_root())
|
||||
return parent->shadow_root()->host()->lang();
|
||||
}
|
||||
|
||||
// 4. If the node's parent element is not null
|
||||
// Use the language of that parent element.
|
||||
if (auto const* parent = parent_element())
|
||||
if (auto parent = parent_element())
|
||||
return parent->lang();
|
||||
|
||||
// 5. Otherwise
|
||||
|
|
|
@ -582,20 +582,14 @@ private:
|
|||
template<>
|
||||
inline bool Node::fast_is<Element>() const { return is_element(); }
|
||||
|
||||
inline Element* Node::parent_element()
|
||||
inline GC::Ptr<Element> Node::parent_element()
|
||||
{
|
||||
auto* parent = this->parent();
|
||||
if (!parent || !is<Element>(parent))
|
||||
return nullptr;
|
||||
return static_cast<Element*>(parent);
|
||||
return as_if<Element>(this->parent());
|
||||
}
|
||||
|
||||
inline Element const* Node::parent_element() const
|
||||
inline GC::Ptr<Element const> Node::parent_element() const
|
||||
{
|
||||
auto const* parent = this->parent();
|
||||
if (!parent || !is<Element>(parent))
|
||||
return nullptr;
|
||||
return static_cast<Element const*>(parent);
|
||||
return as_if<Element>(this->parent());
|
||||
}
|
||||
|
||||
inline bool Element::has_class(FlyString const& class_name, CaseSensitivity case_sensitivity) const
|
||||
|
|
|
@ -2051,7 +2051,7 @@ Optional<String> Node::locate_a_namespace(Optional<String> const& prefix) const
|
|||
}
|
||||
|
||||
// 5. If its parent element is null, then return null.
|
||||
auto* parent_element = element.parent_element();
|
||||
auto parent_element = element.parent_element();
|
||||
if (!element.parent_element())
|
||||
return {};
|
||||
|
||||
|
@ -2090,7 +2090,7 @@ Optional<String> Node::locate_a_namespace(Optional<String> const& prefix) const
|
|||
|
||||
// Otherwise
|
||||
// 1. If its parent element is null, then return null.
|
||||
auto* parent_element = this->parent_element();
|
||||
auto parent_element = this->parent_element();
|
||||
if (!parent_element)
|
||||
return {};
|
||||
|
||||
|
@ -2153,7 +2153,7 @@ Optional<String> Node::lookup_prefix(Optional<String> namespace_) const
|
|||
|
||||
// Otherwise
|
||||
// Return the result of locating a namespace prefix for its parent element, if its parent element is non-null; otherwise null.
|
||||
auto* parent_element = this->parent_element();
|
||||
auto parent_element = this->parent_element();
|
||||
if (!parent_element)
|
||||
return {};
|
||||
|
||||
|
|
|
@ -261,8 +261,8 @@ public:
|
|||
Node* parent_node() { return parent(); }
|
||||
Node const* parent_node() const { return parent(); }
|
||||
|
||||
Element* parent_element();
|
||||
Element const* parent_element() const;
|
||||
GC::Ptr<Element> parent_element();
|
||||
GC::Ptr<Element const> parent_element() const;
|
||||
|
||||
virtual void inserted();
|
||||
virtual void post_connection();
|
||||
|
|
|
@ -56,7 +56,7 @@ bool is_an_assigned_slottable(GC::Ref<Node> node)
|
|||
GC::Ptr<HTML::HTMLSlotElement> find_a_slot(Slottable const& slottable, OpenFlag open_flag)
|
||||
{
|
||||
// 1. If slottable’s parent is null, then return null.
|
||||
auto* parent = slottable.visit([](auto& node) { return node->parent_element(); });
|
||||
auto parent = slottable.visit([](auto& node) { return node->parent_element(); });
|
||||
if (!parent)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -467,15 +467,15 @@ GC::Ptr<DOM::Element> HTMLElement::offset_parent() const
|
|||
// - The computed value of the position property of the element is static
|
||||
// and the ancestor is one of the following HTML elements: td, th, or table.
|
||||
|
||||
for (auto* ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (!ancestor->layout_node())
|
||||
continue;
|
||||
if (ancestor->layout_node()->is_positioned())
|
||||
return const_cast<Element*>(ancestor);
|
||||
return const_cast<Element*>(ancestor.ptr());
|
||||
if (is<HTML::HTMLBodyElement>(*ancestor))
|
||||
return const_cast<Element*>(ancestor);
|
||||
return const_cast<Element*>(ancestor.ptr());
|
||||
if (!ancestor->layout_node()->is_positioned() && ancestor->local_name().is_one_of(HTML::TagNames::td, HTML::TagNames::th, HTML::TagNames::table))
|
||||
return const_cast<Element*>(ancestor);
|
||||
return const_cast<Element*>(ancestor.ptr());
|
||||
}
|
||||
|
||||
// 3. Return null.
|
||||
|
@ -843,7 +843,7 @@ Optional<ARIA::Role> HTMLElement::default_role() const
|
|||
// https://www.w3.org/TR/html-aria/#el-aside
|
||||
if (local_name() == TagNames::aside) {
|
||||
// https://w3c.github.io/html-aam/#el-aside
|
||||
for (auto const* ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->local_name().is_one_of(TagNames::article, TagNames::aside, TagNames::nav, TagNames::section)
|
||||
&& accessible_name(document()).value().is_empty())
|
||||
return ARIA::Role::generic;
|
||||
|
@ -887,7 +887,7 @@ Optional<ARIA::Role> HTMLElement::default_role() const
|
|||
// If not a descendant of an article, aside, main, nav or section element, or an element with role=article,
|
||||
// complementary, main, navigation or region then (footer) role=contentinfo (header) role=banner. Otherwise,
|
||||
// role=generic.
|
||||
for (auto const* ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->local_name().is_one_of(TagNames::article, TagNames::aside, TagNames::main, TagNames::nav, TagNames::section)) {
|
||||
if (local_name() == TagNames::footer)
|
||||
return ARIA::Role::sectionfooter;
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
// https://www.w3.org/TR/html-aria/#el-li
|
||||
virtual Optional<ARIA::Role> default_role() const override
|
||||
{
|
||||
for (auto const* ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
if (ancestor->role_or_default() == ARIA::Role::list)
|
||||
return ARIA::Role::listitem;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ HTMLFormElement* HTMLLegendElement::form()
|
|||
{
|
||||
// The form IDL attribute's behavior depends on whether the legend element is in a fieldset element or not.
|
||||
// If the legend has a fieldset element as its parent, then the form IDL attribute must return the same value as the form IDL attribute on that fieldset element.
|
||||
if (is<HTML::HTMLFieldSetElement>(parent_element())) {
|
||||
return as<HTML::HTMLFieldSetElement>(parent_element())->form();
|
||||
if (auto* field_set = as_if<HTML::HTMLFieldSetElement>(parent_element().ptr())) {
|
||||
return field_set->form();
|
||||
}
|
||||
|
||||
// Otherwise, it must return null.
|
||||
|
|
|
@ -250,7 +250,7 @@ void HTMLOptionElement::removed_from(Node* old_parent, Node& old_root)
|
|||
if (old_parent) {
|
||||
if (is<HTMLSelectElement>(*old_parent))
|
||||
static_cast<HTMLSelectElement&>(*old_parent).update_selectedness();
|
||||
else if (is<HTMLOptGroupElement>(*old_parent) && old_parent->parent_element() && is<HTMLSelectElement>(old_parent->parent_element()))
|
||||
else if (is<HTMLOptGroupElement>(*old_parent) && old_parent->parent_element() && is<HTMLSelectElement>(*old_parent->parent_element()))
|
||||
static_cast<HTMLSelectElement&>(*old_parent->parent_element()).update_selectedness();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ void HTMLSummaryElement::activation_behavior(DOM::Event const&)
|
|||
return;
|
||||
|
||||
// 2. Let parent be this summary element's parent.
|
||||
auto* parent = this->parent_element();
|
||||
auto parent = this->parent_element();
|
||||
|
||||
// 3. If the open attribute is present on parent, then remove it. Otherwise, set parent's open attribute to the empty string.
|
||||
if (parent->has_attribute(HTML::AttributeNames::open))
|
||||
|
@ -50,7 +50,7 @@ bool HTMLSummaryElement::is_summary_for_its_parent_details()
|
|||
return false;
|
||||
|
||||
// 2. Let parent be this summary element's parent.
|
||||
auto* parent = this->parent_element();
|
||||
auto parent = this->parent_element();
|
||||
|
||||
// 3. If parent is not a details element, then return false.
|
||||
if (!is<HTMLDetailsElement>(*parent))
|
||||
|
|
|
@ -215,7 +215,7 @@ WebIDL::Long HTMLTableCellElement::cell_index() const
|
|||
Optional<ARIA::Role> HTMLTableCellElement::default_role() const
|
||||
{
|
||||
if (local_name() == TagNames::th) {
|
||||
for (auto const* ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
for (auto ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
// AD-HOC: The ancestor checks here aren’t explicitly defined in the spec, but implicitly follow from what
|
||||
// the spec does state, and from the physical placement/layout of elements. Also, the el-th and el-th-in-row
|
||||
// tests at https://wpt.fyi/results/html-aam/table-roles.html require doing these ancestor checks — and
|
||||
|
|
|
@ -151,7 +151,7 @@ void HTMLTrackElement::start_the_track_processing_model()
|
|||
return;
|
||||
|
||||
// 3. If the text track's track element does not have a media element as a parent, return.
|
||||
if (!is<HTMLMediaElement>(parent_element()))
|
||||
if (!is<HTMLMediaElement>(parent_element().ptr()))
|
||||
return;
|
||||
|
||||
// 4. Run the remainder of these steps in parallel, allowing whatever caused these steps to run to continue.
|
||||
|
|
|
@ -342,7 +342,7 @@ void TextNode::compute_text_for_rendering()
|
|||
if (dom_node().is_editable() && !dom_node().is_uninteresting_whitespace_node())
|
||||
collapse = false;
|
||||
|
||||
auto const* parent_element = dom_node().parent_element();
|
||||
auto parent_element = dom_node().parent_element();
|
||||
auto const maybe_lang = parent_element ? parent_element->lang() : Optional<String> {};
|
||||
auto const lang = maybe_lang.has_value() ? maybe_lang.value() : Optional<StringView> {};
|
||||
|
||||
|
|
|
@ -727,7 +727,7 @@ void Page::update_find_in_page_selection(Vector<GC::Root<DOM::Range>> matches)
|
|||
|
||||
selection->add_range(*current_range);
|
||||
|
||||
if (auto* element = common_ancestor_container->parent_element()) {
|
||||
if (auto element = common_ancestor_container->parent_element()) {
|
||||
DOM::ScrollIntoViewOptions scroll_options;
|
||||
scroll_options.block = Bindings::ScrollLogicalPosition::Nearest;
|
||||
scroll_options.inline_ = Bindings::ScrollLogicalPosition::Nearest;
|
||||
|
|
Loading…
Add table
Reference in a new issue