diff --git a/components/script/dom/htmlprogresselement.rs b/components/script/dom/htmlprogresselement.rs index dcd2f018734..718d1999256 100644 --- a/components/script/dom/htmlprogresselement.rs +++ b/components/script/dom/htmlprogresselement.rs @@ -4,8 +4,10 @@ use crate::dom::bindings::codegen::Bindings::HTMLProgressElementBinding::HTMLProgressElementMethods; use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::num::Finite; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::document::Document; +use crate::dom::element::Element; use crate::dom::htmlelement::HTMLElement; use crate::dom::node::Node; use crate::dom::nodelist::NodeList; @@ -48,4 +50,76 @@ impl HTMLProgressElement { impl HTMLProgressElementMethods for HTMLProgressElement { // https://html.spec.whatwg.org/multipage/#dom-lfe-labels make_labels_getter!(Labels, labels_node_list); + + // https://html.spec.whatwg.org/multipage/#dom-progress-value + fn Value(&self) -> Finite { + // In case of missing `value`, parse error, or negative `value`, `value` should be + // interpreted as 0. As `get_string_attribute` returns an empty string in case the + // attribute is missing, this case is handeled as the default of the `map_or` function. + // + // It is safe to wrap the number coming from `parse_floating_point_number` as it will + // return Err on inf and nan + self.upcast::() + .get_string_attribute(&local_name!("value")) + .parse_floating_point_number() + .map_or(Finite::wrap(0.0), |v| { + if v < 0.0 { + Finite::wrap(0.0) + } else { + Finite::wrap(v.min(*self.Max())) + } + }) + } + + // https://html.spec.whatwg.org/multipage/#dom-progress-value + fn SetValue(&self, new_val: Finite) { + if 0.0 <= *new_val { + self.upcast::() + .set_string_attribute(&local_name!("value"), (*new_val).to_string().into()); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-progress-max + fn Max(&self) -> Finite { + // In case of missing `max`, parse error, or negative `max`, `max` should be interpreted as + // 1.0. As `get_string_attribute` returns an empty string in case the attribute is missing, + // these cases are handeled by `map_or` + self.upcast::() + .get_string_attribute(&local_name!("max")) + .parse_floating_point_number() + .map_or(Finite::wrap(1.0), |m| { + if m <= 0.0 { + Finite::wrap(1.0) + } else { + Finite::wrap(m) + } + }) + } + + // 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()); + } + + // https://html.spec.whatwg.org/multipage/#dom-progress-position + fn Position(&self) -> Finite { + let value = self + .upcast::() + .get_string_attribute(&local_name!("value")); + if value.is_empty() { + Finite::wrap(-1.0) + } else { + let value = self.Value(); + let max = self.Max(); + // An unsafe Finite constructor might be nice here, as it's unlikely for the + // compiler to infer the following guarantees. It is probably premature + // optimization though. + // + // Safety: `ret` have to be a finite, defined number. This is the case since both + // value and max is finite, max > 0, and a value >> max cannot exist, as + // Self::Value(&self) enforces value <= max. + Finite::wrap(*value / *max) + } + } } diff --git a/components/script/dom/webidls/HTMLProgressElement.webidl b/components/script/dom/webidls/HTMLProgressElement.webidl index c901e379659..0c25d86977a 100644 --- a/components/script/dom/webidls/HTMLProgressElement.webidl +++ b/components/script/dom/webidls/HTMLProgressElement.webidl @@ -7,10 +7,10 @@ interface HTMLProgressElement : HTMLElement { [HTMLConstructor] constructor(); - // [CEReactions] - // attribute double value; - // [CEReactions] - // attribute double max; - // readonly attribute double position; + [CEReactions] + attribute double value; + [CEReactions] + attribute double max; + readonly attribute double position; readonly attribute NodeList labels; };