From 004c0595186afac7dcf86604aaa41c1036c7e500 Mon Sep 17 00:00:00 2001 From: Patrick Shaughnessy Date: Thu, 30 Jan 2020 15:58:52 -0500 Subject: [PATCH] fix DOMTokenList --- components/script/dom/domtokenlist.rs | 46 +++++++---- .../dom/nodes/Element-classlist.html.ini | 77 ------------------- 2 files changed, 33 insertions(+), 90 deletions(-) delete mode 100644 tests/wpt/metadata/dom/nodes/Element-classlist.html.ini diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index b870ab4f16da..7f56f58c5029 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -52,6 +52,17 @@ impl DOMTokenList { slice => Ok(Atom::from(slice)), } } + + // https://dom.spec.whatwg.org/#concept-dtl-update + fn perform_update_steps(&self, atoms: Vec) { + // Step 1 + if !self.element.has_attribute(&self.local_name) && atoms.len() == 0 { + return; + } + // step 2 + self.element + .set_atomic_tokenlist_attribute(&self.local_name, atoms) + } } // https://dom.spec.whatwg.org/#domtokenlist @@ -93,8 +104,7 @@ impl DOMTokenListMethods for DOMTokenList { atoms.push(token); } } - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(()) } @@ -108,8 +118,7 @@ impl DOMTokenListMethods for DOMTokenList { .position(|atom| *atom == token) .map(|index| atoms.remove(index)); } - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(()) } @@ -122,8 +131,7 @@ impl DOMTokenListMethods for DOMTokenList { Some(true) => Ok(true), _ => { atoms.remove(index); - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(false) }, }, @@ -131,8 +139,7 @@ impl DOMTokenListMethods for DOMTokenList { Some(false) => Ok(false), _ => { atoms.push(token); - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(true) }, }, @@ -166,14 +173,27 @@ impl DOMTokenListMethods for DOMTokenList { let mut atoms = self.element.get_tokenlist_attribute(&self.local_name); let mut result = false; if let Some(pos) = atoms.iter().position(|atom| *atom == token) { - if !atoms.contains(&new_token) { - atoms[pos] = new_token; + if let Some(redundant_pos) = atoms.iter().position(|atom| *atom == new_token) { + if redundant_pos > pos { + // The replacement is already in the list, later, + // so we perform the replacement and remove the + // later copy. + atoms[pos] = new_token; + atoms.remove(redundant_pos); + } else if redundant_pos < pos { + // The replacement is already in the list, earlier, + // so we remove the index where we'd be putting the + // later copy. + atoms.remove(pos); + } + // else we are replacing the token with itself, nothing to change } else { - atoms.remove(pos); + // The replacement is not in the list already + atoms[pos] = new_token; } + // Step 5. - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); result = true; } Ok(result) diff --git a/tests/wpt/metadata/dom/nodes/Element-classlist.html.ini b/tests/wpt/metadata/dom/nodes/Element-classlist.html.ini deleted file mode 100644 index 95c9293d9955..000000000000 --- a/tests/wpt/metadata/dom/nodes/Element-classlist.html.ini +++ /dev/null @@ -1,77 +0,0 @@ -[Element-classlist.html] - type: testharness - [classList.remove("a") with attribute value null (HTML node)] - expected: FAIL - - [classList.remove("a", "b") with attribute value null (HTML node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a" (HTML node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a a a b" (HTML node)] - expected: FAIL - - [classList.replace("c", "a") with attribute value "c b a" (HTML node)] - expected: FAIL - - [classList.remove("a") with attribute value null (XHTML node)] - expected: FAIL - - [classList.remove("a", "b") with attribute value null (XHTML node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a" (XHTML node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a a a b" (XHTML node)] - expected: FAIL - - [classList.replace("c", "a") with attribute value "c b a" (XHTML node)] - expected: FAIL - - [classList.remove("a") with attribute value null (MathML node)] - expected: FAIL - - [classList.remove("a", "b") with attribute value null (MathML node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a" (MathML node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a a a b" (MathML node)] - expected: FAIL - - [classList.replace("c", "a") with attribute value "c b a" (MathML node)] - expected: FAIL - - [classList.remove("a") with attribute value null (XML node with null namespace)] - expected: FAIL - - [classList.remove("a", "b") with attribute value null (XML node with null namespace)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a" (XML node with null namespace)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a a a b" (XML node with null namespace)] - expected: FAIL - - [classList.replace("c", "a") with attribute value "c b a" (XML node with null namespace)] - expected: FAIL - - [classList.remove("a") with attribute value null (foo node)] - expected: FAIL - - [classList.remove("a", "b") with attribute value null (foo node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a" (foo node)] - expected: FAIL - - [classList.replace("a", "a") with attribute value "a a a b" (foo node)] - expected: FAIL - - [classList.replace("c", "a") with attribute value "c b a" (foo node)] - expected: FAIL -