diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 4db03cfb3b3..ed4c37c4378 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -121,7 +121,7 @@ use crate::dom::htmlelement::HTMLElement; use crate::dom::htmlfieldsetelement::HTMLFieldSetElement; use crate::dom::htmlfontelement::{HTMLFontElement, HTMLFontElementLayoutHelpers}; use crate::dom::htmlformelement::FormControlElementHelpers; -use crate::dom::htmlhrelement::{HTMLHRElement, HTMLHRLayoutHelpers}; +use crate::dom::htmlhrelement::{HTMLHRElement, HTMLHRLayoutHelpers, SizePresentationalHint}; use crate::dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods}; use crate::dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers}; use crate::dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers}; @@ -1306,6 +1306,47 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> { PropertyDeclaration::PaddingRight(cellpadding), )); } + + // https://html.spec.whatwg.org/multipage/#the-hr-element-2 + if let Some(size_info) = self + .downcast::() + .and_then(|hr_element| hr_element.get_size_info()) + { + match size_info { + SizePresentationalHint::SetHeightTo(height) => { + hints.push(from_declaration( + shared_lock, + PropertyDeclaration::Height(height), + )); + }, + SizePresentationalHint::SetAllBorderWidthValuesTo(border_width) => { + hints.push(from_declaration( + shared_lock, + PropertyDeclaration::BorderLeftWidth(border_width.clone()), + )); + hints.push(from_declaration( + shared_lock, + PropertyDeclaration::BorderRightWidth(border_width.clone()), + )); + hints.push(from_declaration( + shared_lock, + PropertyDeclaration::BorderTopWidth(border_width.clone()), + )); + hints.push(from_declaration( + shared_lock, + PropertyDeclaration::BorderBottomWidth(border_width), + )); + }, + SizePresentationalHint::SetBottomBorderWidthToZero => { + hints.push(from_declaration( + shared_lock, + PropertyDeclaration::BorderBottomWidth( + specified::border::BorderSideWidth::from_px(0.), + ), + )); + }, + } + } } fn get_span(self) -> Option { diff --git a/components/script/dom/htmlhrelement.rs b/components/script/dom/htmlhrelement.rs index c88a0fcf184..8dc11e4e848 100644 --- a/components/script/dom/htmlhrelement.rs +++ b/components/script/dom/htmlhrelement.rs @@ -2,11 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::str::FromStr; + use dom_struct::dom_struct; use html5ever::{LocalName, Prefix, local_name, ns}; use js::rust::HandleObject; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::color::AbsoluteColor; +use style::values::generics::NonNegative; +use style::values::specified::border::BorderSideWidth; +use style::values::specified::length::Size; +use style::values::specified::{LengthPercentage, NoCalcLength}; use crate::dom::bindings::codegen::Bindings::HTMLHRElementBinding::HTMLHRElementMethods; use crate::dom::bindings::inheritance::Castable; @@ -65,6 +71,18 @@ impl HTMLHRElementMethods for HTMLHRElement { // https://html.spec.whatwg.org/multipage/#dom-hr-color make_legacy_color_setter!(SetColor, "color"); + // https://html.spec.whatwg.org/multipage/#dom-hr-noshade + make_bool_getter!(NoShade, "noshade"); + + // https://html.spec.whatwg.org/multipage/#dom-hr-noshade + make_bool_setter!(SetNoShade, "noshade"); + + // https://html.spec.whatwg.org/multipage/#dom-hr-size + make_getter!(Size, "size"); + + // https://html.spec.whatwg.org/multipage/#dom-hr-size + make_dimension_setter!(SetSize, "size"); + // https://html.spec.whatwg.org/multipage/#dom-hr-width make_getter!(Width, "width"); @@ -72,9 +90,20 @@ impl HTMLHRElementMethods for HTMLHRElement { make_dimension_setter!(SetWidth, "width"); } +/// The result of applying the the presentational hint for the `size` attribute. +/// +/// (This attribute can mean different things depending on its value and other attributes) +#[allow(clippy::enum_variant_names)] +pub(crate) enum SizePresentationalHint { + SetHeightTo(Size), + SetAllBorderWidthValuesTo(BorderSideWidth), + SetBottomBorderWidthToZero, +} + pub(crate) trait HTMLHRLayoutHelpers { fn get_color(self) -> Option; fn get_width(self) -> LengthOrPercentageOrAuto; + fn get_size_info(self) -> Option; } impl HTMLHRLayoutHelpers for LayoutDom<'_, HTMLHRElement> { @@ -92,6 +121,35 @@ impl HTMLHRLayoutHelpers for LayoutDom<'_, HTMLHRElement> { .cloned() .unwrap_or(LengthOrPercentageOrAuto::Auto) } + + fn get_size_info(self) -> Option { + // https://html.spec.whatwg.org/multipage/#the-hr-element-2 + let element = self.upcast::(); + let size_value = element + .get_attr_val_for_layout(&ns!(), &local_name!("size")) + .and_then(|value| usize::from_str(value).ok()) + .filter(|value| *value != 0)?; + + let hint = if element + .get_attr_for_layout(&ns!(), &local_name!("color")) + .is_some() || + element + .get_attr_for_layout(&ns!(), &local_name!("noshade")) + .is_some() + { + SizePresentationalHint::SetAllBorderWidthValuesTo(BorderSideWidth::from_px( + size_value as f32 / 2.0, + )) + } else if size_value == 1 { + SizePresentationalHint::SetBottomBorderWidthToZero + } else { + SizePresentationalHint::SetHeightTo(Size::LengthPercentage(NonNegative( + LengthPercentage::Length(NoCalcLength::from_px((size_value - 2) as f32)), + ))) + }; + + Some(hint) + } } impl VirtualMethods for HTMLHRElement { diff --git a/components/script_bindings/webidls/HTMLHRElement.webidl b/components/script_bindings/webidls/HTMLHRElement.webidl index 8963d5e8901..45828d4da76 100644 --- a/components/script_bindings/webidls/HTMLHRElement.webidl +++ b/components/script_bindings/webidls/HTMLHRElement.webidl @@ -12,14 +12,9 @@ interface HTMLHRElement : HTMLElement { // https://html.spec.whatwg.org/multipage/#HTMLHRElement-partial partial interface HTMLHRElement { - [CEReactions] - attribute DOMString align; - [CEReactions] - attribute DOMString color; - // [CEReactions] - // attribute boolean noShade; - // [CEReactions] - // attribute DOMString size; - [CEReactions] - attribute DOMString width; + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString color; + [CEReactions] attribute boolean noShade; + [CEReactions] attribute DOMString size; + [CEReactions] attribute DOMString width; }; diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 400ef8b2ccf..deff780986e 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -351937,6 +351937,32 @@ {} ] ], + "size-with-color-or-noshade.html": [ + "db1d583934e6df482cde846eda757e010e7d0310", + [ + null, + [ + [ + "/html/rendering/non-replaced-elements/the-hr-element-0/size-with-color-or-noshade-ref.html", + "==" + ] + ], + {} + ] + ], + "size.html": [ + "2162131b853ed77917ab373f4fb2c70c536e453c", + [ + null, + [ + [ + "/html/rendering/non-replaced-elements/the-hr-element-0/size-ref.html", + "==" + ] + ], + {} + ] + ], "width.html": [ "a436d2ae25a6b03f320bda066f32c374b84e0d92", [ @@ -480431,6 +480457,14 @@ "5cd35c83ada3470ad7a16d14a5028b01596bb60c", [] ], + "size-ref.html": [ + "03a21eb45737ef46247d8bdd61fe5ea0dcefef3e", + [] + ], + "size-with-color-or-noshade-ref.html": [ + "d6300e250d97d113e9ef358daa300de4bd593850", + [] + ], "width-ref.html": [ "71e7651c1ab6927f1be436ef8ff749f920924562", [] diff --git a/tests/wpt/meta/html/dom/idlharness.https.html.ini b/tests/wpt/meta/html/dom/idlharness.https.html.ini index 81d2aa5b8a5..b2ea5b118c1 100644 --- a/tests/wpt/meta/html/dom/idlharness.https.html.ini +++ b/tests/wpt/meta/html/dom/idlharness.https.html.ini @@ -5455,18 +5455,6 @@ [HTMLHeadingElement interface: document.createElement("h1") must inherit property "align" with the proper type] expected: FAIL - [HTMLHRElement interface: attribute noShade] - expected: FAIL - - [HTMLHRElement interface: attribute size] - expected: FAIL - - [HTMLHRElement interface: document.createElement("hr") must inherit property "noShade" with the proper type] - expected: FAIL - - [HTMLHRElement interface: document.createElement("hr") must inherit property "size" with the proper type] - expected: FAIL - [HTMLOListElement interface: attribute reversed] expected: FAIL diff --git a/tests/wpt/meta/html/dom/reflection-grouping.html.ini b/tests/wpt/meta/html/dom/reflection-grouping.html.ini index 556eea039e9..ec7075bc5ab 100644 --- a/tests/wpt/meta/html/dom/reflection-grouping.html.ini +++ b/tests/wpt/meta/html/dom/reflection-grouping.html.ini @@ -383,234 +383,6 @@ [hr.tabIndex: IDL set to -2147483648] expected: FAIL - [hr.noShade: typeof IDL attribute] - expected: FAIL - - [hr.noShade: IDL get with DOM attribute unset] - expected: FAIL - - [hr.noShade: setAttribute() to ""] - expected: FAIL - - [hr.noShade: setAttribute() to " foo "] - expected: FAIL - - [hr.noShade: setAttribute() to undefined] - expected: FAIL - - [hr.noShade: setAttribute() to null] - expected: FAIL - - [hr.noShade: setAttribute() to 7] - expected: FAIL - - [hr.noShade: setAttribute() to 1.5] - expected: FAIL - - [hr.noShade: setAttribute() to "5%"] - expected: FAIL - - [hr.noShade: setAttribute() to "+100"] - expected: FAIL - - [hr.noShade: setAttribute() to ".5"] - expected: FAIL - - [hr.noShade: setAttribute() to true] - expected: FAIL - - [hr.noShade: setAttribute() to false] - expected: FAIL - - [hr.noShade: setAttribute() to object "[object Object\]"] - expected: FAIL - - [hr.noShade: setAttribute() to NaN] - expected: FAIL - - [hr.noShade: setAttribute() to Infinity] - expected: FAIL - - [hr.noShade: setAttribute() to -Infinity] - expected: FAIL - - [hr.noShade: setAttribute() to "\\0"] - expected: FAIL - - [hr.noShade: setAttribute() to object "test-toString"] - expected: FAIL - - [hr.noShade: setAttribute() to object "test-valueOf"] - expected: FAIL - - [hr.noShade: setAttribute() to "noShade"] - expected: FAIL - - [hr.noShade: IDL set to ""] - expected: FAIL - - [hr.noShade: IDL set to " foo "] - expected: FAIL - - [hr.noShade: IDL set to undefined] - expected: FAIL - - [hr.noShade: IDL set to null] - expected: FAIL - - [hr.noShade: IDL set to 7] - expected: FAIL - - [hr.noShade: IDL set to 1.5] - expected: FAIL - - [hr.noShade: IDL set to "5%"] - expected: FAIL - - [hr.noShade: IDL set to "+100"] - expected: FAIL - - [hr.noShade: IDL set to ".5"] - expected: FAIL - - [hr.noShade: IDL set to false] - expected: FAIL - - [hr.noShade: IDL set to object "[object Object\]"] - expected: FAIL - - [hr.noShade: IDL set to NaN] - expected: FAIL - - [hr.noShade: IDL set to Infinity] - expected: FAIL - - [hr.noShade: IDL set to -Infinity] - expected: FAIL - - [hr.noShade: IDL set to "\\0"] - expected: FAIL - - [hr.noShade: IDL set to object "test-toString"] - expected: FAIL - - [hr.noShade: IDL set to object "test-valueOf"] - expected: FAIL - - [hr.size: typeof IDL attribute] - expected: FAIL - - [hr.size: IDL get with DOM attribute unset] - expected: FAIL - - [hr.size: setAttribute() to ""] - expected: FAIL - - [hr.size: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "] - expected: FAIL - - [hr.size: setAttribute() to undefined] - expected: FAIL - - [hr.size: setAttribute() to 7] - expected: FAIL - - [hr.size: setAttribute() to 1.5] - expected: FAIL - - [hr.size: setAttribute() to "5%"] - expected: FAIL - - [hr.size: setAttribute() to "+100"] - expected: FAIL - - [hr.size: setAttribute() to ".5"] - expected: FAIL - - [hr.size: setAttribute() to true] - expected: FAIL - - [hr.size: setAttribute() to false] - expected: FAIL - - [hr.size: setAttribute() to object "[object Object\]"] - expected: FAIL - - [hr.size: setAttribute() to NaN] - expected: FAIL - - [hr.size: setAttribute() to Infinity] - expected: FAIL - - [hr.size: setAttribute() to -Infinity] - expected: FAIL - - [hr.size: setAttribute() to "\\0"] - expected: FAIL - - [hr.size: setAttribute() to null] - expected: FAIL - - [hr.size: setAttribute() to object "test-toString"] - expected: FAIL - - [hr.size: setAttribute() to object "test-valueOf"] - expected: FAIL - - [hr.size: IDL set to ""] - expected: FAIL - - [hr.size: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "] - expected: FAIL - - [hr.size: IDL set to undefined] - expected: FAIL - - [hr.size: IDL set to 7] - expected: FAIL - - [hr.size: IDL set to 1.5] - expected: FAIL - - [hr.size: IDL set to "5%"] - expected: FAIL - - [hr.size: IDL set to "+100"] - expected: FAIL - - [hr.size: IDL set to ".5"] - expected: FAIL - - [hr.size: IDL set to true] - expected: FAIL - - [hr.size: IDL set to false] - expected: FAIL - - [hr.size: IDL set to object "[object Object\]"] - expected: FAIL - - [hr.size: IDL set to NaN] - expected: FAIL - - [hr.size: IDL set to Infinity] - expected: FAIL - - [hr.size: IDL set to -Infinity] - expected: FAIL - - [hr.size: IDL set to "\\0"] - expected: FAIL - - [hr.size: IDL set to null] - expected: FAIL - - [hr.size: IDL set to object "test-toString"] - expected: FAIL - - [hr.size: IDL set to object "test-valueOf"] - expected: FAIL - [pre.accessKey: typeof IDL attribute] expected: FAIL diff --git a/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-ref.html b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-ref.html new file mode 100644 index 00000000000..03a21eb4573 --- /dev/null +++ b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-ref.html @@ -0,0 +1,20 @@ + + + + + + +
+
+ + + diff --git a/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-with-color-or-noshade-ref.html b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-with-color-or-noshade-ref.html new file mode 100644 index 00000000000..d6300e250d9 --- /dev/null +++ b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-with-color-or-noshade-ref.html @@ -0,0 +1,17 @@ + + + + + + +
+
+
+
+ + + diff --git a/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-with-color-or-noshade.html b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-with-color-or-noshade.html new file mode 100644 index 00000000000..db1d583934e --- /dev/null +++ b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size-with-color-or-noshade.html @@ -0,0 +1,15 @@ + + + +hr elements: Tests behaviour of a size attribute with color/noshade attributes present + + + + +
+
+
+
+ + + diff --git a/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size.html b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size.html new file mode 100644 index 00000000000..2162131b853 --- /dev/null +++ b/tests/wpt/tests/html/rendering/non-replaced-elements/the-hr-element-0/size.html @@ -0,0 +1,13 @@ + + + +hr elements: Tests behaviour of a size attribute without color/noshade attributes + + + + +
+
+ + +