diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 0d8770c0699..f565f7821a7 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -16,6 +16,7 @@ use chrono::{Datelike, TimeZone}; use cssparser::CowRcStr; use html5ever::{LocalName, Namespace}; use lazy_static::lazy_static; +use num_traits::Zero; use regex::Regex; use servo_atoms::Atom; @@ -456,10 +457,20 @@ impl DOMString { None } + /// Applies the same processing as `parse_floating_point_number` with some additional handling + /// according to ECMA's string conversion steps. + /// + /// Used for specific elements when handling floating point values, namely the `number` and + /// `range` inputs, as well as `meter` and `progress` elements. + /// /// + /// pub fn set_best_representation_of_the_floating_point_number(&mut self) { if let Some(val) = self.parse_floating_point_number() { - self.0 = val.to_string(); + // [tc39] Step 2: If x is either +0 or -0, return "0". + let parsed_value = if val.is_zero() { 0.0_f64 } else { val }; + + self.0 = parsed_value.to_string() } } diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 20649baa774..40315c3ecdf 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -2189,7 +2189,13 @@ impl HTMLInputElement { datetime.format("%Y-%m-%dT%H:%M:%S%.3f").to_string(), )) }, - InputType::Number | InputType::Range => Ok(DOMString::from(value.to_string())), + InputType::Number | InputType::Range => { + let mut value = DOMString::from(value.to_string()); + + value.set_best_representation_of_the_floating_point_number(); + + Ok(value) + }, // this won't be called from other input types _ => unreachable!(), } diff --git a/components/script/dom/htmlmeterelement.rs b/components/script/dom/htmlmeterelement.rs index 53fa61e9074..034f01283ea 100644 --- a/components/script/dom/htmlmeterelement.rs +++ b/components/script/dom/htmlmeterelement.rs @@ -12,6 +12,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLMeterElementBinding::HTMLMeterE use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::bindings::str::DOMString; use crate::dom::document::Document; use crate::dom::element::Element; use crate::dom::htmlelement::HTMLElement; @@ -75,8 +76,12 @@ impl HTMLMeterElementMethods for HTMLMeterElement { /// fn SetValue(&self, value: Finite) { + let mut string_value = DOMString::from_string((*value).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + self.upcast::() - .set_string_attribute(&local_name!("value"), (*value).to_string().into()); + .set_string_attribute(&local_name!("value"), string_value); } /// @@ -91,8 +96,12 @@ impl HTMLMeterElementMethods for HTMLMeterElement { /// fn SetMin(&self, value: Finite) { + let mut string_value = DOMString::from_string((*value).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + self.upcast::() - .set_string_attribute(&local_name!("min"), (*value).to_string().into()); + .set_string_attribute(&local_name!("min"), string_value); } /// @@ -108,8 +117,12 @@ impl HTMLMeterElementMethods for HTMLMeterElement { /// fn SetMax(&self, value: Finite) { + let mut string_value = DOMString::from_string((*value).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + self.upcast::() - .set_string_attribute(&local_name!("max"), (*value).to_string().into()); + .set_string_attribute(&local_name!("max"), string_value); } /// @@ -129,8 +142,12 @@ impl HTMLMeterElementMethods for HTMLMeterElement { /// fn SetLow(&self, value: Finite) { + let mut string_value = DOMString::from_string((*value).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + self.upcast::() - .set_string_attribute(&local_name!("low"), (*value).to_string().into()); + .set_string_attribute(&local_name!("low"), string_value); } /// @@ -154,8 +171,12 @@ impl HTMLMeterElementMethods for HTMLMeterElement { /// fn SetHigh(&self, value: Finite) { + let mut string_value = DOMString::from_string((*value).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + self.upcast::() - .set_string_attribute(&local_name!("high"), (*value).to_string().into()); + .set_string_attribute(&local_name!("high"), string_value); } /// @@ -175,7 +196,11 @@ impl HTMLMeterElementMethods for HTMLMeterElement { /// fn SetOptimum(&self, value: Finite) { + let mut string_value = DOMString::from_string((*value).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + self.upcast::() - .set_string_attribute(&local_name!("optimum"), (*value).to_string().into()); + .set_string_attribute(&local_name!("optimum"), string_value); } } diff --git a/components/script/dom/htmlprogresselement.rs b/components/script/dom/htmlprogresselement.rs index 62f05a5c7db..a4c39f3e9ec 100644 --- a/components/script/dom/htmlprogresselement.rs +++ b/components/script/dom/htmlprogresselement.rs @@ -10,6 +10,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLProgressElementBinding::HTMLPro use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::bindings::str::DOMString; use crate::dom::document::Document; use crate::dom::element::Element; use crate::dom::htmlelement::HTMLElement; @@ -75,11 +76,15 @@ impl HTMLProgressElementMethods for HTMLProgressElement { }) } - // https://html.spec.whatwg.org/multipage/#dom-progress-value + /// fn SetValue(&self, new_val: Finite) { - if 0.0 <= *new_val { + if *new_val >= 0.0 { + let mut string_value = DOMString::from_string((*new_val).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + self.upcast::() - .set_string_attribute(&local_name!("value"), (*new_val).to_string().into()); + .set_string_attribute(&local_name!("value"), string_value); } } @@ -100,10 +105,16 @@ impl HTMLProgressElementMethods for HTMLProgressElement { }) } - // https://html.spec.whatwg.org/multipage/#dom-progress-max + /// fn SetMax(&self, new_val: Finite) { - self.upcast::() - .set_string_attribute(&local_name!("max"), (*new_val).to_string().into()); + if *new_val > 0.0 { + let mut string_value = DOMString::from_string((*new_val).to_string()); + + string_value.set_best_representation_of_the_floating_point_number(); + + self.upcast::() + .set_string_attribute(&local_name!("max"), string_value); + } } // https://html.spec.whatwg.org/multipage/#dom-progress-position diff --git a/tests/wpt/meta-legacy-layout/html/dom/reflection-forms.html.ini b/tests/wpt/meta-legacy-layout/html/dom/reflection-forms.html.ini index f18e02cb406..8a32689d65f 100644 --- a/tests/wpt/meta-legacy-layout/html/dom/reflection-forms.html.ini +++ b/tests/wpt/meta-legacy-layout/html/dom/reflection-forms.html.ini @@ -20181,39 +20181,21 @@ [meter.value: IDL get with DOM attribute unset] expected: FAIL - [meter.value: IDL set to -0] - expected: FAIL - [meter.min: IDL get with DOM attribute unset] expected: FAIL - [meter.min: IDL set to -0] - expected: FAIL - [meter.max: IDL get with DOM attribute unset] expected: FAIL - [meter.max: IDL set to -0] - expected: FAIL - [meter.low: IDL get with DOM attribute unset] expected: FAIL - [meter.low: IDL set to -0] - expected: FAIL - [meter.high: IDL get with DOM attribute unset] expected: FAIL - [meter.high: IDL set to -0] - expected: FAIL - [meter.optimum: IDL get with DOM attribute unset] expected: FAIL - [meter.optimum: IDL set to -0] - expected: FAIL - [optgroup.accessKey: setAttribute() to "5%"] expected: FAIL @@ -20802,18 +20784,6 @@ [progress.max: setAttribute() to "+100"] expected: FAIL - [progress.max: IDL set to -10000000000] - expected: FAIL - - [progress.max: IDL set to -1] - expected: FAIL - - [progress.max: IDL set to -0] - expected: FAIL - - [progress.max: IDL set to 0] - expected: FAIL - [progress.max: IDL set to 1e-10] expected: FAIL diff --git a/tests/wpt/meta/html/dom/reflection-forms.html.ini b/tests/wpt/meta/html/dom/reflection-forms.html.ini index 4498919cd97..e216a11a0c0 100644 --- a/tests/wpt/meta/html/dom/reflection-forms.html.ini +++ b/tests/wpt/meta/html/dom/reflection-forms.html.ini @@ -3380,24 +3380,6 @@ [meter.tabIndex: IDL set to -2147483648] expected: FAIL - [meter.value: IDL set to -0] - expected: FAIL - - [meter.min: IDL set to -0] - expected: FAIL - - [meter.max: IDL set to -0] - expected: FAIL - - [meter.low: IDL set to -0] - expected: FAIL - - [meter.high: IDL set to -0] - expected: FAIL - - [meter.optimum: IDL set to -0] - expected: FAIL - [form.tabIndex: setAttribute() to "7\\v"] expected: FAIL @@ -3551,18 +3533,6 @@ [progress.max: setAttribute() to "+100"] expected: FAIL - [progress.max: IDL set to -10000000000] - expected: FAIL - - [progress.max: IDL set to -1] - expected: FAIL - - [progress.max: IDL set to -0] - expected: FAIL - - [progress.max: IDL set to 0] - expected: FAIL - [progress.max: IDL set to 1e-10] expected: FAIL