Skip to content

Commit ab67050

Browse files
committed
DomTokenList.forEach() now takes care of the current state of the list
1 parent 1898697 commit ab67050

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

src/changes/changes.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
<body>
1010
<release version="4.12.0" date="April xx, 2025" description="Chrome/Edge 135, Firefox 137, Rhino RegExp, Bugfixes">
11+
<action type="fix" dev="rbri">
12+
DomTokenList.forEach() now takes care of the current state of the list
13+
(e.g. the forEach function might add/remove elements to the list itself).
14+
</action>
1115
<action type="fix" dev="rbri">
1216
NodeList.forEach() now takes care of the current state of the list
1317
(e.g. the forEach function might add/remove elements to the list itself).

src/main/java/org/htmlunit/javascript/host/dom/DOMTokenList.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,16 @@ public void forEach(final Object callback) {
421421
final ContextAction<Object> contextAction = cx -> {
422422
final Function function = (Function) callback;
423423
final Scriptable scope = getParentScope();
424-
final List<String> parts = split(value);
424+
425+
List<String> parts = split(value);
425426
final int size = parts.size();
426-
for (int i = 0; i < size; i++) {
427+
int i = 0;
428+
while (i < size && i < parts.size()) {
427429
function.call(cx, scope, this, new Object[] {parts.get(i), i, this});
430+
431+
// refresh
432+
parts = split(getValue());
433+
i++;
428434
}
429435
return null;
430436
};

src/test/java/org/htmlunit/javascript/host/dom/DOMTokenListTest.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,90 @@ public void forEach() throws Exception {
210210
loadPageVerifyTitle2(html);
211211
}
212212

213+
/**
214+
* @throws Exception if the test fails
215+
*/
216+
@Test
217+
@Alerts({"4", "a", "b", "c", "d", "4"})
218+
public void forEachAdd() throws Exception {
219+
final String html = DOCTYPE_HTML
220+
+ "<html><head><script>\n"
221+
+ LOG_TITLE_FUNCTION
222+
+ "function test() {\n"
223+
+ " var list = document.getElementById('d1').classList;\n"
224+
+ " log(list.length);\n"
225+
226+
+ " list.forEach((i) => {\n"
227+
+ " log(i);\n"
228+
+ " if (list.lenght < 7) { list.add('new ' + i); }\n"
229+
+ " });\n"
230+
231+
+ " log(list.length);\n"
232+
+ "}\n"
233+
+ "</script></head><body onload='test()'>\n"
234+
+ " <div id='d1' class='a b c d'></div>\n"
235+
+ "</body></html>";
236+
237+
loadPageVerifyTitle2(html);
238+
}
239+
240+
/**
241+
* @throws Exception if the test fails
242+
*/
243+
@Test
244+
@Alerts({"4", "a", "c", "d", "3"})
245+
public void forEachRemove() throws Exception {
246+
final String html = DOCTYPE_HTML
247+
+ "<html><head><script>\n"
248+
+ LOG_TITLE_FUNCTION
249+
+ "function test() {\n"
250+
+ " var list = document.getElementById('d1').classList;\n"
251+
+ " log(list.length);\n"
252+
253+
+ " list.forEach((i) => {\n"
254+
+ " log(i);\n"
255+
+ " list.remove('a');\n"
256+
+ " });\n"
257+
258+
+ " log(list.length);\n"
259+
+ "}\n"
260+
+ "</script></head><body onload='test()'>\n"
261+
+ " <div id='d1' class='a b c d'></div>\n"
262+
+ "</body></html>";
263+
264+
loadPageVerifyTitle2(html);
265+
}
266+
267+
268+
/**
269+
* @throws Exception if the test fails
270+
*/
271+
@Test
272+
@Alerts({"4", "a", "1"})
273+
public void forEachRemove2() throws Exception {
274+
final String html = DOCTYPE_HTML
275+
+ "<html><head><script>\n"
276+
+ LOG_TITLE_FUNCTION
277+
+ "function test() {\n"
278+
+ " var list = document.getElementById('d1').classList;\n"
279+
+ " log(list.length);\n"
280+
281+
+ " list.forEach((i) => {\n"
282+
+ " log(i);\n"
283+
+ " list.remove('a');\n"
284+
+ " list.remove('c');\n"
285+
+ " list.remove('d');\n"
286+
+ " });\n"
287+
288+
+ " log(list.length);\n"
289+
+ "}\n"
290+
+ "</script></head><body onload='test()'>\n"
291+
+ " <div id='d1' class='a b c d'></div>\n"
292+
+ "</body></html>";
293+
294+
loadPageVerifyTitle2(html);
295+
}
296+
213297
/**
214298
* @throws Exception if the test fails
215299
*/

0 commit comments

Comments
 (0)