1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-09 09:34:57 +09:00

LibWeb: Make a elements honor base element's target

This commit is contained in:
Psychpsyo 2025-02-14 18:28:29 +01:00 committed by Andreas Kling
parent 79d6d5a7fa
commit f839f1b44b
Notes: github-actions[bot] 2025-02-16 08:22:46 +00:00
8 changed files with 50 additions and 8 deletions

View file

@ -536,6 +536,7 @@ void Document::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_fonts);
visitor.visit(m_selection);
visitor.visit(m_first_base_element_with_href_in_tree_order);
visitor.visit(m_first_base_element_with_target_in_tree_order);
visitor.visit(m_parser);
visitor.visit(m_lazy_load_intersection_observer);
visitor.visit(m_visual_viewport);
@ -1075,18 +1076,26 @@ Vector<CSS::BackgroundLayerData> const* Document::background_layers() const
void Document::update_base_element(Badge<HTML::HTMLBaseElement>)
{
GC::Ptr<HTML::HTMLBaseElement const> base_element;
GC::Ptr<HTML::HTMLBaseElement const> base_element_with_href = nullptr;
GC::Ptr<HTML::HTMLBaseElement const> base_element_with_target = nullptr;
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;
for_each_in_subtree_of_type<HTML::HTMLBaseElement>([&base_element_with_href, &base_element_with_target](HTML::HTMLBaseElement const& base_element_in_tree) {
if (!base_element_with_href && base_element_in_tree.has_attribute(HTML::AttributeNames::href)) {
base_element_with_href = &base_element_in_tree;
if (base_element_with_target)
return TraversalDecision::Break;
}
if (!base_element_with_target && base_element_in_tree.has_attribute(HTML::AttributeNames::target)) {
base_element_with_target = &base_element_in_tree;
if (base_element_with_href)
return TraversalDecision::Break;
}
return TraversalDecision::Continue;
});
m_first_base_element_with_href_in_tree_order = base_element;
m_first_base_element_with_href_in_tree_order = base_element_with_href;
m_first_base_element_with_target_in_tree_order = base_element_with_target;
}
GC::Ptr<HTML::HTMLBaseElement const> Document::first_base_element_with_href_in_tree_order() const
@ -1094,6 +1103,11 @@ GC::Ptr<HTML::HTMLBaseElement const> Document::first_base_element_with_href_in_t
return m_first_base_element_with_href_in_tree_order;
}
GC::Ptr<HTML::HTMLBaseElement const> Document::first_base_element_with_target_in_tree_order() const
{
return m_first_base_element_with_target_in_tree_order;
}
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fallback-base-url
URL::URL Document::fallback_base_url() const
{

View file

@ -152,6 +152,7 @@ public:
void update_base_element(Badge<HTML::HTMLBaseElement>);
GC::Ptr<HTML::HTMLBaseElement const> first_base_element_with_href_in_tree_order() const;
GC::Ptr<HTML::HTMLBaseElement const> first_base_element_with_target_in_tree_order() const;
String url_string() const { return m_url.to_string(); }
String document_uri() const { return url_string(); }
@ -1022,8 +1023,9 @@ private:
// https://w3c.github.io/selection-api/#dfn-selection
GC::Ptr<Selection::Selection> m_selection;
// NOTE: This is a cache to make finding the first <base href> element O(1).
// NOTE: This is a cache to make finding the first <base href> or <base target> element O(1).
GC::Ptr<HTML::HTMLBaseElement const> m_first_base_element_with_href_in_tree_order;
GC::Ptr<HTML::HTMLBaseElement const> m_first_base_element_with_target_in_tree_order;
// https://html.spec.whatwg.org/multipage/images.html#list-of-available-images
GC::Ptr<HTML::ListOfAvailableImages> m_list_of_available_images;

View file

@ -948,8 +948,10 @@ String HTMLElement::get_an_elements_target(Optional<String> target) const
if (auto maybe_target = attribute(AttributeNames::target); maybe_target.has_value()) {
target = maybe_target.release_value();
}
// FIXME: 2. Otherwise, if element's node document contains a base element with a target attribute,
// 2. Otherwise, if element's node document contains a base element with a target attribute,
// set target to the value of the target attribute of the first such base element.
if (auto base_element = document().first_base_element_with_target_in_tree_order())
target = base_element->attribute(AttributeNames::target);
}
// 2. If target is not null, and contains an ASCII tab or newline and a U+003C (<), then set target to "_blank".

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
SUCCESS!

View file

@ -0,0 +1,3 @@
<!DOCTYPE html>
<base target="_parent">
<a id="a" href="a-element-target-sub-alt.html">Click me!</a>

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
<iframe id="frame" src="a-element-target-sub-sub.html"></iframe>

View file

@ -0,0 +1 @@
Parent frame navigated successfully!

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<iframe id="frame" src="../../data/base/a-element-target-sub.html"></iframe>
<script>
asyncTest(done => {
window.onload = () => {
frame.onload = () => {
frame.onload = () => {
println(frame.contentDocument.location.href.includes("a-element-target-sub-alt.html")? "Parent frame navigated successfully!" : "Parent frame incorrectly navigated to " + frame.contentDocument.location.href);
done();
}
}
frame.contentDocument.getElementById("frame").contentDocument.getElementById("a").click();
};
});
</script>