aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/htmloptionelement.rs41
-rwxr-xr-xcomponents/script/dom/htmlselectelement.rs2
-rw-r--r--components/script/dom/webidls/HTMLOptionElement.webidl2
-rw-r--r--tests/wpt/metadata/html/dom/idlharness.https.html.ini9
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-option-element/option-index.html.ini14
5 files changed, 43 insertions, 25 deletions
diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs
index 4ebb2860a79..d61f4b6ffb0 100644
--- a/components/script/dom/htmloptionelement.rs
+++ b/components/script/dom/htmloptionelement.rs
@@ -28,6 +28,7 @@ use crate::dom::window::Window;
use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix, QualName};
use std::cell::Cell;
+use std::convert::TryInto;
use style::element_state::ElementState;
use style::str::{split_html_space_chars, str_join};
@@ -127,6 +128,41 @@ impl HTMLOptionElement {
select.ask_for_reset();
}
}
+
+ // https://html.spec.whatwg.org/multipage/#concept-option-index
+ fn index(&self) -> i32 {
+ if let Some(parent) = self.upcast::<Node>().GetParentNode() {
+ if let Some(select_parent) = parent.downcast::<HTMLSelectElement>() {
+ // return index in parent select's list of options
+ return self.index_in_select(select_parent);
+ } else if parent.is::<HTMLOptGroupElement>() {
+ if let Some(grandparent) = parent.GetParentNode() {
+ if let Some(select_grandparent) = grandparent.downcast::<HTMLSelectElement>() {
+ // return index in grandparent select's list of options
+ return self.index_in_select(select_grandparent);
+ }
+ }
+ }
+ }
+ // "If the option element is not in a list of options,
+ // then the option element's index is zero."
+ // self is neither a child of a select, nor a grandchild of a select
+ // via an optgroup, so it is not in a list of options
+ 0
+ }
+
+ fn index_in_select(&self, select: &HTMLSelectElement) -> i32 {
+ match select.list_of_options().position(|n| &*n == self) {
+ Some(index) => index.try_into().unwrap_or(0),
+ None => {
+ // shouldn't happen but not worth a browser panic
+ warn!(
+ "HTMLOptionElement called index_in_select at a select that did not contain it"
+ );
+ 0
+ },
+ }
+ }
}
// FIXME(ajeffrey): Provide a way of buffering DOMStrings other than using Strings
@@ -225,6 +261,11 @@ impl HTMLOptionElementMethods for HTMLOptionElement {
self.selectedness.set(selected);
self.pick_if_selected_and_reset();
}
+
+ // https://html.spec.whatwg.org/multipage/#dom-option-index
+ fn Index(&self) -> i32 {
+ self.index()
+ }
}
impl VirtualMethods for HTMLOptionElement {
diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs
index f6330b9b65a..bef4bfff8b4 100755
--- a/components/script/dom/htmlselectelement.rs
+++ b/components/script/dom/htmlselectelement.rs
@@ -102,7 +102,7 @@ impl HTMLSelectElement {
}
// https://html.spec.whatwg.org/multipage/#concept-select-option-list
- fn list_of_options(&self) -> impl Iterator<Item = DomRoot<HTMLOptionElement>> {
+ pub fn list_of_options(&self) -> impl Iterator<Item = DomRoot<HTMLOptionElement>> {
self.upcast::<Node>().children().flat_map(|node| {
if node.is::<HTMLOptionElement>() {
let node = DomRoot::downcast::<HTMLOptionElement>(node).unwrap();
diff --git a/components/script/dom/webidls/HTMLOptionElement.webidl b/components/script/dom/webidls/HTMLOptionElement.webidl
index 65f37458295..c995070d0e7 100644
--- a/components/script/dom/webidls/HTMLOptionElement.webidl
+++ b/components/script/dom/webidls/HTMLOptionElement.webidl
@@ -22,5 +22,5 @@ interface HTMLOptionElement : HTMLElement {
[CEReactions]
attribute DOMString text;
- // readonly attribute long index;
+ readonly attribute long index;
};
diff --git a/tests/wpt/metadata/html/dom/idlharness.https.html.ini b/tests/wpt/metadata/html/dom/idlharness.https.html.ini
index 7d065c82a88..87fb3f15f10 100644
--- a/tests/wpt/metadata/html/dom/idlharness.https.html.ini
+++ b/tests/wpt/metadata/html/dom/idlharness.https.html.ini
@@ -2337,9 +2337,6 @@
[HTMLInputElement interface: createInput("url") must inherit property "stepDown(long)" with the proper type]
expected: FAIL
- [HTMLOptionElement interface: new Option() must inherit property "index" with the proper type]
- expected: FAIL
-
[HTMLInputElement interface: createInput("password") must inherit property "height" with the proper type]
expected: FAIL
@@ -3702,9 +3699,6 @@
[HTMLInputElement interface: calling setCustomValidity(DOMString) on createInput("range") with too few arguments must throw TypeError]
expected: FAIL
- [HTMLOptionElement interface: attribute index]
- expected: FAIL
-
[HTMLInputElement interface: document.createElement("input") must inherit property "valueAsNumber" with the proper type]
expected: FAIL
@@ -4923,9 +4917,6 @@
[HTMLInputElement interface: createInput("number") must inherit property "valueAsDate" with the proper type]
expected: FAIL
- [HTMLOptionElement interface: document.createElement("option") must inherit property "index" with the proper type]
- expected: FAIL
-
[HTMLInputElement interface: createInput("email") must inherit property "setCustomValidity(DOMString)" with the proper type]
expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/forms/the-option-element/option-index.html.ini b/tests/wpt/metadata/html/semantics/forms/the-option-element/option-index.html.ini
deleted file mode 100644
index 07f5873d1b4..00000000000
--- a/tests/wpt/metadata/html/semantics/forms/the-option-element/option-index.html.ini
+++ /dev/null
@@ -1,14 +0,0 @@
-[option-index.html]
- type: testharness
- [option index should work inside the document]
- expected: FAIL
-
- [option index should always be 0 for options in datalists]
- expected: FAIL
-
- [option index should always be 0 for options with no container]
- expected: FAIL
-
- [option index should always be 0 for options not even in the document]
- expected: FAIL
-