mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-13 11:39:43 +00:00
LibWeb: Make a elements honor base element's target
This commit is contained in:
parent
79d6d5a7fa
commit
f839f1b44b
Notes:
github-actions[bot]
2025-02-16 08:22:46 +00:00
Author: https://github.com/Psychpsyo
Commit: f839f1b44b
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3576
8 changed files with 50 additions and 8 deletions
|
@ -536,6 +536,7 @@ void Document::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(m_fonts);
|
visitor.visit(m_fonts);
|
||||||
visitor.visit(m_selection);
|
visitor.visit(m_selection);
|
||||||
visitor.visit(m_first_base_element_with_href_in_tree_order);
|
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_parser);
|
||||||
visitor.visit(m_lazy_load_intersection_observer);
|
visitor.visit(m_lazy_load_intersection_observer);
|
||||||
visitor.visit(m_visual_viewport);
|
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>)
|
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) {
|
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_in_tree.has_attribute(HTML::AttributeNames::href)) {
|
if (!base_element_with_href && base_element_in_tree.has_attribute(HTML::AttributeNames::href)) {
|
||||||
base_element = &base_element_in_tree;
|
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::Break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TraversalDecision::Continue;
|
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
|
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;
|
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
|
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fallback-base-url
|
||||||
URL::URL Document::fallback_base_url() const
|
URL::URL Document::fallback_base_url() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -152,6 +152,7 @@ public:
|
||||||
|
|
||||||
void update_base_element(Badge<HTML::HTMLBaseElement>);
|
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_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 url_string() const { return m_url.to_string(); }
|
||||||
String document_uri() const { return url_string(); }
|
String document_uri() const { return url_string(); }
|
||||||
|
@ -1022,8 +1023,9 @@ private:
|
||||||
// https://w3c.github.io/selection-api/#dfn-selection
|
// https://w3c.github.io/selection-api/#dfn-selection
|
||||||
GC::Ptr<Selection::Selection> m_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_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
|
// https://html.spec.whatwg.org/multipage/images.html#list-of-available-images
|
||||||
GC::Ptr<HTML::ListOfAvailableImages> m_list_of_available_images;
|
GC::Ptr<HTML::ListOfAvailableImages> m_list_of_available_images;
|
||||||
|
|
|
@ -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()) {
|
if (auto maybe_target = attribute(AttributeNames::target); maybe_target.has_value()) {
|
||||||
target = maybe_target.release_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.
|
// 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".
|
// 2. If target is not null, and contains an ASCII tab or newline and a U+003C (<), then set target to "_blank".
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
SUCCESS!
|
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<base target="_parent">
|
||||||
|
<a id="a" href="a-element-target-sub-alt.html">Click me!</a>
|
2
Tests/LibWeb/Text/data/base/a-element-target-sub.html
Normal file
2
Tests/LibWeb/Text/data/base/a-element-target-sub.html
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<iframe id="frame" src="a-element-target-sub-sub.html"></iframe>
|
1
Tests/LibWeb/Text/expected/base/a-element-target.txt
Normal file
1
Tests/LibWeb/Text/expected/base/a-element-target.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Parent frame navigated successfully!
|
16
Tests/LibWeb/Text/input/base/a-element-target.html
Normal file
16
Tests/LibWeb/Text/input/base/a-element-target.html
Normal 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>
|
Loading…
Add table
Add a link
Reference in a new issue