Differentiate between missing/invalid value in make_enumerated_getter! (#34412)

* Create spec-compliant version of create_enumerated_getter

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Use new make_enumerated_getter! macro everywhere

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Remove old make_enumerated_getter macro

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Return lowercased value from make_enumerated_getter macro

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Update WPT expectations

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2024-11-28 01:54:03 +01:00 committed by GitHub
parent 612492b372
commit 9168375b33
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 137 additions and 36 deletions

View file

@ -158,22 +158,86 @@ macro_rules! make_labels_getter(
);
);
#[macro_export]
/// Implements the `To determine the state of an attribute` steps from
/// <https://html.spec.whatwg.org/multipage/#keywords-and-enumerated-attributes>
macro_rules! make_enumerated_getter(
( $attr:ident, $htmlname:tt, $default:expr, $($choices:pat_param)|+) => (
($attr:ident,
$htmlname:tt,
$($choices:literal)|+,
missing => $missing:literal,
invalid => $invalid:literal
) => (
fn $attr(&self) -> DOMString {
use $crate::dom::bindings::inheritance::Castable;
use $crate::dom::element::Element;
let element = self.upcast::<Element>();
let mut val = element.get_string_attribute(&html5ever::local_name!($htmlname));
val.make_ascii_lowercase();
// https://html.spec.whatwg.org/multipage/#attr-fs-method
match &*val {
$($choices)|+ => val,
_ => DOMString::from($default)
use $crate::dom::bindings::codegen::Bindings::AttrBinding::Attr_Binding::AttrMethods;
let attr_or_none = self.upcast::<Element>()
.get_attribute(&html5ever::ns!(), &html5ever::local_name!($htmlname));
match attr_or_none {
// Step 1. If the attribute is not specified:
None => {
// Step 1.1. If the attribute has a missing value default state defined, then return that
// missing value default state.
// Step 1.2 Otherwise, return no state.
return DOMString::from($missing);
},
Some(attr) => {
// Step 2. If the attribute's value is an ASCII case-insensitive match for one of the keywords
// defined for the attribute, then return the state represented by that keyword.
let value: DOMString = attr.Value().to_ascii_lowercase().into();
$(
if value.str() == $choices {
return value;
}
)+
// Step 3. If the attribute has an invalid value default state defined, then return that invalid
// value default state.
// Step 4. Return no state.
return DOMString::from($invalid);
}
}
}
);
($attr:ident,
$htmlname:tt,
$($choices:literal)|+,
) => (
make_enumerated_getter!(
$attr,
$htmlname,
$($choices)|+,
missing => "",
invalid => ""
);
);
($attr:ident,
$htmlname:tt,
$($choices:literal)|+,
invalid => $invalid:literal
) => (
make_enumerated_getter!(
$attr,
$htmlname,
$($choices)|+,
missing => "",
invalid => $invalid
);
);
($attr:ident,
$htmlname:tt,
$($choices:literal)|+,
missing => $missing:literal,
) => (
make_enumerated_getter!(
$attr,
$htmlname,
$($choices)|+,
missing => $missing,
invalid => ""
);
);
);
// concat_idents! doesn't work for function name positions, so