View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript;
16  
17  import java.net.URL;
18  
19  import org.htmlunit.WebDriverTestCase;
20  import org.htmlunit.junit.annotation.Alerts;
21  import org.htmlunit.junit.annotation.BuggyWebDriver;
22  import org.htmlunit.junit.annotation.HtmlUnitNYI;
23  import org.htmlunit.util.MimeType;
24  import org.junit.jupiter.api.Test;
25  import org.openqa.selenium.By;
26  import org.openqa.selenium.WebDriver;
27  import org.openqa.selenium.WebDriverException;
28  import org.openqa.selenium.WebElement;
29  
30  /**
31   * Same scope as {@link JavaScriptEngineTest} but extending {@link WebDriverTestCase}.
32   *
33   * @author Marc Guillemot
34   * @author Ahmed Ashour
35   * @author Frank Danek
36   * @author Ronald Brill
37   */
38  public class JavaScriptEngine2Test extends WebDriverTestCase {
39  
40      /**
41       * All browsers except Opera seem to have a single JS execution thread for all windows.
42       * @throws Exception if the test fails
43       */
44      @Test
45      public void jsRunSingleThreadedBrowserWide() throws Exception {
46          final String html = DOCTYPE_HTML
47              + "<html><head><script>\n"
48              + "function test(prefix) {\n"
49              + "  parent.document.getElementById('theArea').value += prefix + ' start\\n';\n"
50              + "  var end = new Date().valueOf() + 1 * 1000;\n"
51              + "  var t = [];\n"
52              + "  while (new Date().valueOf() < end) {\n"
53              + "    var x = document.createElement('iframe');\n"
54              + "    t.push(x);\n"
55              + "  }\n"
56              + "  parent.document.getElementById('theArea').value += prefix + ' end\\n';\n"
57              + "}\n"
58              + "function checkResults() {\n"
59              + "  var value = document.getElementById('theArea').value;\n"
60              + "  var lines = value.split('\\n');\n"
61              + "  if (lines.length < 5)\n"
62              + "    setTimeout(checkResults, 100); // not yet ready, check later\n"
63              + "  value = value.replace(/frame \\d /gi, '').replace(/\\W/gi, '');\n"
64              + "  var singleThreaded = (value == 'startendstartend');\n"
65              + "  document.getElementById('result').innerHTML = (singleThreaded ? 'single threaded' : 'in parallel');\n"
66              + "}\n"
67              + "function doTest() {\n"
68              + "  parent.document.getElementById('theArea').value = '';\n"
69              + "  document.getElementById('frame1').contentWindow.setTimeout(function() {test('frame 1'); }, 10);\n"
70              + "  document.getElementById('frame2').contentWindow.setTimeout(function() {test('frame 2'); }, 10);\n"
71              + "  setTimeout(checkResults, 1000);\n"
72              + "}\n"
73              + "</script></head>\n"
74              + "<body onload='doTest()'>\n"
75              + "<iframe id='frame1' src='about:blank'></iframe>\n"
76              + "<iframe id='frame2' src='about:blank'></iframe>\n"
77              + "<textarea id='theArea' rows='5'></textarea>\n"
78              + "script execution occured: <span id='result'></span>\n"
79              + "</body></html>";
80  
81          final WebDriver driver = loadPage2(html);
82          final WebElement element = driver.findElement(By.id("result"));
83  
84          // give time to the script to execute: normally ~2 seconds when scripts are run sequentially
85          int nbWait = 0;
86          while (element.getText().isEmpty()) {
87              Thread.sleep(100);
88              if (nbWait++ > 50) {
89                  break;
90              }
91          }
92  
93          assertEquals("single threaded", element.getText());
94      }
95  
96      /**
97       * @throws Exception if the test fails
98       */
99      @Test
100     @Alerts({"true", "false", "false", "true"})
101     public void functionCaller() throws Exception {
102         final String html = DOCTYPE_HTML
103             + "<html><head>\n"
104             + "<script>\n"
105             + LOG_TITLE_FUNCTION
106             + "function myFunc() {\n"
107             + "  log(myFunc.caller == null);\n"
108             + "  log(myFunc.caller == foo);\n"
109             + "}\n"
110             + "myFunc()\n"
111             + "function foo() { myFunc() }\n"
112             + "foo()\n"
113             + "</script>\n"
114             + "</head><body></body></html>";
115 
116         loadPageVerifyTitle2(html);
117     }
118 
119     /**
120      * @throws Exception if the test fails
121      */
122     @Test
123     @Alerts({"in goo", "in hoo", "in foo"})
124     public void functionDeclaredForwardInBlock() throws Exception {
125         final String html = DOCTYPE_HTML
126             + "<html><head></head><body>\n"
127             + "<script>\n"
128             + LOG_TITLE_FUNCTION
129             + "  if (true) {\n"
130             + "    goo();\n"
131             + "    function hoo() { log('in hoo'); }\n"
132             + "    try {\n"
133             + "      hoo();\n"
134             + "      foo();\n"
135             + "    } catch(e) {\n"
136             + "      log('foo error');\n"
137             + "    }\n"
138             + "    function foo() { log('in foo'); }\n"
139             + "  }\n"
140             + "  function goo() { log('in goo'); }\n"
141             + "</script>\n"
142             + "</body></html>";
143 
144         loadPageVerifyTitle2(html);
145     }
146 
147     /**
148      * @throws Exception if the test fails
149      */
150     @Test
151     @Alerts({"undefined", "function foo() {}", "function foo() {}", "function foo() {}"})
152     @HtmlUnitNYI(CHROME = {"function foo() {}", "function foo() {}", "function foo() {}", "function foo() {}"},
153             EDGE = {"function foo() {}", "function foo() {}", "function foo() {}", "function foo() {}"},
154             FF = {"function foo() {}", "function foo() {}", "function foo() {}", "function foo() {}"},
155             FF_ESR = {"function foo() {}", "function foo() {}", "function foo() {}", "function foo() {}"})
156     public void variableNotDefined() throws Exception {
157         final String html = DOCTYPE_HTML
158             + "<html><head></head><body>\n"
159             + "<script>\n"
160             + LOG_TITLE_FUNCTION
161             + "if (true) {\n"
162             + "  try {\n"
163             + "    log(window.foo);\n"
164             + "    log(foo);\n"
165             + "  } catch(e) {\n"
166             + "    log('foo error');\n"
167             + "  }\n"
168             + "  function foo() {}\n"
169             + "  try {\n"
170             + "    log(window.foo);\n"
171             + "    log(foo);\n"
172             + "  } catch(e) {\n"
173             + "    log('foo error');\n"
174             + "  }\n"
175             + "}\n"
176             + "</script>\n"
177             + "</body></html>";
178 
179         loadPageVerifyTitle2(html);
180     }
181 
182     /**
183      * @throws Exception if the test fails
184      */
185     @Test
186     @Alerts({"undefined", "foo error", "undefined", "foo error"})
187     public void variableNotDefinedExpression() throws Exception {
188         final String html = DOCTYPE_HTML
189             + "<html><head></head><body>\n"
190             + "<script>\n"
191             + LOG_TITLE_FUNCTION
192             + "if (true) {\n"
193             + "  try {\n"
194             + "    log(window.foo);\n"
195             + "    log(foo);\n"
196             + "  } catch(e) {\n"
197             + "    log('foo error');\n"
198             + "  }\n"
199             + "  var fo = function foo() {}\n"
200             + "  try {\n"
201             + "    log(window.foo);\n"
202             + "    log(foo);\n"
203             + "  } catch(e) {\n"
204             + "    log('foo error');\n"
205             + "  }\n"
206             + "}\n"
207             + "</script>\n"
208             + "</body></html>";
209 
210         loadPageVerifyTitle2(html);
211     }
212 
213     /**
214      * @throws Exception if the test fails
215      */
216     @Test
217     @Alerts({"function Window() { [native code] }", "function Window() { [native code] }", "true",
218              "function HTMLDocument() { [native code] }", "function HTMLDocument() { [native code] }",
219              "true", "function"})
220     public void constructor() throws Exception {
221         final String html = DOCTYPE_HTML
222             + "<html><head></head><body>\n"
223             + "<script>\n"
224             + LOG_TITLE_FUNCTION
225             + "  try { log(Window); } catch(e) { log('ex window'); }\n"
226             + "  log(window.constructor);\n"
227             + "  try {\n"
228             + "    log(window.constructor === Window);\n"
229             + "  } catch(e) {\n"
230             + "    log('ex win const');\n"
231             + "  }\n"
232 
233             + "  try { log(HTMLDocument); } catch(e) { log('ex doc'); }\n"
234             + "  log(document.constructor);\n"
235             + "  try {\n"
236             + "    log(document.constructor === HTMLDocument);\n"
237             + "  } catch(e) {\n"
238             + "    log('exception doc const');\n"
239             + "  }\n"
240             + "  log(typeof new Object().constructor);\n"
241             + "</script>\n"
242             + "</body></html>";
243 
244         loadPageVerifyTitle2(html);
245     }
246 
247     /**
248      * @throws Exception if the test fails
249      */
250     @Test
251     @Alerts("ReferenceError")
252     public void packages() throws Exception {
253         object("Packages");
254     }
255 
256     /**
257      * @throws Exception if the test fails
258      */
259     @Test
260     @Alerts("ReferenceError")
261     public void java() throws Exception {
262         object("java");
263     }
264 
265     /**
266      * @throws Exception if the test fails
267      */
268     @Test
269     @Alerts("undefined")
270     public void object_getClass() throws Exception {
271         object("window.getClass");
272     }
273 
274     private void object(final String object) throws Exception {
275         final String html = DOCTYPE_HTML
276             + "<html><head></head><body>\n"
277             + "<script>\n"
278             + LOG_TITLE_FUNCTION
279             + "try {\n"
280             + "  log(" + object + ");\n"
281             + "} catch(e) {\n"
282             + "  logEx(e);\n"
283             + "}\n"
284             + "</script>\n"
285             + "</body></html>";
286 
287         loadPageVerifyTitle2(html);
288     }
289 
290     /**
291      * @throws Exception if the test fails
292      */
293     @Test
294     @Alerts({"function", "function"})
295     public void inline() throws Exception {
296         final String html = DOCTYPE_HTML
297                 + "<html><head>\n"
298                 + "<script>\n"
299                 + LOG_TITLE_FUNCTION
300                 + "log(typeof Array.prototype.filter);\n"
301                 + "  function test() {\n"
302                 + "    log(typeof Array.prototype.filter);\n"
303                 + "  }\n"
304                 + "</script></head><body onload='test()'>\n"
305                 + "</body></html>";
306 
307         loadPageVerifyTitle2(html);
308     }
309 
310     /**
311      * @throws Exception if the test fails
312      */
313     @Test
314     @Alerts("found")
315     public void enumerateMethods() throws Exception {
316         final String html = DOCTYPE_HTML
317             + "<html><head>\n"
318             + "<script>\n"
319             + LOG_TITLE_FUNCTION
320             + "  function test() {\n"
321             + "    for (var x in document) {\n"
322             + "      if (x == 'getElementById')\n"
323             + "        log('found');\n"
324             + "    }\n"
325             + "  }\n"
326             + "</script></head><body onload='test()'>\n"
327             + "</body></html>";
328 
329         loadPageVerifyTitle2(html);
330     }
331 
332     /**
333      * Unit tests for bug 2531218 reported by Rhino as
334      * <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=477604">Bug 477604 -
335      * Array.concat causes ArrayIndexOutOfBoundException with non dense array</a>.
336      * @throws Exception if the test fails
337      */
338     @Test
339     @Alerts("3")
340     public void array_concat() throws Exception {
341         final String html = DOCTYPE_HTML
342             + "<html><head>\n"
343             + "<script>\n"
344             + LOG_TITLE_FUNCTION
345             + "  function test() {\n"
346             + "    var a = [1, 2, 3];\n"
347             + "    for (var i = 10; i < 20; i++)\n"
348             + "      a[i] = 't' + i;\n"
349             + "    var b = [1, 2, 3];\n"
350             + "    b.concat(a);\n"
351             + "    log(b.length);\n"
352             + "  }\n"
353             + "</script></head><body onload='test()'>\n"
354             + "</body></html>";
355 
356         loadPageVerifyTitle2(html);
357     }
358 
359     /**
360      * @throws Exception if the test fails
361      */
362     @Test
363     @Alerts("function f() {}")
364     public void function_toStringValue() throws Exception {
365         final String html = DOCTYPE_HTML
366             + "<html><head>\n"
367             + "<script>\n"
368             + LOG_TITLE_FUNCTION
369             + "  function f() {}\n"
370             + "  function test() {\n"
371             + "    log(String(f));\n"
372             + "  }\n"
373             + "</script></head><body onload='test()'>\n"
374             + "</body></html>";
375 
376         loadPageVerifyTitle2(html);
377     }
378 
379     /**
380      * @throws Exception if the test fails
381      */
382     @Test
383     @Alerts("WebDriverException thrown")
384     @BuggyWebDriver("WebDriverException NOT thrown")
385     public void function_object_method() throws Exception {
386         final String html = DOCTYPE_HTML
387                 + "<html><head>\n"
388                 + "<script>\n"
389                 + "  try {\n"
390                 + "    log('1');\n"
391                 + "    function document.onclick() {\n"
392                 + "      log('hi');\n"
393                 + "    }\n"
394                 + "    log('2');\n"
395                 + "  } catch(e) { log(e); }\n"
396                 + "</script>\n"
397                 + "</head>\n"
398                 + "<body>\n"
399                 + "</body></html>";
400 
401         final String[] expected = getExpectedAlerts();
402 
403         try {
404             setExpectedAlerts();
405             loadPageWithAlerts2(html);
406 
407             // at the moment we do not get the syntax exception when running in selenium
408             assertEquals("WebDriverException NOT thrown", expected[0]);
409         }
410         catch (final WebDriverException e) {
411             assertEquals("WebDriverException thrown", expected[0]);
412         }
413     }
414 
415     /**
416      * @throws Exception if the test fails
417      */
418     @Test
419     @Alerts("that's it")
420     public void quoteAsUnicodeInString() throws Exception {
421         final String html = DOCTYPE_HTML
422             + "<html><head>\n"
423             + "<script>\n"
424             + LOG_TITLE_FUNCTION
425             + "log('that\\x27s it');\n"
426             + "</script></head><body>\n"
427             + "</body></html>";
428 
429         loadPageVerifyTitle2(html);
430     }
431 
432     /**
433      * @throws Exception if the test fails
434      */
435     @Test
436     @Alerts(DEFAULT = "RangeError",
437             FF = "InternalError/InternalError",
438             FF_ESR = "InternalError/InternalError")
439     @HtmlUnitNYI(CHROME = "InternalError/InternalError",
440             EDGE = "InternalError/InternalError")
441     public void recursion() throws Exception {
442         final String html = DOCTYPE_HTML
443             + "<html><head><script>\n"
444             + "  function recurse(c) {\n"
445             + LOG_TITLE_FUNCTION
446             + "    try {\n"
447             + "      recurse(c++);\n"
448             + "    } catch(e) { logEx(e); }\n"
449             + "  }\n"
450             + "</script></head>\n"
451             + "<body onload='recurse(1)'>\n"
452             + "</body></html>";
453 
454         loadPageVerifyTitle2(html);
455     }
456 
457     /**
458      * String value of native functions starts with \n on IE.
459      * @throws Exception if the test fails
460      */
461     @Test
462     @Alerts({"0", "false", "0"})
463     public void nativeFunction_toStringValue() throws Exception {
464         final String html = DOCTYPE_HTML
465             + "<html><head>\n"
466             + "<script>\n"
467             + LOG_TITLE_FUNCTION
468             + "  function test() {\n"
469             + "    log(String(window.alert).indexOf('function'));\n"
470             + "    log(String(window.alert).charAt(0) == '\\n');\n"
471             + "    log(String(document.getElementById).indexOf('function'));\n"
472             + "  }\n"
473             + "</script></head><body onload='test()'>\n"
474             + "</body></html>";
475 
476         loadPageVerifyTitle2(html);
477     }
478 
479     /**
480      * Regression test for bug <a href="https://sf.net/tracker/?func=detail&atid=448266&aid=1609944&group_id=47038">
481      * https://sf.net/tracker/?func=detail&amp;atid=448266&amp;aid=1609944&amp;group_id=47038</a>.
482      * @throws Exception if the test fails
483      */
484     @Test
485     @Alerts("0")
486     @HtmlUnitNYI(CHROME = "1",
487             EDGE = "1",
488             FF = "1",
489             FF_ESR = "1")
490     public void onloadJavascriptFunction() throws Exception {
491         final String html = DOCTYPE_HTML
492             + "<html><head>\n"
493             + "<script>\n"
494             + "function onload() { alert('foo'); }\n"
495             + "</script></head>\n"
496             + "<body>\n"
497             + "</body></html>";
498 
499         final WebDriver driver = loadPage2(html);
500         assertEquals(Integer.parseInt(getExpectedAlerts()[0]), getCollectedAlerts(driver, 1).size());
501     }
502 
503     /**
504      * @throws Exception if the test fails
505      */
506     @Test
507     @Alerts("foo")
508     public void alert() throws Exception {
509         final String html = DOCTYPE_HTML
510             + "<html><head><title>foo</title><script>\n"
511             + "  alert('foo');\n"
512             + "</script></head><body>\n"
513             + "<p>hello world</p>\n"
514             + "<form name='form1'>\n"
515             + "  <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
516             + "  <input type='text' name='textfield2' id='textfield2'/>\n"
517             + "</form>\n"
518             + "</body></html>";
519 
520         loadPageWithAlerts2(html);
521     }
522 
523     /**
524      * Checks that a dynamically compiled function works in the scope of its birth.
525      * @throws Exception if the test fails
526      */
527     @Test
528     @Alerts("foo")
529     public void scopeOfNewFunction() throws Exception {
530         final String html = DOCTYPE_HTML
531             + "<html><head><script>\n"
532             + LOG_TITLE_FUNCTION
533             + "  var f = new Function('log(\"foo\")');\n"
534             + "  f();\n"
535             + "</script></head><body>\n"
536             + "</body></html>";
537 
538         loadPageVerifyTitle2(html);
539     }
540 
541     /**
542      * @throws Exception if the test fails
543      */
544     @Test
545     @Alerts("foo")
546     public void scopeOfNestedNewFunction() throws Exception {
547         final String html = DOCTYPE_HTML
548             + "<html><head>\n"
549             + "<script>\n"
550             + LOG_TITLE_FUNCTION
551             + "  var foo = 'foo';\n"
552             + "  var f1 = new Function('f = new Function(\"log(foo)\"); f()');\n"
553             + "  f1();\n"
554             + "</script>\n"
555             + "</head>\n"
556             + "<body>\n"
557             + "</body></html>";
558 
559         loadPageVerifyTitle2(html);
560     }
561 
562     /**
563      * Sets value on input expects a string. If you pass in a value that isn't a string
564      * this used to blow up.
565      * @throws Exception if the test fails
566      */
567     @Test
568     @Alerts("1")
569     public void setValuesThatAreNotStrings() throws Exception {
570         final String html = DOCTYPE_HTML
571             + "<html><head>\n"
572             + "<script>\n"
573             + LOG_TITLE_FUNCTION
574             + "function doTest() {\n"
575             + "  document.form1.textfield1.value = 1;\n"
576             + "  log(document.form1.textfield1.value);\n"
577             + "}\n"
578             + "</script></head><body onload='doTest()'>\n"
579             + "<p>hello world</p>\n"
580             + "<form name='form1'>\n"
581             + "  <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
582             + "  <input type='text' name='textfield2' id='textfield2'/>\n"
583             + "</form>\n"
584             + "</body></html>";
585 
586         loadPageVerifyTitle2(html);
587     }
588 
589     /**
590      * @throws Exception if the test fails
591      */
592     @Test
593     @Alerts("foo")
594     public void javaScriptWrappedInHtmlComments() throws Exception {
595         final String html = DOCTYPE_HTML
596             + "<html><head>\n"
597             + "<script language='javascript'><!--\n"
598             + LOG_TITLE_FUNCTION
599             + "function doTest() {\n"
600             + "  log('foo');\n"
601             + "}\n"
602             + "-->\n</script></head>\n"
603             + "<body onload='doTest()'></body></html>";
604 
605         loadPageVerifyTitle2(html);
606     }
607 
608     /**
609      * @throws Exception if the test fails
610      */
611     @Test
612     @Alerts("1")
613     public void javaScriptWrappedInHtmlComments2() throws Exception {
614         final String html = DOCTYPE_HTML
615             + "<html><head>\n"
616             + "<script>\n"
617             + LOG_TITLE_FUNCTION
618             + "</script>\n"
619             + "<script><!--\n"
620             + " log('1');\n"
621             + "--></script>\n"
622             + "</head>\n"
623             + "<body>\n"
624             + "</body></html>";
625 
626         loadPageVerifyTitle2(html);
627     }
628 
629     /**
630      * @throws Exception if the test fails
631      */
632     @Test
633     @Alerts("1")
634     public void javaScriptWrappedInHtmlComments_commentOnOpeningLine() throws Exception {
635         final String html = DOCTYPE_HTML
636             + "<html><head>\n"
637             + "<script language='javascript'><!-- Some comment here\n"
638             + LOG_TITLE_FUNCTION
639             + "function doTest() {\n"
640             + "  log('1');\n"
641             + "}\n"
642             + "-->\n</script></head>\n"
643             + "<body onload='doTest()'></body></html>";
644 
645         loadPageVerifyTitle2(html);
646     }
647 
648     /**
649      * Regression test for bug 1714762.
650      * @throws Exception if the test fails
651      */
652     @Test
653     public void javaScriptWrappedInHtmlComments_commentNotClosed() throws Exception {
654         final String html = DOCTYPE_HTML
655             + "<html><head><title>foo</title>\n"
656             + "<script language='javascript'><!-- log(1);</script>\n"
657             + "<script language='javascript'><!-- </script>\n"
658             + "</head>\n"
659             + "<body></body></html>";
660 
661         loadPageWithAlerts2(html);
662     }
663 
664     /**
665      * @throws Exception if the test fails
666      */
667     @Test
668     @Alerts("undefined")
669     public void javaScriptWrappedInHtmlComments_allOnOneLine() throws Exception {
670         final String html = DOCTYPE_HTML
671             + "<html>\n"
672             + "  <head>\n"
673             + "    <title>test</title>\n"
674             + "    <script>var test;</script>\n"
675             + "    <!-- var test should be undefined since it's on first line -->\n"
676             + "    <!-- but there should be no index out of bounds exception  -->\n"
677             + "    <script> <!-- test = 'abc'; // --> </script>\n"
678             + "  </head>\n"
679             + "  <body onload='alert(test)'>\n"
680             + "  </body>\n"
681             + "</html>";
682 
683         loadPageWithAlerts2(html);
684     }
685 
686     /**
687      * @throws Exception if the test fails
688      */
689     @Test
690     @Alerts("test")
691     public void eventHandlerWithComment() throws Exception {
692         final String html = DOCTYPE_HTML + "<html><body onLoad='alert(\"test\"); // xxx'></body></html>";
693         loadPageWithAlerts2(html);
694     }
695 
696     /**
697      * @throws Exception if the test fails
698      */
699     @Test
700     @Alerts({"2", "3"})
701     public void comment() throws Exception {
702         final String html = DOCTYPE_HTML
703             + "<html><head>\n"
704             + "  <script>\n"
705             + LOG_TITLE_FUNCTION
706             + "    </script>\n"
707             + "<script><!-- log(1);\n"
708             + " log(2);\n"
709             + "log(3)//--></script>\n"
710             + "</head>\n"
711             + "<body>\n"
712             + "</body></html>";
713 
714         loadPageVerifyTitle2(html);
715     }
716 
717     /**
718      * @throws Exception if the test fails
719      */
720     @Test
721     @Alerts({"rstlne-rstlne-rstlne", "rstlno-rstlne-rstlne",
722              "rstlna-rstlne-rstlne", "rstlne-rstlne-rstlne",
723              "rstlni-rstlni-rstlni", "rstlna-rstlna-rstlna"})
724     public void regExpSupport() throws Exception {
725         final String html = DOCTYPE_HTML
726             + "<html>\n"
727             + "  <head>\n"
728             + "    <script id='a'>\n"
729             + LOG_TITLE_FUNCTION
730             + "       var s = new String('rstlne-rstlne-rstlne');\n"
731             + "       log(s);\n"
732             + "       s = s.replace('e', 'o');\n"
733             + "       log(s);\n"
734             + "       s = s.replace(/o/, 'a');\n"
735             + "       log(s);\n"
736             + "       s = s.replace(new RegExp('a'), 'e');\n"
737             + "       log(s);\n"
738             + "       s = s.replace(new RegExp('e', 'g'), 'i');\n"
739             + "       log(s);\n"
740             + "       s = s.replace(/i/g, 'a');\n"
741             + "       log(s);\n"
742             + "    </script>\n"
743             + "  </head>\n"
744             + "  <body>abc</body>\n"
745             + "</html>";
746 
747         loadPageVerifyTitle2(html);
748     }
749 
750     /**
751      * Test ECMA reserved keywords... that are accepted by "normal" browsers
752      * @throws Exception if the test fails
753      */
754     @Test
755     @Alerts("123")
756     public void ecmaReservedKeywords() throws Exception {
757         final String html = DOCTYPE_HTML
758             + "<html><head>\n"
759             + "<script>\n"
760             + LOG_TITLE_FUNCTION
761             + "  var o = {float: 123};\n"
762             + "  log(o.float);\n"
763             + "</script></head><body>\n"
764             + "</body></html>";
765 
766         loadPageVerifyTitle2(html);
767     }
768 
769     /**
770      * @throws Exception if the test fails
771      */
772     @Test
773     @Alerts("[object Window]")
774     public void boundFunction() throws Exception {
775         final String html = DOCTYPE_HTML
776                 + "<html><head><script>\n"
777                 + LOG_TITLE_FUNCTION
778                 + "  function test() {\n"
779                 + "    if (focusMe.bind) {\n"
780                 + "      var boundFunction = focusMe.bind(null);\n"
781                 + "      document.getElementById('myId').addEventListener('focus', boundFunction, true);\n"
782                 + "    }\n"
783                 + "  }\n"
784                 + "  function focusMe() {\n"
785                 + "    log(this);\n"
786                 + "  }\n"
787                 + "</script></head>\n"
788                 + "<body onload='test()'>\n"
789                 + "  <button id='myId'>Click me</button>\n"
790                 + "</body></html>";
791 
792         final WebDriver driver = loadPage2(html);
793         final String[] expectedAlerts = getExpectedAlerts();
794 
795         driver.findElement(By.id("myId")).click();
796         verifyTitle2(driver, expectedAlerts);
797     }
798 
799     /**
800      * @throws Exception if the test fails
801      */
802     @Test
803     @Alerts({"t=undefined", "inside"})
804     public void functionHasNameOfVar() throws Exception {
805         final String html = DOCTYPE_HTML
806                 + "<html><head>\n"
807                 + "<script>\n"
808                 + LOG_TITLE_FUNCTION
809                 + "  function test() {\n"
810                 + "    log('t=' + t);\n"
811                 + "    var t = 42;\n"
812                 + "    ! function t() { log('inside'); } ();\n"
813                 + "  }\n"
814                 + "</script>\n"
815                 + "</head>\n"
816                 + "<body onload='test()'>\n"
817                 + "</body></html>";
818 
819         loadPageVerifyTitle2(html);
820     }
821 
822     /**
823      * @throws Exception if the test fails
824      */
825     @Test
826     @Alerts({"outer abc = 1", "inner abc = function"})
827     public void functionHasNameOfVarStrictMode() throws Exception {
828         final String html = DOCTYPE_HTML
829                 + "<html><head>\n"
830                 + "<script>\n"
831                 + "  'use strict';\n"
832                 + LOG_TITLE_FUNCTION
833                 + "  var abc = 1;\n"
834                 + "  var foo = function abc() { log('inner abc = ' + typeof abc); }\n"
835                 + "  log('outer abc = ' + abc);\n"
836                 + "  foo()\n"
837                 + "</script>\n"
838                 + "</head>\n"
839                 + "<body>\n"
840                 + "</body></html>";
841 
842         loadPageVerifyTitle2(html);
843     }
844 
845     /**
846      * @throws Exception if the test fails
847      */
848     @Test
849     @Alerts({"a", "b"})
850     public void innerFunctionWithSameName() throws Exception {
851         final String html = DOCTYPE_HTML
852                 + "<html><head>\n"
853                 + "<script>\n"
854                 + LOG_TITLE_FUNCTION
855                 + "  var a = function () {\n"
856                 + "    var x = (function x () { log('a') });\n"
857                 + "    return function () { x() };\n"
858                 + "  }();\n"
859 
860                 + "  var b = function () {\n"
861                 + "    var x = (function x () { log('b') });\n"
862                 + "    return function () { x() };\n"
863                 + "  }();\n"
864 
865                 + "  a();\n"
866                 + "  b();\n"
867                 + "</script>\n"
868                 + "</head>\n"
869                 + "<body>\n"
870                 + "</body></html>";
871 
872         loadPageVerifyTitle2(html);
873     }
874 
875     /**
876      * @throws Exception if the test fails
877      */
878     @Test
879     @Alerts("a")
880     public void innerFunctionWithSameNameAsOutsideStrict() throws Exception {
881         final String html = DOCTYPE_HTML
882                 + "<html><head>\n"
883                 + "<script>\n"
884                 + "  'use strict';\n"
885                 + LOG_TITLE_FUNCTION
886                 + "  var a = function () {\n"
887                 + "    var x = (function x () { log('a') });\n"
888                 + "    return function () { x() };\n"
889                 + "  }();\n"
890 
891                 + "  var x = function () { log('x') };\n"
892 
893                 + "  a();\n"
894                 + "</script>\n"
895                 + "</head>\n"
896                 + "<body>\n"
897                 + "</body></html>";
898 
899         loadPageVerifyTitle2(html);
900     }
901 
902     /**
903      * @throws Exception if the test fails
904      */
905     @Test
906     @Alerts({"functionfunc(){log(norm(func));}", "outer"})
907     public void secondFunctionWithSameNameStrict() throws Exception {
908         final String html = DOCTYPE_HTML
909                 + "<html><head>\n"
910                 + "<script>\n"
911                 + "  'use strict';\n"
912                 + LOG_TITLE_FUNCTION
913                 + "  function norm(foo) { return ('' + foo).replace(/(\\s)/gm,'') }\n"
914 
915                 + "  function func () { log('outer'); }\n"
916 
917                 + "  var x = function func() { log(norm(func)); }\n"
918 
919                 + "  x();\n"
920                 + "  func();\n"
921                 + "</script>\n"
922                 + "</head>\n"
923                 + "<body>\n"
924                 + "</body></html>";
925 
926         loadPageVerifyTitle2(html);
927     }
928 
929     /**
930      * @throws Exception if the test fails
931      */
932     @Test
933     @Alerts({"f1", "f2", "f3", "!f4", "f5", "!f6", "!f7", "!f8", "f10", "f11", "f12", "!f10", "f11", "f12", "f13"})
934     @HtmlUnitNYI(CHROME = {"f1", "f2", "f3", "!f4", "f5", "!f6", "!f7", "!f8",
935                            "f10", "f11", "f12", "f10", "f11", "f12", "f13"},
936             EDGE = {"f1", "f2", "f3", "!f4", "f5", "!f6", "!f7", "!f8",
937                     "f10", "f11", "f12", "f10", "f11", "f12", "f13"},
938             FF = {"f1", "f2", "f3", "!f4", "f5", "!f6", "!f7", "!f8", "f10", "f11", "f12", "f10", "f11", "f12", "f13"},
939             FF_ESR = {"f1", "f2", "f3", "!f4", "f5", "!f6", "!f7", "!f8",
940                       "f10", "f11", "f12", "f10", "f11", "f12", "f13"})
941     public void functioNamesExceptionsStrict() throws Exception {
942         final String html = DOCTYPE_HTML
943                 + "<html><head>\n"
944                 + "<script>\n"
945                 + "  'use strict';\n"
946                 + LOG_TITLE_FUNCTION
947 
948                 + "  function f1() {"
949                 + "    log('f1');"
950                 + "    function f9() { log('f9'); }"
951                 + "  }\n"
952 
953                 + "  var f2 = function () { log('f2'); }\n"
954                 + "  var f3 = function f4() { log('f3'); }\n"
955                 + "  var f5 = function f5() { log('f5'); }\n"
956 
957                 + "  !function f6() { log('f6'); };\n"
958                 + "  (function f7() { log('f7'); });\n"
959 
960                 + "  void function f8() { log('f8'); }\n"
961 
962                 + "  try { f1() } catch(e) { log('!f1'); }"
963                 + "  try { f2() } catch(e) { log('!f2'); }"
964                 + "  try { f3() } catch(e) { log('!f3'); }"
965                 + "  try { f4() } catch(e) { log('!f4'); }"
966                 + "  try { f5() } catch(e) { log('!f5'); }"
967                 + "  try { f6() } catch(e) { log('!f6'); }"
968                 + "  try { f7() } catch(e) { log('!f7'); }"
969                 + "  try { f8() } catch(e) { log('!f8'); }"
970 
971                 + "  {\n"
972                 + "    function f10() { log('f10'); }\n"
973                 + "    var f11 = function () { log('f11'); }\n"
974                 + "    var f12 = function f12() { log('f12'); }\n"
975                 + "    f10();\n"
976                 + "    f11();\n"
977                 + "    f12();\n"
978                 + "  }\n"
979 
980                 + "  try { f10() } catch(e) { log('!f10'); }"
981                 + "  try { f11() } catch(e) { log('!f11'); }"
982                 + "  try { f12() } catch(e) { log('!f12'); }"
983 
984                 + "  function f13() { log('f13') } + 1;"
985                 + "  try { f13() } catch(e) { log('!f13'); }"
986 
987                 + "</script>\n"
988                 + "</head>\n"
989                 + "<body>\n"
990                 + "</body></html>";
991 
992         loadPageVerifyTitle2(html);
993     }
994 
995     /**
996      * @throws Exception if the test fails
997      */
998     @Test
999     @Alerts("false")
1000     public void ctorBooleanDocumentAll() throws Exception {
1001         final String html = DOCTYPE_HTML
1002             + "<html><head>\n"
1003             + "<script>\n"
1004             + LOG_TITLE_FUNCTION
1005             + "function test() {\n"
1006             + "  log(Boolean(document.all))\n"
1007             + "}\n"
1008             + "</script></head>\n"
1009             + "<body onload='test()'>\n"
1010             + "</body></html>";
1011 
1012         loadPageVerifyTitle2(html);
1013     }
1014 
1015     /**
1016      * @throws Exception if the test fails
1017      */
1018     @Test
1019     @Alerts("false")
1020     public void falsyDocumentAll() throws Exception {
1021         final String html = DOCTYPE_HTML
1022             + "<html><head>\n"
1023             + "<script>\n"
1024             + LOG_TITLE_FUNCTION
1025             + "function test() {\n"
1026             + "  if (document.all) log('true'); else log('false');\n"
1027             + "}\n"
1028             + "</script></head>\n"
1029             + "<body onload='test()'>\n"
1030             + "</body></html>";
1031 
1032         loadPageVerifyTitle2(html);
1033     }
1034 
1035     /**
1036      * @throws Exception if the test fails
1037      */
1038     @Test
1039     @Alerts("[object HTMLAllCollection]")
1040     public void falsyAndDocumentAll() throws Exception {
1041         final String html = DOCTYPE_HTML
1042             + "<html><head>\n"
1043             + "<script>\n"
1044             + LOG_TITLE_FUNCTION
1045             + "function test() {\n"
1046             + "  var res = document.all && 'Html';\n"
1047             + "  log(res);\n"
1048             + "}\n"
1049             + "</script></head>\n"
1050             + "<body onload='test()'>\n"
1051             + "</body></html>";
1052 
1053         loadPageVerifyTitle2(html);
1054     }
1055 
1056     /**
1057      * @throws Exception if the test fails
1058      */
1059     @Test
1060     @Alerts("ReferenceError")
1061     public void javaNotAccessable() throws Exception {
1062         final String html = DOCTYPE_HTML
1063                 + "<html><head>\n"
1064                 + "<script>\n"
1065                 + LOG_TITLE_FUNCTION
1066                 + "function test() {\n"
1067                 + "  try {\n"
1068                 + "    log(java.lang.Math.PI);\n"
1069                 + "  } catch(e) { logEx(e); }\n"
1070                 + "}\n"
1071                 + "</script>\n"
1072                 + "</head>\n"
1073                 + "<body onload='test()'>\n"
1074                 + "</body></html>";
1075 
1076         loadPageVerifyTitle2(html);
1077     }
1078 
1079     /**
1080      * @throws Exception if the test fails
1081      */
1082     @Test
1083     @Alerts("Received: from worker - exception")
1084     public void javaNotAccessableFromWorker() throws Exception {
1085         final String html = DOCTYPE_HTML
1086             + "<html><body>\n"
1087             + "<script async>\n"
1088             + LOG_TITLE_FUNCTION
1089             + "try {\n"
1090             + "  var myWorker = new Worker('worker.js');\n"
1091             + "  myWorker.onmessage = function(e) {\n"
1092             + "    log('Received: ' + e.data);\n"
1093             + "  };\n"
1094             + "} catch(e) { logEx(e); }\n"
1095             + "</script></body></html>\n";
1096 
1097         final String workerJs = "var pi = 'from worker';\n"
1098                 + "try {\n"
1099                 + "  pi = pi + ' - ' + java.lang.Math.PI\n"
1100                 + "} catch(e) { pi = pi + ' - ' + 'exception'; }\n"
1101                 + "postMessage(pi);\n";
1102 
1103         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
1104 
1105         loadPage2(html);
1106         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
1107     }
1108 
1109     /**
1110      * @throws Exception if the test fails
1111      */
1112     @Test
1113     @Alerts({"#0", "#1", "2"})
1114     public void constInLoop() throws Exception {
1115         final String html = DOCTYPE_HTML
1116                 + "<html><head>\n"
1117                 + "<script>\n"
1118                 + LOG_TITLE_FUNCTION
1119                 + "function test() {\n"
1120                 + "  var i;\n"
1121                 + "  for (i = 0; i < 2; i++) {\n"
1122                 + "    const x = '#' + i;\n"
1123                 + "    log(x);\n"
1124                 + "  }\n"
1125                 + "  log(i);\n"
1126                 + "}\n"
1127                 + "</script>\n"
1128                 + "</head>\n"
1129                 + "<body onload='test()'>\n"
1130                 + "</body></html>";
1131 
1132         loadPageVerifyTitle2(html);
1133     }
1134 
1135     /**
1136      * @throws Exception if the test fails
1137      */
1138     @Test
1139     @Alerts({"1", "2"})
1140     public void constInOfLoop() throws Exception {
1141         final String html = DOCTYPE_HTML
1142                 + "<html><head>\n"
1143                 + "<script>\n"
1144                 + LOG_TITLE_FUNCTION
1145                 + "function test() {\n"
1146                 + "  var arr = [1, 2];\n"
1147                 + "  for(const elem of arr) {\n"
1148                 + "    log(elem);\n"
1149                 + "  }\n"
1150                 + "}\n"
1151                 + "</script>\n"
1152                 + "</head>\n"
1153                 + "<body onload='test()'>\n"
1154                 + "</body></html>";
1155 
1156         loadPageVerifyTitle2(html);
1157     }
1158 
1159     /**
1160      * @throws Exception if the test fails
1161      */
1162     @Test
1163     @Alerts("seven")
1164     public void constInIfElse() throws Exception {
1165         final String html = DOCTYPE_HTML
1166                 + "<html><head>\n"
1167                 + "<script>\n"
1168                 + LOG_TITLE_FUNCTION
1169                 + "function test() {\n"
1170                 + "  let abcd = '1234';"
1171                 + "  if('abcd' === abcd) {\n"
1172                 + "    const constant = 7;\n"
1173                 + "    log(constant);\n"
1174                 + "  } else {\n"
1175                 + "    const constant = 'seven';\n"
1176                 + "    log(constant);\n"
1177                 + "  }\n"
1178                 + "}\n"
1179                 + "</script>\n"
1180                 + "</head>\n"
1181                 + "<body onload='test()'>\n"
1182                 + "</body></html>";
1183 
1184         loadPageVerifyTitle2(html);
1185     }
1186 
1187     /**
1188      * @throws Exception if the test fails
1189      */
1190     @Test
1191     @Alerts({"1 ready", "2 ready", "3 ready", "4 ready",
1192         "5 ready", "6 ready", "7 ready", "8 ready", "9 ready", "10 ready"})
1193     public void ensureOrder() throws Exception {
1194         final String html = DOCTYPE_HTML
1195             + "<html><body>"
1196             + "<script>\n"
1197             + LOG_TITLE_FUNCTION
1198             + "  function timeoutFunction(nr) {\n"
1199             + "    return function () {\n"
1200             + "      log(nr + ' ready');\n"
1201             + "    }\n"
1202             + "  }\n"
1203 
1204             + "  for (let i = 1; i <= 10; i++) {\n"
1205             + "    setTimeout(timeoutFunction(i));\n"
1206             + "  }\n"
1207             + "</script></body></html>";
1208 
1209         final WebDriver driver = loadPage2(html);
1210         Thread.sleep(DEFAULT_WAIT_TIME.toMillis());
1211         verifyTitle2(driver, getExpectedAlerts());
1212     }
1213 
1214     /**
1215      * @throws Exception if the test fails
1216      */
1217     @Test
1218     @Alerts({"false", "aa", "0", "aabbc", "false", "bb", "2", "aabbc", "true", "undefined"})
1219     public void matchAll() throws Exception {
1220         final String html = DOCTYPE_HTML
1221             + "<html><body>"
1222             + "<script>\n"
1223             + LOG_TITLE_FUNCTION
1224             + "const s = 'aabbc';\n"
1225             + "const re = /([a-z])\\1/g;\n"
1226             + "const matches = s.matchAll(re);\n"
1227 
1228             + "var match = matches.next();\n"
1229             + "log(match.done);\n"
1230             + "log(match.value[0]);\n"
1231             + "log(match.value.index);\n"
1232             + "log(match.value.input);\n"
1233 
1234             + "match = matches.next();\n"
1235             + "log(match.done);\n"
1236             + "log(match.value[0]);\n"
1237             + "log(match.value.index);\n"
1238             + "log(match.value.input);\n"
1239 
1240             + "match = matches.next();\n"
1241             + "log(match.done);\n"
1242             + "log(match.value);\n"
1243             + "</script></body></html>";
1244 
1245         loadPageVerifyTitle2(html);
1246     }
1247 
1248     /**
1249      * Make sure we use the TopScope, otherwise some GeneratorFunction stuff
1250      * does not work.
1251      * @throws Exception if the test fails
1252      */
1253     @Test
1254     @Alerts({"anonymous", "false", "false", "true"})
1255     @HtmlUnitNYI(CHROME = "org.htmlunit.ScriptException: TypeError: Cannot read property \"constructor\" from null",
1256             EDGE = "org.htmlunit.ScriptException: TypeError: Cannot read property \"constructor\" from null",
1257             FF = "org.htmlunit.ScriptException: TypeError: Cannot read property \"constructor\" from null",
1258             FF_ESR = "org.htmlunit.ScriptException: TypeError: Cannot read property \"constructor\" from null")
1259     public void generatorFunction() throws Exception {
1260         final String html = DOCTYPE_HTML
1261             + "<html><body>"
1262             + "<script>\n"
1263             + LOG_TITLE_FUNCTION
1264             + "var GeneratorFunction = Object.getPrototypeOf(function*() {}).constructor;\n"
1265 
1266             + "log(GeneratorFunction().name);\n"
1267             + "log(Object.getOwnPropertyDescriptor(GeneratorFunction(), 'name').enumerable);\n"
1268             + "log(Object.getOwnPropertyDescriptor(GeneratorFunction(), 'name').writable);\n"
1269             + "log(Object.getOwnPropertyDescriptor(GeneratorFunction(), 'name').configurable);\n"
1270             + "</script></body></html>";
1271 
1272         try {
1273             loadPageVerifyTitle2(html);
1274         }
1275         catch (final WebDriverException e) {
1276             assertTrue(e.getMessage(), e.getMessage().startsWith(getExpectedAlerts()[0]));
1277         }
1278     }
1279 
1280 }