layout: Fix CSS attr() function case sensitivity matching (#34574)

Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
This commit is contained in:
Steven Novaryo 2024-12-14 01:29:52 +08:00 committed by GitHub
parent 681d7dca9b
commit 3b3db37f16
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 26 additions and 10 deletions

1
Cargo.lock generated
View file

@ -3915,6 +3915,7 @@ dependencies = [
"range",
"rayon",
"script_layout_interface",
"selectors",
"serde",
"serde_json",
"servo_arc",

View file

@ -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 }

View file

@ -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()),
));

View file

@ -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]

View file

@ -1,2 +0,0 @@
[content-attr-case-001.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[attr-case-sensitivity-001.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[attr-case-sensitivity-002.html]
expected: FAIL