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