aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorSteven Novaryo <65610990+stevennovaryo@users.noreply.github.com>2024-12-14 01:29:52 +0800
committerGitHub <noreply@github.com>2024-12-13 17:29:52 +0000
commit3b3db37f16b61751360ea41ab92c53806209b00a (patch)
treea4a4cbd0a806f52a14a8056f85b1fe0fa4ae5547 /components
parent681d7dca9b20d8996e0d4c18a7100872da6c0f88 (diff)
downloadservo-3b3db37f16b61751360ea41ab92c53806209b00a.tar.gz
servo-3b3db37f16b61751360ea41ab92c53806209b00a.zip
layout: Fix CSS `attr()` function case sensitivity matching (#34574)
Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
Diffstat (limited to 'components')
-rw-r--r--components/layout_2020/Cargo.toml1
-rw-r--r--components/layout_2020/dom_traversal.rs25
-rw-r--r--components/script/layout_dom/element.rs3
3 files changed, 25 insertions, 4 deletions
diff --git a/components/layout_2020/Cargo.toml b/components/layout_2020/Cargo.toml
index 6e4b1ccb884..2abc3a751d2 100644
--- a/components/layout_2020/Cargo.toml
+++ b/components/layout_2020/Cargo.toml
@@ -40,6 +40,7 @@ pixels = { path = "../pixels" }
range = { path = "../range" }
rayon = { workspace = true }
script_layout_interface = { workspace = true }
+selectors = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
servo_arc = { workspace = true }
diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs
index 3966edea383..f5f27fa7e08 100644
--- a/components/layout_2020/dom_traversal.rs
+++ b/components/layout_2020/dom_traversal.rs
@@ -8,6 +8,7 @@ use html5ever::{local_name, LocalName};
use log::warn;
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script_layout_interface::{LayoutElementType, LayoutNodeType};
+use selectors::Element as SelectorsElement;
use servo_arc::Arc as ServoArc;
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
@@ -413,8 +414,28 @@ where
.to_threadsafe()
.as_element()
.expect("Expected an element");
- let attr_val = element
- .get_attr(&attr.namespace_url, &LocalName::from(&*attr.attribute));
+
+ // From
+ // <https://html.spec.whatwg.org/multipage/#case-sensitivity-of-the-css-%27attr%28%29%27-function>
+ //
+ // > CSS Values and Units leaves the case-sensitivity of attribute names for
+ // > the purpose of the `attr()` function to be defined by the host language.
+ // > [[CSSVALUES]].
+ // >
+ // > When comparing the attribute name part of a CSS `attr()`function to the
+ // > names of namespace-less attributes on HTML elements in HTML documents,
+ // > the name part of the CSS `attr()` function must first be converted to
+ // > ASCII lowercase. The same function when compared to other attributes must
+ // > be compared according to its original case. In both cases, to match the
+ // > values must be identical to each other (and therefore the comparison is
+ // > case sensitive).
+ let attr_name = match element.is_html_element_in_html_document() {
+ true => &*attr.attribute.to_ascii_lowercase(),
+ false => &*attr.attribute,
+ };
+
+ let attr_val =
+ element.get_attr(&attr.namespace_url, &LocalName::from(attr_name));
vec.push(PseudoElementContentItem::Text(
attr_val.map_or("".to_string(), |s| s.to_string()),
));
diff --git a/components/script/layout_dom/element.rs b/components/script/layout_dom/element.rs
index e4841b509a9..ec95cf0458b 100644
--- a/components/script/layout_dom/element.rs
+++ b/components/script/layout_dom/element.rs
@@ -847,8 +847,7 @@ impl<'dom> ::selectors::Element for ServoThreadSafeLayoutElement<'dom> {
}
fn is_html_element_in_html_document(&self) -> bool {
- debug!("ServoThreadSafeLayoutElement::is_html_element_in_html_document called");
- true
+ self.element.is_html_element_in_html_document()
}
#[inline]