diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f10fff0b9b..6d91355cbf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -8,6 +8,10 @@ + + DOMTokenList.toggle() now honors the optional force argument: a true value only adds the token + and a false value only removes it, matching the DOM standard. + Content-Security-Policy: XMLHttpRequest supports the connect-src directive (with default-src as fallback); the request url and all redirect targets are checked, blocked requests fail with a network error. diff --git a/src/main/java/org/htmlunit/javascript/host/dom/DOMTokenList.java b/src/main/java/org/htmlunit/javascript/host/dom/DOMTokenList.java index 9756656fba..217efa5a4e 100644 --- a/src/main/java/org/htmlunit/javascript/host/dom/DOMTokenList.java +++ b/src/main/java/org/htmlunit/javascript/host/dom/DOMTokenList.java @@ -277,10 +277,12 @@ public boolean replace(final String oldToken, final String newToken) { /** * Toggles the token, adding or removing it. * @param token the token to add or remove + * @param force if {@code true}, only adds the token; if {@code false}, only removes it; + * if not specified, the token is toggled * @return whether the string now contains the token or not */ @JsxFunction - public boolean toggle(final String token) { + public boolean toggle(final String token, final Object force) { if (org.htmlunit.util.StringUtils.isEmptyOrNull(token)) { throw JavaScriptEngine.asJavaScriptException( getWindow(), @@ -295,15 +297,18 @@ public boolean toggle(final String token) { } final List parts = split(getValue()); - if (parts.contains(token)) { + final boolean present = parts.contains(token); + final boolean add = JavaScriptEngine.isUndefined(force) ? !present : JavaScriptEngine.toBoolean(force); + + if (add && !present) { + parts.add(token); + updateAttribute(String.join(" ", parts)); + } + else if (!add && present) { parts.remove(token); updateAttribute(String.join(" ", parts)); - return false; } - - parts.add(token); - updateAttribute(String.join(" ", parts)); - return true; + return add; } /** diff --git a/src/test/java/org/htmlunit/javascript/host/dom/DOMTokenListTest.java b/src/test/java/org/htmlunit/javascript/host/dom/DOMTokenListTest.java index b4a065097d..d67c4ba3ab 100644 --- a/src/test/java/org/htmlunit/javascript/host/dom/DOMTokenListTest.java +++ b/src/test/java/org/htmlunit/javascript/host/dom/DOMTokenListTest.java @@ -1760,6 +1760,85 @@ public void toggleNotDefined() throws Exception { toggle(null, "a"); } + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"a", "1", "true", "2", "a\\sb", + "", + "class\\schanged\\sold:\\sa"}) + public void toggleForceTrueAdds() throws Exception { + toggle("a", "b", "true"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"a\\sb", "2", "true", "2", "a\\sb", + ""}) + public void toggleForceTrueKeeps() throws Exception { + toggle("a b", "b", "true"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"a\\sb", "2", "false", "1", "a", + "", + "class\\schanged\\sold:\\sa\\sb"}) + public void toggleForceFalseRemoves() throws Exception { + toggle("a b", "b", "false"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"a", "1", "false", "1", "a", + ""}) + public void toggleForceFalseKeeps() throws Exception { + toggle("a", "b", "false"); + } + + private void toggle(final String in, final String token, final String force) throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "\n" + + "\n" + + "
\n" + + ""; + + loadPageVerifyTitle2(html); + } + private void toggle(final String in, final String token) throws Exception { String html = DOCTYPE_HTML + "\n"