From: <rb...@us...> - 2017-12-21 07:59:06
|
Revision: 15029 http://sourceforge.net/p/htmlunit/code/15029 Author: rbri Date: 2017-12-21 07:59:03 +0000 (Thu, 21 Dec 2017) Log Message: ----------- make our test suite working again and som cleanup (wip) Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebTestCase.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/event/Event2Test.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java 2017-12-20 20:23:05 UTC (rev 15028) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java 2017-12-21 07:59:03 UTC (rev 15029) @@ -178,12 +178,17 @@ requestCount_++; requestedUrls_.add(url); - RawResponseData rawResponse = responseMap_.get(url.toExternalForm()); + String urlString = url.toExternalForm(); + final int queryStart = urlString.lastIndexOf('?'); + if (queryStart > -1) { + urlString = urlString.substring(0, queryStart); + } + RawResponseData rawResponse = responseMap_.get(urlString); if (rawResponse == null) { rawResponse = defaultResponse_; if (rawResponse == null) { throw new IllegalStateException("No response specified that can handle URL [" - + url.toExternalForm() + + urlString + "]"); } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebTestCase.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebTestCase.java 2017-12-20 20:23:05 UTC (rev 15028) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebTestCase.java 2017-12-21 07:59:03 UTC (rev 15029) @@ -693,14 +693,6 @@ } /** - * Sets the mock WebConnection instance for the current test. - * @param connection the connection to use - */ - protected void setMockWebConnection(final MockWebConnection connection) { - mockWebConnection_ = connection; - } - - /** * Cleanup after a test. */ @After Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java 2017-12-20 20:23:05 UTC (rev 15028) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java 2017-12-21 07:59:03 UTC (rev 15029) @@ -872,7 +872,7 @@ assertEquals(2, getMockWebConnection().getRequestCount()); assertEquals(HttpMethod.GET, getMockWebConnection().getLastWebRequest().getHttpMethod()); - assertEquals(URL_FIRST + "a.html", getMockWebConnection().getLastWebRequest().getUrl()); + assertEquals(URL_FIRST + "a.html?p1=sieben&p2", getMockWebConnection().getLastWebRequest().getUrl()); final List<NameValuePair> params = getMockWebConnection().getLastWebRequest().getRequestParameters(); assertEquals(2, params.size()); @@ -920,7 +920,7 @@ assertEquals(3, getMockWebConnection().getRequestCount()); assertEquals(HttpMethod.POST, getMockWebConnection().getLastWebRequest().getHttpMethod()); - assertEquals(URL_SECOND + "a.html", getMockWebConnection().getLastWebRequest().getUrl()); + assertEquals(URL_SECOND + "a.html?urlParam=urlVal", getMockWebConnection().getLastWebRequest().getUrl()); final List<NameValuePair> params = getMockWebConnection().getLastWebRequest().getRequestParameters(); assertEquals(4, params.size()); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/event/Event2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/event/Event2Test.java 2017-12-20 20:23:05 UTC (rev 15028) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/event/Event2Test.java 2017-12-21 07:59:03 UTC (rev 15029) @@ -166,7 +166,7 @@ @Test @Alerts("") public void submitClick() throws Exception { - final String firstSnippet = " <input type='submit' name='clickMe' id='clickMe' size='2'\n"; + final String firstSnippet = " <input type='submit' name='clickMe' id='clickMe'\n"; final String secondSnippet = ">\n"; testClickEvents(firstSnippet, secondSnippet); @@ -180,7 +180,7 @@ @Alerts(DEFAULT = "[object MouseEvent] click b:true c:true [clickMe] [1]", IE = "[object PointerEvent] click b:true c:true [clickMe] [1]") public void resetClick() throws Exception { - final String firstSnippet = " <input type='reset' name='clickMe' id='clickMe' size='2'\n"; + final String firstSnippet = " <input type='reset' name='clickMe' id='clickMe'\n"; final String secondSnippet = ">\n"; testClickEvents(firstSnippet, secondSnippet); @@ -194,7 +194,7 @@ @Alerts(DEFAULT = "[object MouseEvent] click b:true c:true [clickMe] [1]", IE = "[object PointerEvent] click b:true c:true [clickMe] [1]") public void buttonClick() throws Exception { - final String firstSnippet = " <input type='button' name='clickMe' id='clickMe' size='2'\n"; + final String firstSnippet = " <input type='button' name='clickMe' id='clickMe'\n"; final String secondSnippet = ">\n"; testClickEvents(firstSnippet, secondSnippet); @@ -208,7 +208,7 @@ @Alerts(DEFAULT = "[object MouseEvent] click b:true c:true [clickMe] [1]", IE = "[object PointerEvent] click b:true c:true [clickMe] [1]") public void anchorClick() throws Exception { - final String firstSnippet = " <a href='#' name='clickMe' id='clickMe' size='2'\n"; + final String firstSnippet = " <a href='#' name='clickMe' id='clickMe'\n"; final String secondSnippet = ">anchor</a>\n"; testClickEvents(firstSnippet, secondSnippet); |
From: <rb...@us...> - 2017-12-21 13:04:22
|
Revision: 15030 http://sourceforge.net/p/htmlunit/code/15030 Author: rbri Date: 2017-12-21 13:04:19 +0000 (Thu, 21 Dec 2017) Log Message: ----------- make our test suite working again and some cleanup (wip) Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlForm2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/LocationTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java 2017-12-21 07:59:03 UTC (rev 15029) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/MockWebConnection.java 2017-12-21 13:04:19 UTC (rev 15030) @@ -38,6 +38,7 @@ * @author Marc Guillemot * @author Brad Clarke * @author Ahmed Ashour + * @author Ronald Brill */ public class MockWebConnection implements WebConnection { @@ -179,17 +180,23 @@ requestedUrls_.add(url); String urlString = url.toExternalForm(); - final int queryStart = urlString.lastIndexOf('?'); - if (queryStart > -1) { - urlString = urlString.substring(0, queryStart); - } RawResponseData rawResponse = responseMap_.get(urlString); if (rawResponse == null) { - rawResponse = defaultResponse_; + // try to find without query params + final int queryStart = urlString.lastIndexOf('?'); + if (queryStart > -1) { + urlString = urlString.substring(0, queryStart); + rawResponse = responseMap_.get(urlString); + } + + // fall back to default if (rawResponse == null) { - throw new IllegalStateException("No response specified that can handle URL [" - + urlString - + "]"); + rawResponse = defaultResponse_; + if (rawResponse == null) { + throw new IllegalStateException("No response specified that can handle URL [" + + urlString + + "]"); + } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlForm2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlForm2Test.java 2017-12-21 07:59:03 UTC (rev 15029) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlForm2Test.java 2017-12-21 13:04:19 UTC (rev 15030) @@ -49,6 +49,7 @@ import com.gargoylesoftware.htmlunit.MockWebConnection; import com.gargoylesoftware.htmlunit.WebDriverTestCase; import com.gargoylesoftware.htmlunit.util.NameValuePair; +import com.gargoylesoftware.htmlunit.util.UrlUtils; /** * Tests for {@link HtmlForm}, with BrowserRunner. @@ -669,7 +670,8 @@ driver.findElement(By.id("myButton")).click(); assertEquals(2, getMockWebConnection().getRequestCount()); - assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl()); + assertEquals(URL_SECOND.toString(), + UrlUtils.getUrlWithNewQuery(getMockWebConnection().getLastWebRequest().getUrl(), null)); assertEquals(getExpectedAlerts()[0], getMockWebConnection().getLastWebRequest().getHttpMethod().name()); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/LocationTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/LocationTest.java 2017-12-21 07:59:03 UTC (rev 15029) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/LocationTest.java 2017-12-21 13:04:19 UTC (rev 15030) @@ -202,8 +202,6 @@ */ @Test public void setPathname() throws Exception { - final WebClient webClient = getWebClient(); - final MockWebConnection webConnection = new MockWebConnection(); final URL url = new URL("http://abc.com/index.html?blah=bleh"); final URL url2 = new URL("http://abc.com/en/index.html?blah=bleh"); final String html @@ -210,11 +208,11 @@ = "<html><head><title>Test 1</title></head>\n" + "<body onload='location.pathname=\"/en/index.html\"'>...</body></html>"; final String html2 = "<html><head><title>Test 2</title></head><body>...</body></html>"; - webConnection.setResponse(url, html); - webConnection.setResponse(url2, html2); - webClient.setWebConnection(webConnection); - final HtmlPage page = webClient.getPage(url); + getMockWebConnection().setResponse(url, html); + getMockWebConnection().setResponse(url2, html2); + + final HtmlPage page = getWebClientWithMockWebConnection().getPage(url); assertEquals("Test 2", page.getTitleText()); assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm()); } @@ -246,8 +244,6 @@ */ @Test public void setProtocol() throws Exception { - final WebClient webClient = getWebClient(); - final MockWebConnection webConnection = new MockWebConnection(); final URL url = new URL("http://abc.com/index.html?blah=bleh"); final URL url2 = new URL("ftp://abc.com/index.html?blah=bleh"); final String html @@ -254,11 +250,11 @@ = "<html><head><title>Test 1</title></head>\n" + "<body onload='location.protocol=\"ftp\"'>...</body></html>"; final String html2 = "<html><head><title>Test 2</title></head><body>...</body></html>"; - webConnection.setResponse(url, html); - webConnection.setResponse(url2, html2); - webClient.setWebConnection(webConnection); - final HtmlPage page = webClient.getPage(url); + getMockWebConnection().setResponse(url, html); + getMockWebConnection().setResponse(url2, html2); + + final HtmlPage page = getWebClientWithMockWebConnection().getPage(url); assertEquals("Test 2", page.getTitleText()); assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm()); } |
From: <rb...@us...> - 2017-12-22 14:21:38
|
Revision: 15033 http://sourceforge.net/p/htmlunit/code/15033 Author: rbri Date: 2017-12-22 14:21:35 +0000 (Fri, 22 Dec 2017) Log Message: ----------- click from javascript works also for hidden elements Issue 1939 Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2017-12-21 18:22:46 UTC (rev 15032) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2017-12-22 14:21:35 UTC (rev 15033) @@ -1358,7 +1358,8 @@ */ @JsxFunction public void click() throws IOException { - getDomNodeOrDie().click(); + // when triggered from js the visibility is ignored + getDomNodeOrDie().click(false, false, false, true, true, false); } /** Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java 2017-12-21 18:22:46 UTC (rev 15032) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java 2017-12-22 14:21:35 UTC (rev 15033) @@ -666,4 +666,39 @@ + "</html>"; loadPageWithAlerts2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"myImage clicked", "myImageDisplayNone clicked"}) + public void click() throws Exception { + try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) { + final byte[] directBytes = IOUtils.toByteArray(is); + final URL urlImage = new URL(URL_FIRST, "img.jpg"); + final List<NameValuePair> emptyList = Collections.emptyList(); + getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", emptyList); + } + + final String html = "<html><head>\n" + + "<script>\n" + + " function test() {\n" + + " var img = document.getElementById('myImage');\n" + + " img.click();\n" + + " img = document.getElementById('myImageDisplayNone');\n" + + " img.click();\n" + + " }\n" + + "</script>\n" + + "</head><body onload='test()'>\n" + + " <img id='myImage' src='\" + URL_SECOND + \"img.jpg' onclick='alert(\"myImage clicked\");'>\n" + + " <img id='myImageDisplayNone' src='\" + URL_SECOND + \"img.jpg' style='display: none'" + + " onclick='alert(\"myImageDisplayNone clicked\");'>\n" + + "</body></html>"; + + final WebDriver driver = getWebDriver(); + if (driver instanceof HtmlUnitDriver) { + ((HtmlUnitDriver) driver).setDownloadImages(true); + } + loadPageWithAlerts2(html); + } } |
From: <rb...@us...> - 2017-12-22 15:44:27
|
Revision: 15034 http://sourceforge.net/p/htmlunit/code/15034 Author: rbri Date: 2017-12-22 15:44:24 +0000 (Fri, 22 Dec 2017) Log Message: ----------- more tests, ignore areas with invalid rect definitions Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLAreaElementTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java 2017-12-22 14:21:35 UTC (rev 15033) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java 2017-12-22 15:44:24 UTC (rev 15034) @@ -26,6 +26,8 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import com.gargoylesoftware.htmlunit.HttpHeader; import com.gargoylesoftware.htmlunit.SgmlPage; @@ -46,6 +48,7 @@ * @author Frank Danek */ public class HtmlArea extends HtmlElement { + private static final Log LOG = LogFactory.getLog(HtmlArea.class); /** The HTML tag represented by this element. */ public static final String TAG_NAME = "area"; @@ -265,21 +268,28 @@ final String[] coords = StringUtils.split(getCoordsAttribute(), ','); double leftX = 0; - if (coords.length > 0) { - leftX = Double.parseDouble(coords[0].trim()); - } double topY = 0; - if (coords.length > 1) { - topY = Double.parseDouble(coords[1].trim()); - } double rightX = 0; - if (coords.length > 2) { - rightX = Double.parseDouble(coords[2].trim()); - } double bottomY = 0; - if (coords.length > 3) { - bottomY = Double.parseDouble(coords[3].trim()); + + try { + if (coords.length > 0) { + leftX = Double.parseDouble(coords[0].trim()); + } + if (coords.length > 1) { + topY = Double.parseDouble(coords[1].trim()); + } + if (coords.length > 2) { + rightX = Double.parseDouble(coords[2].trim()); + } + if (coords.length > 3) { + bottomY = Double.parseDouble(coords[3].trim()); + } } + catch (final NumberFormatException e) { + LOG.warn("Invalid rect coords '" + coords + "'", e); + } + final Rectangle2D rectangle = new Rectangle2D.Double(leftX, topY, rightX - leftX, bottomY - topY); return rectangle; Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLAreaElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLAreaElementTest.java 2017-12-22 14:21:35 UTC (rev 15033) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLAreaElementTest.java 2017-12-22 15:44:24 UTC (rev 15034) @@ -137,4 +137,31 @@ loadPageWithAlerts2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"myImage clicked", "myImageDisplayNone clicked"}) + public void click() throws Exception { + final String html = "<html><head>\n" + + "<script>\n" + + " function test() {\n" + + " document.getElementById('a1').click();\n" + + " document.getElementById('a2').click();\n" + + " }\n" + + "</script>\n" + + "</head>\n" + + "<body onload='test()'>\n" + + " <img usemap='#dot'" + + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA" + + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n" + + " <map name='dot'>\n" + + " <area id='a1' shape='rect' coords='0,0,1,1' onclick='alert(\"a1 clicked\");'/>\n" + + " <area id='a2' shape='rect' coords='0 0 2 2' onclick='alert(\"a2 clicked\");'/>\n" + + " <map>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java 2017-12-22 14:21:35 UTC (rev 15033) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLImageElementTest.java 2017-12-22 15:44:24 UTC (rev 15034) @@ -16,6 +16,7 @@ import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.FF; import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.FF52; +import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.IE; import java.io.File; import java.io.FileInputStream; @@ -671,34 +672,52 @@ * @throws Exception if the test fails */ @Test - @Alerts({"myImage clicked", "myImageDisplayNone clicked"}) + @Alerts({"myImage clicked", "myImageNone clicked"}) public void click() throws Exception { - try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) { - final byte[] directBytes = IOUtils.toByteArray(is); - final URL urlImage = new URL(URL_FIRST, "img.jpg"); - final List<NameValuePair> emptyList = Collections.emptyList(); - getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", emptyList); - } - final String html = "<html><head>\n" + "<script>\n" + " function test() {\n" - + " var img = document.getElementById('myImage');\n" - + " img.click();\n" - + " img = document.getElementById('myImageDisplayNone');\n" - + " img.click();\n" + + " document.getElementById('myImage').click();\n" + + " document.getElementById('myImageNone').click();\n" + " }\n" + "</script>\n" + "</head><body onload='test()'>\n" - + " <img id='myImage' src='\" + URL_SECOND + \"img.jpg' onclick='alert(\"myImage clicked\");'>\n" - + " <img id='myImageDisplayNone' src='\" + URL_SECOND + \"img.jpg' style='display: none'" - + " onclick='alert(\"myImageDisplayNone clicked\");'>\n" + + " <img id='myImage' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA" + + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='" + + " onclick='alert(\"myImage clicked\");'>\n" + + " <img id='myImageNone' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA" + + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='" + + " style='display: none' onclick='alert(\"myImageNone clicked\");'>\n" + "</body></html>"; - final WebDriver driver = getWebDriver(); - if (driver instanceof HtmlUnitDriver) { - ((HtmlUnitDriver) driver).setDownloadImages(true); - } loadPageWithAlerts2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "myImageWithMap clicked", + IE = "a0 clicked") + @NotYetImplemented(IE) + public void clickWithMap() throws Exception { + final String html = "<html><head>\n" + + "<script>\n" + + " function test() {\n" + + " document.getElementById('myImageWithMap').click();\n" + + " }\n" + + "</script>\n" + + "</head><body onload='test()'>\n" + + " <img id='myImageWithMap' usemap='#dot'" + + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA" + + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='" + + " onclick='alert(\"myImageWithMap clicked\");'>\n" + + " <map name='dot'>\n" + + " <area id='a0' shape='rect' coords='0 0 7 7' onclick='alert(\"a0 clicked\");'/>\n" + + " <area id='a1' shape='rect' coords='0,0,1,1' onclick='alert(\"a1 clicked\");'/>\n" + + " <map>\n" + + "</body></html>"; + + loadPageWithAlerts2(html, 70000000); + } } |
From: <rb...@us...> - 2017-12-22 16:44:34
|
Revision: 15035 http://sourceforge.net/p/htmlunit/code/15035 Author: rbri Date: 2017-12-22 16:44:32 +0000 (Fri, 22 Dec 2017) Log Message: ----------- ignore areas with invalid poly definitions Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2017-12-22 15:44:24 UTC (rev 15034) +++ trunk/htmlunit/src/changes/changes.xml 2017-12-22 16:44:32 UTC (rev 15035) @@ -8,6 +8,12 @@ <body> <release version="2.29" date="xx, 2017" description="Bugfixes, Chrome 63, WebStart support"> + <action type="fix" dev="rbri" issue="1939 "> + If the coords of an image map entry are not valid ignore this entry. + </action> + <action type="fix" dev="rbri" issue="1939 "> + JavaScript: calling click() from js should always work even if the control is not visible. + </action> <action type="add" dev="rbri" issue="1936"> JavaScript: Crypto.subtle added </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java 2017-12-22 15:44:24 UTC (rev 15034) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java 2017-12-22 16:44:32 UTC (rev 15035) @@ -317,14 +317,21 @@ private GeneralPath parsePoly() { final String[] coords = StringUtils.split(getCoordsAttribute(), ','); final GeneralPath path = new GeneralPath(); - for (int i = 0; i + 1 < coords.length; i += 2) { - if (i == 0) { - path.moveTo(Float.parseFloat(coords[i]), Float.parseFloat(coords[i + 1])); + + try { + for (int i = 0; i + 1 < coords.length; i += 2) { + if (i == 0) { + path.moveTo(Float.parseFloat(coords[i]), Float.parseFloat(coords[i + 1])); + } + else { + path.lineTo(Float.parseFloat(coords[i]), Float.parseFloat(coords[i + 1])); + } } - else { - path.lineTo(Float.parseFloat(coords[i]), Float.parseFloat(coords[i + 1])); - } } + catch (final NumberFormatException e) { + LOG.warn("Invalid poly coords '" + coords + "'", e); + } + path.closePath(); return path; } |
From: <rb...@us...> - 2017-12-23 14:35:34
|
Revision: 15038 http://sourceforge.net/p/htmlunit/code/15038 Author: rbri Date: 2017-12-23 14:35:32 +0000 (Sat, 23 Dec 2017) Log Message: ----------- fix: NPE thrown if JS "location.href = 'xyz'" called inside Promise.then() Issue 1941 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Promise.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/PromiseTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2017-12-22 17:42:23 UTC (rev 15037) +++ trunk/htmlunit/src/changes/changes.xml 2017-12-23 14:35:32 UTC (rev 15038) @@ -8,6 +8,10 @@ <body> <release version="2.29" date="xx, 2017" description="Bugfixes, Chrome 63, WebStart support"> + <action type="fix" dev="rbri" issue="1941 "> + JavaScript: Promise has to provide the same context setup as the rest + and call processPostponedActions afterwards + </action> <action type="fix" dev="rbri" issue="1939 "> If the coords of an image map entry are not valid ignore this entry. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Promise.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Promise.java 2017-12-22 17:42:23 UTC (rev 15037) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Promise.java 2017-12-23 14:35:32 UTC (rev 15038) @@ -14,6 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host; +import static com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.KEY_STARTING_SCOPE; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.EDGE; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF; @@ -20,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Stack; import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; import com.gargoylesoftware.htmlunit.javascript.background.BasicJavaScriptJob; @@ -110,8 +112,24 @@ } }; + final Context cx = Context.getCurrentContext(); try { - fun.call(Context.getCurrentContext(), window, window, new Object[] {resolve, reject}); + // KEY_STARTING_SCOPE maintains a stack of scopes + @SuppressWarnings("unchecked") + Stack<Scriptable> stack = (Stack<Scriptable>) cx.getThreadLocal(KEY_STARTING_SCOPE); + if (null == stack) { + stack = new Stack<>(); + cx.putThreadLocal(KEY_STARTING_SCOPE, stack); + } + stack.push(window); + try { + fun.call(cx, window, window, new Object[] {resolve, reject}); + } + finally { + stack.pop(); + } + + window.getWebWindow().getWebClient().getJavaScriptEngine().processPostponedActions(); } catch (final JavaScriptException e) { thisPromise.settle(false, e.getValue(), window); @@ -331,7 +349,7 @@ @Override public void run() { - Context.enter(); + final Context cx = Context.enter(); try { Function toExecute = null; if (thisPromise.state_ == PromiseState.FULFILLED && onFulfilled instanceof Function) { @@ -350,8 +368,22 @@ callbackResult = dummy; } else { - callbackResult = toExecute.call(Context.getCurrentContext(), - window, thisPromise, new Object[] {value_}); + // KEY_STARTING_SCOPE maintains a stack of scopes + @SuppressWarnings("unchecked") + Stack<Scriptable> stack = (Stack<Scriptable>) cx.getThreadLocal(KEY_STARTING_SCOPE); + if (null == stack) { + stack = new Stack<>(); + cx.putThreadLocal(KEY_STARTING_SCOPE, stack); + } + stack.push(window); + try { + callbackResult = toExecute.call(cx, window, thisPromise, new Object[] {value_}); + } + finally { + stack.pop(); + } + + window.getWebWindow().getWebClient().getJavaScriptEngine().processPostponedActions(); } if (callbackResult instanceof Promise) { final Promise resultPromise = (Promise) callbackResult; Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java 2017-12-22 17:42:23 UTC (rev 15037) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Location2Test.java 2017-12-23 14:35:32 UTC (rev 15038) @@ -795,36 +795,39 @@ final String html = "<html><head><title>Frameset</title></head>\n" + "<frameset rows='20%,80%'>\n" + " <frame src='menu.html' name='menu'>\n" - + " <frame src='' name='content'>\n" + + " <frame src='content.html' name='content'>\n" + "</frameset></html>"; final String menu = "<html><head><title>Menu</title></head>\n" + "<body>\n" - + " <a id='link' href='content.html' target='content'>Link</a>\n" - + " <a id='jsLink' href='#' onclick=\"javascript:top.content.location='content.html';\">jsLink</a>\n" + + " <a id='link' href='newContent.html' target='content'>Link</a>\n" + + " <a id='jsLink' href='#' " + + "onclick=\"javascript:top.content.location='newContent.html';\">jsLink</a>\n" + "</body></html>"; final String content = "<html><head><title>Content</title></head><body><p>content</p></body></html>"; + final String newContent = "<html><head><title>New Content</title></head><body><p>new content</p></body></html>"; final MockWebConnection conn = getMockWebConnection(); conn.setResponse(new URL(URL_FIRST, "menu.html"), menu); conn.setResponse(new URL(URL_FIRST, "content.html"), content); + conn.setResponse(new URL(URL_FIRST, "newContent.html"), newContent); expandExpectedAlertsVariables(URL_FIRST); final WebDriver driver = loadPage2(html); - assertEquals(2, conn.getRequestCount()); + assertEquals(3, conn.getRequestCount()); // click an anchor with href and target driver.switchTo().frame(0); driver.findElement(By.id("link")).click(); - assertEquals(3, conn.getRequestCount()); + assertEquals(4, conn.getRequestCount()); Map<String, String> lastAdditionalHeaders = conn.getLastAdditionalHeaders(); assertEquals(getExpectedAlerts()[0], lastAdditionalHeaders.get(HttpHeader.REFERER)); // click an anchor with onclick which sets frame.location driver.findElement(By.id("jsLink")).click(); - assertEquals(4, conn.getRequestCount()); + assertEquals(5, conn.getRequestCount()); lastAdditionalHeaders = conn.getLastAdditionalHeaders(); assertEquals(getExpectedAlerts()[0], lastAdditionalHeaders.get(HttpHeader.REFERER)); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/PromiseTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/PromiseTest.java 2017-12-22 17:42:23 UTC (rev 15037) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/PromiseTest.java 2017-12-23 14:35:32 UTC (rev 15038) @@ -1600,4 +1600,35 @@ final String text = driver.findElement(By.id("log")).getAttribute("value").trim().replaceAll("\r", ""); assertEquals(String.join("\n", getExpectedAlerts()), text); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "", + IE = "test") + public void changeLocationFromPromise() throws Exception { + final String html = + "<html>\n" + + "<head>\n" + + " <title>test</title>\n" + + " <script>\n" + + " function test() {\n" + + " if (window.Promise) {\n" + + " Promise.resolve(1).then(function () {\n" + + " location.href = 'about:blank';\n" + + " });\n" + + " }\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='test()'>\n" + + " <textarea id='log' cols='80' rows='40'></textarea>\n" + + "</body>\n" + + "</html>"; + + final WebDriver driver = loadPage2(html); + Thread.sleep(200); + assertEquals(getExpectedAlerts()[0], driver.getTitle()); + } } |
From: <rb...@us...> - 2017-12-24 15:46:47
|
Revision: 15041 http://sourceforge.net/p/htmlunit/code/15041 Author: rbri Date: 2017-12-24 15:46:44 +0000 (Sun, 24 Dec 2017) Log Message: ----------- fix build Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Element.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/dom/MutationObserverTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Element.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Element.java 2017-12-24 15:02:46 UTC (rev 15040) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Element.java 2017-12-24 15:46:44 UTC (rev 15041) @@ -1216,7 +1216,9 @@ * @param style the style of the element */ protected void setStyle(final String style) { - getStyle().setCssText(style); + if (!getBrowserVersion().hasFeature(JS_ELEMENT_GET_ATTRIBUTE_RETURNS_EMPTY)) { + getStyle().setCssText(style); + } } /** Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java 2017-12-24 15:02:46 UTC (rev 15040) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java 2017-12-24 15:46:44 UTC (rev 15041) @@ -1785,10 +1785,11 @@ + "<script>\n" + " function test() {\n" + " var div1 = document.getElementById('div1');\n" + + " var empty = getOffsetHeight('width: 300px; height: 300px;');\n" + " var marginAndPadding = getOffsetHeight('width: 300px; height: 300px; margin: 3px; padding: 5px;');\n" + " var withBorderBox = getOffsetHeight('width: 300px; height: 300px; margin: 3px; padding: 5px;" - + " box-sizing: border-box;');\n" + + " box-sizing: border-box;');\n" + " alert(marginAndPadding - empty);\n" + " alert(withBorderBox - empty);\n" + " }\n" Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/dom/MutationObserverTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/dom/MutationObserverTest.java 2017-12-24 15:02:46 UTC (rev 15040) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/dom/MutationObserverTest.java 2017-12-24 15:46:44 UTC (rev 15041) @@ -21,12 +21,10 @@ import org.junit.runner.RunWith; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; -import org.openqa.selenium.htmlunit.HtmlUnitDriver; import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; import com.gargoylesoftware.htmlunit.WebDriverTestCase; -import com.gargoylesoftware.htmlunit.html.HtmlElement; /** * Tests for {@link MutationObserver}. @@ -359,15 +357,6 @@ final WebDriver driver = loadPage2(html); driver.findElement(By.id("id1")).click(); verifyAlerts(driver, getExpectedAlerts()); - - if (driver instanceof HtmlUnitDriver) { - driver.get(URL_FIRST.toExternalForm()); - final HtmlElement element = toHtmlElement(driver.findElement(By.id("headline"))); - element.setAttribute("style", "color: red"); - - element.getHtmlPageOrNull().getWebClient().getJavaScriptEngine().processPostponedActions(); - verifyAlerts(driver, getExpectedAlerts()); - } } /** @@ -402,7 +391,7 @@ + "<body onload='test()'>\n" + " <div id='myDiv' style='color: green'>old</div>\n" + "</body></html>"; - loadPageWithAlerts2(html, 700000); + loadPageWithAlerts2(html); } /** |
From: <rb...@us...> - 2017-12-27 16:53:38
|
Revision: 15043 http://sourceforge.net/p/htmlunit/code/15043 Author: rbri Date: 2017-12-27 16:53:36 +0000 (Wed, 27 Dec 2017) Log Message: ----------- TextEncoder/TextDecoder impl added Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoder.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoder.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/arrays/Uint8Array.java Added Paths: ----------- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoderTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoderTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2017-12-26 10:49:19 UTC (rev 15042) +++ trunk/htmlunit/src/changes/changes.xml 2017-12-27 16:53:36 UTC (rev 15043) @@ -8,6 +8,9 @@ <body> <release version="2.29" date="xx, 2017" description="Bugfixes, Chrome 63, WebStart support"> + <action type="add" dev="rbri"> + JavaScript: TextEncoder/TextDecoder impl added. + </action> <action type="fix" dev="rbri" issue="1940" due-to="Atsushi Nakagawa"> JavaScript: MutationObserver fires callbacks asynchronously </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoder.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoder.java 2017-12-26 10:49:19 UTC (rev 15042) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoder.java 2017-12-27 16:53:36 UTC (rev 15043) @@ -17,22 +17,391 @@ import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; + import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor; +import com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction; +import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter; +import com.gargoylesoftware.htmlunit.javascript.host.arrays.ArrayBuffer; +import com.gargoylesoftware.htmlunit.javascript.host.arrays.ArrayBufferView; +import net.sourceforge.htmlunit.corejs.javascript.Context; +import net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime; +import net.sourceforge.htmlunit.corejs.javascript.Undefined; + /** * A JavaScript object for {@code TextDecoder}. * * @author Ahmed Ashour + * @author Ronald Brill */ @JsxClass({CHROME, FF}) public class TextDecoder extends SimpleScriptable { + private static java.util.Map<String, Charset> ENCODINGS_; + private static java.util.Map<String, String> ENCODING_NAMES_; + private Charset encoding_ = StandardCharsets.UTF_8; + static { + ENCODINGS_ = new HashMap<>(); + ENCODING_NAMES_ = new HashMap<>(); + + Charset charset = StandardCharsets.UTF_8; + ENCODINGS_.put("utf-8", charset); + ENCODINGS_.put("utf8", charset); + ENCODINGS_.put("unicode-1-1-utf-8", charset); + + charset = Charset.forName("big5"); + ENCODINGS_.put("big5", charset); + ENCODINGS_.put("big5-hkscs", charset); + ENCODINGS_.put("cn-big5", charset); + ENCODINGS_.put("csbig5", charset); + ENCODINGS_.put("x-x-big5", charset); + + charset = Charset.forName("euc-jp"); + ENCODINGS_.put("cseucpkdfmtjapanese", charset); + ENCODINGS_.put("euc-jp", charset); + ENCODINGS_.put("x-euc-jp", charset); + + charset = Charset.forName("euc-kr"); + ENCODINGS_.put("cseuckr", charset); + ENCODINGS_.put("csksc56011987", charset); + ENCODINGS_.put("euc-kr", charset); + ENCODINGS_.put("iso-ir-149", charset); + ENCODINGS_.put("korean", charset); + ENCODINGS_.put("ks_c_5601-1987", charset); + ENCODINGS_.put("ks_c_5601-1989", charset); + ENCODINGS_.put("ksc5601", charset); + ENCODINGS_.put("ksc_5601", charset); + ENCODINGS_.put("windows-949", charset); + + charset = Charset.forName("gb18030"); + ENCODINGS_.put("gb18030", charset); + + charset = Charset.forName("gbk"); + ENCODINGS_.put("chinese", charset); + ENCODINGS_.put("csgb2312", charset); + ENCODINGS_.put("csiso58gb231280", charset); + ENCODINGS_.put("gb2312", charset); + ENCODINGS_.put("gb_2312", charset); + ENCODINGS_.put("gb_2312-80", charset); + ENCODINGS_.put("gbk", charset); + ENCODINGS_.put("iso-ir-58", charset); + ENCODINGS_.put("x-gbk", charset); + + charset = Charset.forName("ibm866"); + ENCODINGS_.put("866", charset); + ENCODINGS_.put("cp866", charset); + ENCODINGS_.put("csibm866", charset); + ENCODINGS_.put("ibm866", charset); + + charset = Charset.forName("iso-2022-jp"); + ENCODINGS_.put("csiso2022jp", charset); + ENCODINGS_.put("iso-2022-jp", charset); + + charset = Charset.forName("iso-8859-2"); + ENCODINGS_.put("csisolatin2", charset); + ENCODINGS_.put("iso-8859-2", charset); + ENCODINGS_.put("iso-ir-101", charset); + ENCODINGS_.put("iso8859-2", charset); + ENCODINGS_.put("iso88592", charset); + ENCODINGS_.put("iso_8859-2", charset); + ENCODINGS_.put("iso_8859-2:1987", charset); + ENCODINGS_.put("l2", charset); + ENCODINGS_.put("latin2", charset); + + charset = Charset.forName("iso-8859-3"); + ENCODINGS_.put("csisolatin3", charset); + ENCODINGS_.put("iso-8859-3", charset); + ENCODINGS_.put("iso-ir-109", charset); + ENCODINGS_.put("iso8859-3", charset); + ENCODINGS_.put("iso88593", charset); + ENCODINGS_.put("iso_8859-3", charset); + ENCODINGS_.put("iso_8859-3:1988", charset); + ENCODINGS_.put("l3", charset); + ENCODINGS_.put("latin3", charset); + + charset = Charset.forName("iso-8859-4"); + ENCODINGS_.put("csisolatin4", charset); + ENCODINGS_.put("iso-8859-4", charset); + ENCODINGS_.put("iso-ir-110", charset); + ENCODINGS_.put("iso8859-4", charset); + ENCODINGS_.put("iso88594", charset); + ENCODINGS_.put("iso_8859-4", charset); + ENCODINGS_.put("iso_8859-4:1988", charset); + ENCODINGS_.put("l4", charset); + ENCODINGS_.put("latin4", charset); + + charset = Charset.forName("iso-8859-5"); + ENCODINGS_.put("csisolatincyrillic", charset); + ENCODINGS_.put("cyrillic", charset); + ENCODINGS_.put("iso-8859-5", charset); + ENCODINGS_.put("iso-ir-144", charset); + ENCODINGS_.put("iso88595", charset); + ENCODINGS_.put("iso_8859-5", charset); + ENCODINGS_.put("iso_8859-5:1988", charset); + + charset = Charset.forName("iso-8859-6"); + ENCODINGS_.put("arabic", charset); + ENCODINGS_.put("asmo-708", charset); + ENCODINGS_.put("csiso88596e", charset); + ENCODINGS_.put("csiso88596i", charset); + ENCODINGS_.put("csisolatinarabic", charset); + ENCODINGS_.put("ecma-114", charset); + ENCODINGS_.put("iso-8859-6", charset); + ENCODINGS_.put("iso-8859-6-e", charset); + ENCODINGS_.put("iso-8859-6-i", charset); + ENCODINGS_.put("iso-ir-127", charset); + ENCODINGS_.put("iso8859-6", charset); + ENCODINGS_.put("iso88596", charset); + ENCODINGS_.put("iso_8859-6", charset); + ENCODINGS_.put("iso_8859-6:1987", charset); + + charset = Charset.forName("iso-8859-7"); + ENCODINGS_.put("csisolatingreek", charset); + ENCODINGS_.put("ecma-118", charset); + ENCODINGS_.put("elot_928", charset); + ENCODINGS_.put("greek", charset); + ENCODINGS_.put("greek8", charset); + ENCODINGS_.put("iso-8859-7", charset); + ENCODINGS_.put("iso-ir-126", charset); + ENCODINGS_.put("iso8859-7", charset); + ENCODINGS_.put("iso88597", charset); + ENCODINGS_.put("iso_8859-7", charset); + ENCODINGS_.put("iso_8859-7:1987", charset); + ENCODINGS_.put("sun_eu_greek", charset); + + charset = Charset.forName("iso-8859-8"); + ENCODINGS_.put("csiso88598e", charset); + ENCODINGS_.put("csisolatinhebrew", charset); + ENCODINGS_.put("hebrew", charset); + ENCODINGS_.put("iso-8859-8", charset); + ENCODINGS_.put("iso-8859-8-e", charset); + ENCODINGS_.put("iso-ir-138", charset); + ENCODINGS_.put("iso8859-8", charset); + ENCODINGS_.put("iso88598", charset); + ENCODINGS_.put("iso_8859-8", charset); + ENCODINGS_.put("iso_8859-8:1988", charset); + ENCODINGS_.put("visual", charset); + +// charset = Charset.forName("iso-8859-8-i"); +// ENCODINGS_.put("csiso88598i", charset); +// ENCODINGS_.put("iso-8859-8-i", charset); +// ENCODINGS_.put("logical", charset); + +// charset = Charset.forName("iso-8859-10"); +// ENCODINGS_.put("csisolatin6", charset); +// ENCODINGS_.put("iso-8859-10", charset); +// ENCODINGS_.put("iso-ir-157", charset); +// ENCODINGS_.put("iso8859-10", charset); +// ENCODINGS_.put("iso885910", charset); +// ENCODINGS_.put("l6", charset); +// ENCODINGS_.put("latin6", charset); + + charset = Charset.forName("iso-8859-13"); + ENCODINGS_.put("iso-8859-13", charset); + ENCODINGS_.put("iso8859-13", charset); + ENCODINGS_.put("iso885913", charset); + +// charset = Charset.forName("iso-8859-14"); +// ENCODINGS_.put("iso-8859-14", charset); +// ENCODINGS_.put("iso8859-14", charset); +// ENCODINGS_.put("iso885914", charset); + + charset = Charset.forName("iso-8859-15"); + ENCODINGS_.put("csisolatin9", charset); + ENCODINGS_.put("iso-8859-15", charset); + ENCODINGS_.put("iso8859-15", charset); + ENCODINGS_.put("iso885915", charset); + ENCODINGS_.put("l9", charset); + // ENCODINGS_.put("latin9", charset); + +// charset = Charset.forName("iso-8859-16"); +// ENCODINGS_.put("iso-8859-16", charset); + + charset = Charset.forName("koi8-r"); + ENCODINGS_.put("cskoi8r", charset); + ENCODINGS_.put("koi", charset); + ENCODINGS_.put("koi8", charset); + ENCODINGS_.put("koi8-r", charset); + ENCODINGS_.put("koi8_r", charset); + + charset = Charset.forName("koi8-u"); + ENCODINGS_.put("koi8-u", charset); + + charset = Charset.forName("shift_jis"); + ENCODINGS_.put("csshiftjis", charset); + ENCODINGS_.put("ms_kanji", charset); + ENCODINGS_.put("shift-jis", charset); + ENCODINGS_.put("shift_jis", charset); + ENCODINGS_.put("sjis", charset); + ENCODINGS_.put("windows-31j", charset); + ENCODINGS_.put("x-sjis", charset); + + charset = Charset.forName("utf-16be"); + ENCODINGS_.put("utf-16be", charset); + + charset = Charset.forName("utf-16le"); + ENCODINGS_.put("utf-16", charset); + ENCODINGS_.put("utf-16le", charset); + + charset = Charset.forName("windows-1250"); + ENCODINGS_.put("cp1250", charset); + ENCODINGS_.put("windows-1250", charset); + ENCODINGS_.put("x-cp1250", charset); + + charset = Charset.forName("windows-1251"); + ENCODINGS_.put("cp1251", charset); + ENCODINGS_.put("windows-1251", charset); + ENCODINGS_.put("x-cp1251", charset); + + charset = Charset.forName("windows-1252"); + ENCODINGS_.put("ansi_x3.4-1968", charset); + ENCODINGS_.put("ascii", charset); + ENCODINGS_.put("cp1252", charset); + ENCODINGS_.put("cp819", charset); + ENCODINGS_.put("csisolatin1", charset); + ENCODINGS_.put("ibm819", charset); + ENCODINGS_.put("iso-8859-1", charset); + ENCODINGS_.put("iso-ir-100", charset); + ENCODINGS_.put("iso8859-1", charset); + ENCODINGS_.put("iso88591", charset); + ENCODINGS_.put("iso_8859-1", charset); + ENCODINGS_.put("iso_8859-1:1987", charset); + ENCODINGS_.put("l1", charset); + ENCODINGS_.put("latin1", charset); + ENCODINGS_.put("us-ascii", charset); + ENCODINGS_.put("windows-1252", charset); + ENCODINGS_.put("x-cp1252", charset); + + charset = Charset.forName("windows-1253"); + ENCODINGS_.put("cp1253", charset); + ENCODINGS_.put("windows-1253", charset); + ENCODINGS_.put("x-cp1253", charset); + + charset = Charset.forName("windows-1254"); + ENCODINGS_.put("cp1254", charset); + ENCODINGS_.put("csisolatin5", charset); + ENCODINGS_.put("iso-8859-9", charset); + ENCODINGS_.put("iso-ir-148", charset); + ENCODINGS_.put("iso8859-9", charset); + ENCODINGS_.put("iso88599", charset); + ENCODINGS_.put("iso_8859-9", charset); + ENCODINGS_.put("iso_8859-9:1989", charset); + ENCODINGS_.put("l5", charset); + ENCODINGS_.put("latin5", charset); + ENCODINGS_.put("windows-1254", charset); + ENCODINGS_.put("x-cp1254", charset); + + charset = Charset.forName("windows-1255"); + ENCODINGS_.put("cp1255", charset); + ENCODINGS_.put("windows-1255", charset); + ENCODINGS_.put("x-cp1255", charset); + + charset = Charset.forName("windows-1256"); + ENCODINGS_.put("cp1256", charset); + ENCODINGS_.put("windows-1256", charset); + ENCODINGS_.put("x-cp1256", charset); + + charset = Charset.forName("windows-1257"); + ENCODINGS_.put("cp1257", charset); + ENCODINGS_.put("windows-1257", charset); + ENCODINGS_.put("x-cp1257", charset); + + charset = Charset.forName("windows-1258"); + ENCODINGS_.put("cp1258", charset); + ENCODINGS_.put("windows-1258", charset); + ENCODINGS_.put("x-cp1258", charset); + + charset = Charset.forName("x-windows-874"); + ENCODING_NAMES_.put("x-windows-874", "windows-874"); + ENCODINGS_.put("dos-874", charset); + ENCODINGS_.put("iso-8859-11", charset); + ENCODINGS_.put("iso8859-11", charset); + ENCODINGS_.put("iso885911", charset); + ENCODINGS_.put("tis-620", charset); + ENCODINGS_.put("windows-874", charset); + + charset = Charset.forName("x-MacCyrillic"); + ENCODING_NAMES_.put("x-MacCyrillic", "x-mac-cyrillic"); + ENCODINGS_.put("x-mac-cyrillic", charset); + ENCODINGS_.put("x-mac-ukrainian", charset); + + charset = Charset.forName("x-MacRoman"); + ENCODING_NAMES_.put("x-MacRoman", "macintosh"); + ENCODINGS_.put("csmacintosh", charset); + ENCODINGS_.put("mac", charset); + ENCODINGS_.put("macintosh", charset); + ENCODINGS_.put("x-mac-roman", charset); + +// charset = Charset.forName("x-user-defined"); +// ENCODINGS_.put("x-user-defined", charset); + } + /** + * Ctor. + */ + public TextDecoder() { + } + + /** * Creates an instance. + * @param encoding the encoding */ @JsxConstructor - public TextDecoder() { + public TextDecoder(final Object encoding) { + if (Undefined.instance == encoding) { + return; + } + + final String enc = Context.toString(encoding); + final Charset charset = ENCODINGS_.get(enc); + if (charset != null) { + encoding_ = charset; + return; + } + throw ScriptRuntime.typeError("Argument 1 '" + enc + "' is not a supported encoding"); } + + /** + * @return always "utf-8" + */ + @JsxGetter + public String getEncoding() { + String name = encoding_.name(); + name = ENCODING_NAMES_.get(name); + if (name != null) { + return name; + } + return encoding_.name().toLowerCase(); + } + + /** + * @param buffer to be decoded + * @return returns the decoded string + */ + @JsxFunction + public String decode(final Object buffer) { + if (Undefined.instance == buffer) { + return ""; + } + + ArrayBuffer arrayBuffer = null; + if (buffer instanceof ArrayBuffer) { + arrayBuffer = (ArrayBuffer) buffer; + } + else if (buffer instanceof ArrayBufferView) { + arrayBuffer = ((ArrayBufferView) buffer).getBuffer(); + } + + if (arrayBuffer != null) { + return new String(arrayBuffer.getBytes(), encoding_); + } + + throw ScriptRuntime.typeError("Argument 1 of TextDecoder.decode could not be" + + " converted to any of: ArrayBufferView, ArrayBuffer."); + } } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoder.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoder.java 2017-12-26 10:49:19 UTC (rev 15042) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoder.java 2017-12-27 16:53:36 UTC (rev 15043) @@ -17,14 +17,23 @@ import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF; +import java.nio.charset.StandardCharsets; + import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor; +import com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction; +import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter; +import com.gargoylesoftware.htmlunit.javascript.host.arrays.Uint8Array; +import net.sourceforge.htmlunit.corejs.javascript.Context; +import net.sourceforge.htmlunit.corejs.javascript.Undefined; + /** * A JavaScript object for {@code TextEncoder}. * * @author Ahmed Ashour + * @author Ronald Brill */ @JsxClass({CHROME, FF}) public class TextEncoder extends SimpleScriptable { @@ -35,4 +44,34 @@ @JsxConstructor public TextEncoder() { } + + /** + * @return always "utf-8" + */ + @JsxGetter + public String getEncoding() { + return "utf-8"; + } + + /** + * @param toEncode the string to encode + * @return returns a Uint8Array containing the text given encoded . + */ + @JsxFunction + public Uint8Array encode(final Object toEncode) { + if (Undefined.instance == toEncode) { + return new Uint8Array(new byte[0], getWindow()); + } + + final String txt; + if (toEncode == null) { + txt = "null"; + } + else { + txt = Context.toString(toEncode); + } + + final byte[] bytes = txt.getBytes(StandardCharsets.UTF_8); + return new Uint8Array(bytes, getWindow()); + } } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/arrays/Uint8Array.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/arrays/Uint8Array.java 2017-12-26 10:49:19 UTC (rev 15042) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/arrays/Uint8Array.java 2017-12-27 16:53:36 UTC (rev 15043) @@ -17,6 +17,7 @@ import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstant; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor; +import com.gargoylesoftware.htmlunit.javascript.host.Window; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; @@ -31,6 +32,32 @@ @JsxClass public class Uint8Array extends ArrayBufferViewBase { + /** + * Ctor. + */ + public Uint8Array() { + super(); + } + + /** + * Ctor. + * + * @param bytes the bytes to store + * @param window the context + */ + public Uint8Array(final byte[] bytes, final Window window) { + this(); + setPrototype(window.getPrototype(getClass())); + setParentScope(getParentScope()); + + setByteLength(bytes.length); + + final ArrayBuffer buffer = new ArrayBuffer(bytes); + buffer.setPrototype(window.getPrototype(buffer.getClass())); + buffer.setParentScope(getParentScope()); + setBuffer(buffer); + } + /** The size, in bytes, of each array element. */ @JsxConstant public static final int BYTES_PER_ELEMENT = 1; @@ -70,5 +97,4 @@ protected int getBytesPerElement() { return BYTES_PER_ELEMENT; } - } Added: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoderTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoderTest.java (rev 0) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoderTest.java 2017-12-27 16:53:36 UTC (rev 15043) @@ -0,0 +1,796 @@ +/* + * Copyright (c) 2002-2017 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gargoylesoftware.htmlunit.javascript.host; + +import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.CHROME; +import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.FF; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.gargoylesoftware.htmlunit.BrowserRunner; +import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; +import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented; +import com.gargoylesoftware.htmlunit.WebDriverTestCase; + +/** + * Tests for {@link TextDecoder}. + * + * @author Ronald Brill + * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder">TextDecoder() - Web APIs | MDN</a> + */ +@RunWith(BrowserRunner.class) +public class TextDecoderTest extends WebDriverTestCase { + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = {"utf-8", "utf-8", "utf-8", "utf-8"}, + IE = "no TextDecoder") + public void encoding() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextDecoder === 'undefined') {\n" + + " alert('no TextDecoder');\n" + + " return;\n" + + " };\n" + + " var enc = new TextDecoder();\n" + + " alert(enc.encoding);\n" + + + " enc = new TextDecoder(undefined);\n" + + " alert(enc.encoding);\n" + + + " enc = new TextDecoder('utf-8');\n" + + " alert(enc.encoding);\n" + + + " enc = new TextDecoder('utf8');\n" + + " alert(enc.encoding);\n" + + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "utf-8", + IE = "no TextDecoder") + public void encoding_utf8() throws Exception { + encoding("unicode-1-1-utf-8"); + encoding("utf-8"); + encoding("utf8"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "ibm866", + IE = "no TextDecoder") + public void encoding_ibm866() throws Exception { + encoding("866"); + encoding("cp866"); + encoding("csibm866"); + encoding("ibm866"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-2", + IE = "no TextDecoder") + public void encoding_iso_8859_2() throws Exception { + encoding("csisolatin2"); + encoding("iso-8859-2"); + encoding("iso-ir-101"); + encoding("iso8859-2"); + encoding("iso88592"); + encoding("iso_8859-2"); + encoding("iso_8859-2:1987"); + encoding("l2"); + encoding("latin2"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-3", + IE = "no TextDecoder") + public void encoding_iso_8859_3() throws Exception { + encoding("csisolatin3"); + encoding("iso-8859-3"); + encoding("iso-ir-109"); + encoding("iso8859-3"); + encoding("iso88593"); + encoding("iso_8859-3"); + encoding("iso_8859-3:1988"); + encoding("l3"); + encoding("latin3"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-4", + IE = "no TextDecoder") + public void encoding_iso_8859_4() throws Exception { + encoding("csisolatin4"); + encoding("iso-8859-4"); + encoding("iso-ir-110"); + encoding("iso8859-4"); + encoding("iso88594"); + encoding("iso_8859-4"); + encoding("iso_8859-4:1988"); + encoding("l4"); + encoding("latin4"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-5", + IE = "no TextDecoder") + public void encoding_iso_8859_5() throws Exception { + encoding("csisolatincyrillic"); + encoding("cyrillic"); + encoding("iso-8859-5"); + encoding("iso-ir-144"); + encoding("iso88595"); + encoding("iso_8859-5"); + encoding("iso_8859-5:1988"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-6", + IE = "no TextDecoder") + public void encoding_iso_8859_6() throws Exception { + encoding("arabic"); + encoding("asmo-708"); + encoding("csiso88596e"); + encoding("csiso88596i"); + encoding("csisolatinarabic"); + encoding("ecma-114"); + encoding("iso-8859-6"); + encoding("iso-8859-6-e"); + encoding("iso-8859-6-i"); + encoding("iso-ir-127"); + encoding("iso8859-6"); + encoding("iso88596"); + encoding("iso_8859-6"); + encoding("iso_8859-6:1987"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-7", + IE = "no TextDecoder") + public void encoding_iso_8859_7() throws Exception { + encoding("csisolatingreek"); + encoding("ecma-118"); + encoding("elot_928"); + encoding("greek"); + encoding("greek8"); + encoding("iso-8859-7"); + encoding("iso-ir-126"); + encoding("iso8859-7"); + encoding("iso88597"); + encoding("iso_8859-7"); + encoding("iso_8859-7:1987"); + encoding("sun_eu_greek"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-8", + IE = "no TextDecoder") + public void encoding_iso_8859_8() throws Exception { + encoding("csiso88598e"); + encoding("csisolatinhebrew"); + encoding("hebrew"); + encoding("iso-8859-8"); + encoding("iso-8859-8-e"); + encoding("iso-ir-138"); + encoding("iso8859-8"); + encoding("iso88598"); + encoding("iso_8859-8"); + encoding("iso_8859-8:1988"); + encoding("visual"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-8-i", + IE = "no TextDecoder") + @NotYetImplemented({CHROME, FF}) + public void encoding_iso_8859_8i() throws Exception { + encoding("csiso88598i"); + encoding("iso-8859-8-i"); + encoding("logical"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-10", + IE = "no TextDecoder") + @NotYetImplemented({CHROME, FF}) + public void encoding_iso_8859_10() throws Exception { + encoding("csisolatin6"); + encoding("iso-8859-10"); + encoding("iso-ir-157"); + encoding("iso8859-10"); + encoding("iso885910"); + encoding("l6"); + encoding("latin6"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-13", + IE = "no TextDecoder") + public void encoding_iso_8859_13() throws Exception { + encoding("iso-8859-13"); + encoding("iso8859-13"); + encoding("iso885913"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-14", + IE = "no TextDecoder") + @NotYetImplemented({CHROME, FF}) + public void encoding_iso_8859_14() throws Exception { + encoding("iso-8859-14"); + encoding("iso8859-14"); + encoding("iso885914"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-15", + IE = "no TextDecoder") + public void encoding_iso_8859_15() throws Exception { + encoding("csisolatin9"); + encoding("iso-8859-15"); + encoding("iso8859-15"); + encoding("iso885915"); + encoding("l9"); + // encoding("latin9"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "exception", + IE = "no TextDecoder") + public void encoding_iso_8859_15_ex() throws Exception { + encoding("latin9"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-8859-16", + IE = "no TextDecoder") + @NotYetImplemented({CHROME, FF}) + public void encoding_iso_8859_16() throws Exception { + encoding("iso-8859-16"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "koi8-r", + IE = "no TextDecoder") + public void encoding_koi8_r() throws Exception { + encoding("cskoi8r"); + encoding("koi"); + encoding("koi8"); + encoding("koi8-r"); + encoding("koi8_r"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "koi8-u", + IE = "no TextDecoder") + public void encoding_koi8_u() throws Exception { + encoding("koi8-u"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "macintosh", + IE = "no TextDecoder") + public void encoding_macintosh() throws Exception { + encoding("csmacintosh"); + encoding("mac"); + encoding("macintosh"); + encoding("x-mac-roman"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-874", + IE = "no TextDecoder") + public void encoding_windows_874() throws Exception { + encoding("dos-874"); + encoding("iso-8859-11"); + encoding("iso8859-11"); + encoding("iso885911"); + encoding("tis-620"); + encoding("windows-874"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1250", + IE = "no TextDecoder") + public void encoding_windows_1250() throws Exception { + encoding("cp1250"); + encoding("windows-1250"); + encoding("x-cp1250"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1251", + IE = "no TextDecoder") + public void encoding_windows_1251() throws Exception { + encoding("cp1251"); + encoding("windows-1251"); + encoding("x-cp1251"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1252", + IE = "no TextDecoder") + public void encoding_windows_1252() throws Exception { + encoding("ansi_x3.4-1968"); + encoding("ascii"); + encoding("cp1252"); + encoding("cp819"); + encoding("csisolatin1"); + encoding("ibm819"); + encoding("iso-8859-1"); + encoding("iso-ir-100"); + encoding("iso8859-1"); + encoding("iso88591"); + encoding("iso_8859-1"); + encoding("iso_8859-1:1987"); + encoding("l1"); + encoding("latin1"); + encoding("us-ascii"); + encoding("windows-1252"); + encoding("x-cp1252"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1253", + IE = "no TextDecoder") + public void encoding_windows_1253() throws Exception { + encoding("cp1253"); + encoding("windows-1253"); + encoding("x-cp1253"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1254", + IE = "no TextDecoder") + public void encoding_windows_1254() throws Exception { + encoding("cp1254"); + encoding("csisolatin5"); + encoding("iso-8859-9"); + encoding("iso-ir-148"); + encoding("iso8859-9"); + encoding("iso88599"); + encoding("iso_8859-9"); + encoding("iso_8859-9:1989"); + encoding("l5"); + encoding("latin5"); + encoding("windows-1254"); + encoding("x-cp1254"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1255", + IE = "no TextDecoder") + public void encoding_windows_1255() throws Exception { + encoding("cp1255"); + encoding("windows-1255"); + encoding("x-cp1255"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1256", + IE = "no TextDecoder") + public void encoding_windows_1256() throws Exception { + encoding("cp1256"); + encoding("windows-1256"); + encoding("x-cp1256"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1257", + IE = "no TextDecoder") + public void encoding_windows_1257() throws Exception { + encoding("cp1257"); + encoding("windows-1257"); + encoding("x-cp1257"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "windows-1258", + IE = "no TextDecoder") + public void encoding_windows_1258() throws Exception { + encoding("cp1258"); + encoding("windows-1258"); + encoding("x-cp1258"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "x-mac-cyrillic", + IE = "no TextDecoder") + public void encoding_x_mac_cyrillic() throws Exception { + encoding("x-mac-cyrillic"); + encoding("x-mac-ukrainian"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "gbk", + IE = "no TextDecoder") + public void encoding_gbk() throws Exception { + encoding("chinese"); + encoding("csgb2312"); + encoding("csiso58gb231280"); + encoding("gb2312"); + encoding("gb_2312"); + encoding("gb_2312-80"); + encoding("gbk"); + encoding("iso-ir-58"); + encoding("x-gbk"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "gb18030", + IE = "no TextDecoder") + public void encoding_gb18030() throws Exception { + encoding("gb18030"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "exception", + IE = "no TextDecoder") + public void encoding_hz_gb_2312() throws Exception { + encoding("hz-gb-2312"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "big5", + IE = "no TextDecoder") + public void encoding_big5() throws Exception { + encoding("big5"); + encoding("big5-hkscs"); + encoding("cn-big5"); + encoding("csbig5"); + encoding("x-x-big5"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "euc-jp", + IE = "no TextDecoder") + public void encoding_euc_jp() throws Exception { + encoding("cseucpkdfmtjapanese"); + encoding("euc-jp"); + encoding("x-euc-jp"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "iso-2022-jp", + IE = "no TextDecoder") + public void encoding_iso_2022_jp() throws Exception { + encoding("csiso2022jp"); + encoding("iso-2022-jp"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "shift_jis", + IE = "no TextDecoder") + public void encoding_shift_jis() throws Exception { + encoding("csshiftjis"); + encoding("ms_kanji"); + encoding("shift-jis"); + encoding("shift_jis"); + encoding("sjis"); + encoding("windows-31j"); + encoding("x-sjis"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "euc-kr", + IE = "no TextDecoder") + public void encoding_euc_kr() throws Exception { + encoding("cseuckr"); + encoding("csksc56011987"); + encoding("euc-kr"); + encoding("iso-ir-149"); + encoding("korean"); + encoding("ks_c_5601-1987"); + encoding("ks_c_5601-1989"); + encoding("ksc5601"); + encoding("ksc_5601"); + encoding("windows-949"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "exception", + IE = "no TextDecoder") + public void encoding_iso_2022_kr() throws Exception { + encoding("csiso2022kr"); + encoding("iso-2022-kr"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "utf-16be", + IE = "no TextDecoder") + public void encoding_utf_16be() throws Exception { + encoding("utf-16be"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "utf-16le", + IE = "no TextDecoder") + public void encoding_utf_16le() throws Exception { + encoding("utf-16"); + encoding("utf-16le"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "x-user-defined", + IE = "no TextDecoder") + @NotYetImplemented({CHROME, FF}) + public void encoding_x_user_defined() throws Exception { + encoding("x-user-defined"); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "exception", + IE = "no TextDecoder") + public void encoding_replacement() throws Exception { + encoding("iso-2022-cn"); + encoding("iso-2022-cn-ext"); + } + + private void encoding(final String encoding) throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextDecoder === 'undefined') {\n" + + " alert('no TextDecoder');\n" + + " return;\n" + + " };\n" + + " try {\n" + + " enc = new TextDecoder('" + encoding + "');\n" + + " alert(enc.encoding);\n" + + " } catch(e) { alert('exception'); }\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = {"0", "8", "72", "116"}, + IE = "no TextEncoder") + public void encode() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextEncoder === 'undefined') {\n" + + " alert('no TextEncoder');\n" + + " return;\n" + + " };\n" + + " var enc = new TextEncoder();\n" + + " var encoded = enc.encode('');\n" + + " alert(encoded.length);\n" + + + " encoded = enc.encode('HtmlUnit');\n" + + " alert(encoded.length);\n" + + " alert(encoded[0]);\n" + + " alert(encoded[encoded.length - 1]);\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = {"HtmlUnit"}, + IE = "no TextDecoder") + public void decode() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextDecoder === 'undefined') {\n" + + " alert('no TextDecoder');\n" + + " return;\n" + + " };\n" + + " var enc = new TextEncoder();\n" + + " var encoded = enc.encode('HtmlUnit');\n" + + + " var dec = new TextDecoder('utf-8');\n" + + " var decoded = dec.decode(encoded);\n" + + " alert(decoded);\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = {"", "exception"}, + IE = "no TextDecoder") + public void decode2() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextDecoder === 'undefined') {\n" + + " alert('no TextDecoder');\n" + + " return;\n" + + " };\n" + + " var dec = new TextDecoder('utf-8');\n" + + " try {\n" + + " alert(dec.decode(undefined));\n" + + " } catch(e) { alert('exception'); }\n" + + + " try {\n" + + " alert(dec.decode(null));\n" + + " } catch(e) { alert('exception'); }\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } +} Property changes on: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextDecoderTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoderTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoderTest.java (rev 0) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoderTest.java 2017-12-27 16:53:36 UTC (rev 15043) @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2002-2017 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gargoylesoftware.htmlunit.javascript.host; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.gargoylesoftware.htmlunit.BrowserRunner; +import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; +import com.gargoylesoftware.htmlunit.WebDriverTestCase; + +/** + * Tests for {@link TextEncoder}. + * + * @author Ronald Brill + * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder">TextEncoder() - Web APIs | MDN</a> + */ +@RunWith(BrowserRunner.class) +public class TextEncoderTest extends WebDriverTestCase { + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = "utf-8", + IE = "no TextEncoder") + public void encoding() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextEncoder === 'undefined') {\n" + + " alert('no TextEncoder');\n" + + " return;\n" + + " };\n" + + " var enc = new TextEncoder();\n" + + " alert(enc.encoding);\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = {"0", "8", "72", "116"}, + IE = "no TextEncoder") + public void encode() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextEncoder === 'undefined') {\n" + + " alert('no TextEncoder');\n" + + " return;\n" + + " };\n" + + " var enc = new TextEncoder();\n" + + " var encoded = enc.encode('');\n" + + " alert(encoded.length);\n" + + + " encoded = enc.encode('HtmlUnit');\n" + + " alert(encoded.length);\n" + + " alert(encoded[0]);\n" + + " alert(encoded[encoded.length - 1]);\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts(DEFAULT = {"0", "0", "4"}, + IE = "no TextEncoder") + public void encode2() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + " <script>\n" + + " function doTest() {\n" + + " if (typeof TextEncoder === 'undefined') {\n" + + " alert('no TextEncoder');\n" + + " return;\n" + + " };\n" + + " var enc = new TextEncoder();\n" + + " var encoded = enc.encode();\n" + + " alert(encoded.length);\n" + + + " var encoded = enc.encode(undefined);\n" + + " alert(encoded.length);\n" + + + " var encoded = enc.encode(null);\n" + + " alert(encoded.length);\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } +} Property changes on: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/TextEncoderTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property |
From: <rb...@us...> - 2017-12-29 20:51:12
|
Revision: 15050 http://sourceforge.net/p/htmlunit/code/15050 Author: rbri Date: 2017-12-29 20:51:09 +0000 (Fri, 29 Dec 2017) Log Message: ----------- relax the cast a bit Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java 2017-12-28 16:44:40 UTC (rev 15049) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java 2017-12-29 20:51:09 UTC (rev 15050) @@ -19,9 +19,9 @@ import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; +import net.sourceforge.htmlunit.corejs.javascript.BaseFunction; import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.Function; -import net.sourceforge.htmlunit.corejs.javascript.FunctionObject; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; import net.sourceforge.htmlunit.corejs.javascript.Undefined; @@ -57,10 +57,11 @@ array[i] = scriptable.get(i, scriptable); } } + final Object iterator = scriptable.get(Symbol.ITERATOR_STRING, scriptable); if (iterator != Scriptable.NOT_FOUND) { final List<Object> list = new ArrayList<>(); - final Iterator it = (Iterator) ((FunctionObject) iterator) + final Iterator it = (Iterator) ((BaseFunction) iterator) .call(context, thisObj.getParentScope(), scriptable, new Object[0]); SimpleScriptable next = it.next(); boolean done = (boolean) next.get("done"); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java 2017-12-28 16:44:40 UTC (rev 15049) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java 2017-12-29 20:51:09 UTC (rev 15050) @@ -365,6 +365,69 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = {"3", "1", "two", "3"}, + IE = "not supported") + @NotYetImplemented + public void fromUserDefinedIterable() throws Exception { + final String html + = "<html>\n" + + "<head>\n" + + "<script>\n" + + " if (Array.from) {\n" + + " var myIterable = {};\n" + + " myIterable[Symbol.iterator] = function*() {\n" + + " yield 1;\n" + + " yield 'two';\n" + + " yield 3;\n" + + " };\n" + + " var arr = Array.from(myIterable);\n" + + " alert(arr.length);\n" + + " for (var i = 0; i < arr.length; i++) {\n" + + " alert(arr[i]);\n" + + " }\n" + + " } else {\n" + + " alert('not supported');\n" + + " }\n" + + "</script>\n" + + "</head>\n" + + "<body>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "0", + IE = "not supported") + public void fromNativeObject() throws Exception { + final String html + = "<html>\n" + + "<head>\n" + + "<script>\n" + + " if (Array.from) {\n" + + " var arr = Array.from({firstName: 'Erika', age: 42});\n" + + " alert(arr.length);\n" + + " for (var i = 0; i < arr.length; i++) {\n" + + " alert(arr[i]);\n" + + " }\n" + + " } else {\n" + + " alert('not supported');\n" + + " }\n" + + "</script>\n" + + "</head>\n" + + "<body>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts({"true", "true", "true", "true", "false", "false", "false", "false", "false", "false", "false", "false", "false"}) public void isArray() throws Exception { |
From: <rb...@us...> - 2017-12-30 20:13:16
|
Revision: 15051 http://sourceforge.net/p/htmlunit/code/15051 Author: rbri Date: 2017-12-30 20:13:13 +0000 (Sat, 30 Dec 2017) Log Message: ----------- CSSStyleSheet#addRule fixed error handling CSSStyleDeclaration#cssText throws an NPE when in stylesheet mode CSSStyleDeclaration#cssText usually return a ';' after the last rule make one method private Issue 1943 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2017-12-29 20:51:09 UTC (rev 15050) +++ trunk/htmlunit/src/changes/changes.xml 2017-12-30 20:13:13 UTC (rev 15051) @@ -7,6 +7,18 @@ </properties> <body> + <release version="2.30" date="xx, 2018" description="Bugfixes"> + <action type="fix" dev="rbri" issue="1943"> + JavaScript: CSSStyleSheet#addRule fixed error handling + </action> + <action type="fix" dev="rbri"> + JavaScript: CSSStyleDeclaration#cssText throws an NPE when in stylesheet mode + </action> + <action type="fix" dev="rbri"> + JavaScript: CSSStyleDeclaration#cssText usually return a ';' after the last rule + </action> + </release> + <release version="2.29" date="December 28, 2017" description="Bugfixes, Chrome 63, WebStart support"> <action type="add" dev="rbri"> JavaScript: TextEncoder/TextDecoder impl added. Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 2017-12-29 20:51:09 UTC (rev 15050) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 2017-12-30 20:13:13 UTC (rev 15051) @@ -273,7 +273,7 @@ * Initializes the object. * @param htmlElement the element that this style describes */ - void initialize(final Element element) { + private void initialize(final Element element) { // Initialize. WebAssert.notNull("htmlElement", element); jsElement_ = element; @@ -1217,6 +1217,13 @@ */ @JsxGetter public String getCssText() { + if (styleDeclaration_ != null) { + final String text = styleDeclaration_.getCssText(); + if (styleDeclaration_.getLength() > 0) { + return text + ";"; + } + return text; + } return jsElement_.getDomNodeOrDie().getAttribute("style"); } @@ -1226,6 +1233,10 @@ */ @JsxSetter public void setCssText(final String value) { + if (styleDeclaration_ != null) { + styleDeclaration_.setCssText(value); + return; + } jsElement_.getDomNodeOrDie().setAttribute("style", value); } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java 2017-12-29 20:51:09 UTC (rev 15050) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java 2017-12-30 20:13:13 UTC (rev 15051) @@ -1176,7 +1176,7 @@ */ @JsxFunction({IE, CHROME}) public int addRule(final String selector, final String rule) { - final String completeRule = selector + " {" + rule + "}"; + String completeRule = selector + " {" + rule + "}"; try { initCssRules(); wrapped_.insertRule(completeRule, wrapped_.getCssRules().getLength()); @@ -1183,7 +1183,16 @@ refreshCssRules(); } catch (final DOMException e) { - throw Context.throwAsScriptRuntimeEx(e); + // in case of error try with an empty rule + completeRule = selector + " {}"; + try { + initCssRules(); + wrapped_.insertRule(completeRule, wrapped_.getCssRules().getLength()); + refreshCssRules(); + } + catch (final DOMException ex) { + throw Context.throwAsScriptRuntimeEx(ex); + } } return -1; } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java 2017-12-29 20:51:09 UTC (rev 15050) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java 2017-12-30 20:13:13 UTC (rev 15051) @@ -191,8 +191,8 @@ * @throws Exception if an error occurs */ @Test - @Alerts(DEFAULT = {"1", "false", "false", "0", "2", "p"}, - FF = {"1", "false", "true", "0", "2", "p"}) + @Alerts(DEFAULT = {"1", "false", "false", "0", "2", "p", "vertical-align: top;"}, + FF = {"1", "false", "true", "0", "2", "p", "vertical-align: top;"}) public void addRule_insertRule() throws Exception { final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n" @@ -205,9 +205,10 @@ + " if (s.insertRule)\n" + " alert(s.insertRule('div { color: red; }', 0));\n" + " else\n" - + " alert(s.addRule('div', 'color: red;', 1));\n" + + " alert(s.addRule('div', 'color: red;'));\n" + " alert(rules.length);\n" + " alert(rules[1].selectorText);\n" + + " alert(rules[1].style.cssText);\n" + "}</script>\n" + "<style id='myStyle'>p { vertical-align:top }</style>\n" + "</head><body onload='doTest()'>\n" @@ -217,12 +218,45 @@ } /** + * Minimal test for addRule / insertRule. + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = {"1", "-1", "div", "", "2"}, + IE = {"1", "1", "div", "", "2"}, + FF = {"1", "1"}) + public void addRuleInvalidRule() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + "<script>\n" + + " function doTest() {\n" + + " var f = document.getElementById('myStyle');\n" + + " var s = f.sheet ? f.sheet : f.styleSheet;\n" + + " var rules = s.cssRules || s.rules;\n" + + " alert(rules.length);\n" + + " if (s.addRule) {\n" + + " alert(s.addRule('div', 'invalid'));\n" + + " alert(rules[rules.length - 1].selectorText);\n" + + " alert(rules[rules.length - 1].style.cssText);\n" + + " }\n" + + " alert(rules.length);\n" + + " }\n" + + " </script>\n" + + " <style id='myStyle'>p { vertical-align:top }</style>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** * Minimal test for removeRule / deleteRule. * @throws Exception if an error occurs */ @Test - @Alerts(DEFAULT = {"2", "false", "false", "undefined", "1", "div"}, - FF = {"2", "false", "true", "undefined", "1", "div"}) + @Alerts(DEFAULT = {"2", "false", "false", "undefined", "1", "div", "color: red;"}, + FF = {"2", "false", "true", "undefined", "1", "div", "color: red;"}) public void removeRule_deleteRule() throws Exception { final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n" @@ -238,6 +272,7 @@ + " alert(s.removeRule(0));\n" + " alert(rules.length);\n" + " alert(rules[0].selectorText);\n" + + " alert(rules[0].style.cssText);\n" + "}</script>\n" + "<style id='myStyle'>p { vertical-align:top } div { color: red; }</style>\n" + "</head><body onload='doTest()'>\n" @@ -277,7 +312,7 @@ * @throws Exception if an error occurs */ @Test - @Alerts({"2", "1", "div"}) + @Alerts({"2", "1", "div", "color: red;"}) public void deleteRuleIgnored() throws Exception { final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n" @@ -292,6 +327,7 @@ + " s.removeRule(0);\n" + " alert(rules.length);\n" + " alert(rules[0].selectorText);\n" + + " alert(rules[0].style.cssText);\n" + " } catch(err) { alert('exception'); }\n" + "}</script>\n" + "<style id='myStyle'>\n" @@ -309,7 +345,7 @@ * @throws Exception if an error occurs */ @Test - @Alerts({"2", "1", "p"}) + @Alerts({"2", "1", "p", "vertical-align: top;"}) public void deleteRuleIgnoredLast() throws Exception { final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n" @@ -324,6 +360,7 @@ + " s.removeRule(1);\n" + " alert(rules.length);\n" + " alert(rules[0].selectorText);\n" + + " alert(rules[0].style.cssText);\n" + " } catch(err) { alert('exception'); }\n" + "}</script>\n" + "<style id='myStyle'>\n" @@ -342,7 +379,7 @@ * @throws Exception if an error occurs */ @Test - @Alerts({"2", ".testStyleDef", ".testStyle"}) + @Alerts({"2", ".testStyleDef", "height: 42px;", ".testStyle", "width: 24px;"}) public void insertRuleLeadingWhitespace() throws Exception { final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ @@ -356,7 +393,9 @@ + " s.insertRule(' .testStyleDef { height: 42px; }', 0);\n" + " alert(rules.length);\n" + " alert(rules[0].selectorText);\n" + + " alert(rules[0].style.cssText);\n" + " alert(rules[1].selectorText);\n" + + " alert(rules[1].style.cssText);\n" + " }\n" + "}</script>\n" + "<style id='myStyle'></style>\n" |
From: <rb...@us...> - 2017-12-31 11:20:03
|
Revision: 15052 http://sourceforge.net/p/htmlunit/code/15052 Author: rbri Date: 2017-12-31 11:20:00 +0000 (Sun, 31 Dec 2017) Log Message: ----------- CSSStyleSheet#addRule fixed return value when simulating ie CSSStyleSheet#insertRule improved error handling Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2017-12-30 20:13:13 UTC (rev 15051) +++ trunk/htmlunit/src/changes/changes.xml 2017-12-31 11:20:00 UTC (rev 15052) @@ -12,6 +12,12 @@ JavaScript: CSSStyleSheet#addRule fixed error handling </action> <action type="fix" dev="rbri"> + JavaScript: CSSStyleSheet#addRule fixed return value when simulating ie + </action> + <action type="fix" dev="rbri"> + JavaScript: CSSStyleSheet#insertRule improved error handling + </action> + <action type="fix" dev="rbri"> JavaScript: CSSStyleDeclaration#cssText throws an NPE when in stylesheet mode </action> <action type="fix" dev="rbri"> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2017-12-30 20:13:13 UTC (rev 15051) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2017-12-31 11:20:00 UTC (rev 15052) @@ -1509,6 +1509,13 @@ STRING_TRIM_LEFT_RIGHT, /** + * Method addRule returns the rule position instead of -1. + * (href empty) is null. + */ + @BrowserFeature(IE) + STYLESHEET_ADD_RULE_RETURNS_POS, + + /** * Indicates that the href property for a <link rel="stylesheet" type="text/css" href="" /> * (href empty) is null. */ Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java 2017-12-30 20:13:13 UTC (rev 15051) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java 2017-12-31 11:20:00 UTC (rev 15052) @@ -18,6 +18,7 @@ import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.QUERYSELECTORALL_NOT_IN_QUIRKS; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.QUERYSELECTORALL_NO_TARGET; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.QUERYSELECTOR_CSS3_PSEUDO_REQUIRE_ATTACHED_NODE; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.STYLESHEET_ADD_RULE_RETURNS_POS; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.STYLESHEET_HREF_EMPTY_IS_NULL; import static com.gargoylesoftware.htmlunit.html.DomElement.ATTRIBUTE_NOT_DEFINED; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME; @@ -1106,6 +1107,19 @@ return result; } catch (final DOMException e) { + // in case of error try with an empty rule + final int pos = rule.indexOf('{'); + if (pos > -1) { + final String newRule = rule.substring(0, pos) + "{}"; + try { + final int result = wrapped_.insertRule(newRule, fixIndex(position)); + refreshCssRules(); + return result; + } + catch (final DOMException ex) { + throw Context.throwAsScriptRuntimeEx(ex); + } + } throw Context.throwAsScriptRuntimeEx(e); } } @@ -1186,7 +1200,6 @@ // in case of error try with an empty rule completeRule = selector + " {}"; try { - initCssRules(); wrapped_.insertRule(completeRule, wrapped_.getCssRules().getLength()); refreshCssRules(); } @@ -1194,6 +1207,9 @@ throw Context.throwAsScriptRuntimeEx(ex); } } + if (getBrowserVersion().hasFeature(STYLESHEET_ADD_RULE_RETURNS_POS)) { + return wrapped_.getCssRules().getLength() - 1; + } return -1; } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java 2017-12-30 20:13:13 UTC (rev 15051) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheetTest.java 2017-12-31 11:20:00 UTC (rev 15052) @@ -191,27 +191,30 @@ * @throws Exception if an error occurs */ @Test - @Alerts(DEFAULT = {"1", "false", "false", "0", "2", "p", "vertical-align: top;"}, - FF = {"1", "false", "true", "0", "2", "p", "vertical-align: top;"}) - public void addRule_insertRule() throws Exception { - final String html = "<html><head><title>foo</title><script>\n" - + "function doTest() {\n" - + " var f = document.getElementById('myStyle');\n" - + " var s = f.sheet ? f.sheet : f.styleSheet;\n" - + " var rules = s.cssRules || s.rules;\n" - + " alert(rules.length);\n" - + " alert(s.insertRule == undefined);\n" - + " alert(s.addRule == undefined);\n" - + " if (s.insertRule)\n" - + " alert(s.insertRule('div { color: red; }', 0));\n" - + " else\n" - + " alert(s.addRule('div', 'color: red;'));\n" - + " alert(rules.length);\n" - + " alert(rules[1].selectorText);\n" - + " alert(rules[1].style.cssText);\n" - + "}</script>\n" + @Alerts(DEFAULT = {"1", "false", "-1", "div", "color: red;", "2"}, + IE = {"1", "false", "1", "div", "color: red;", "2"}, + FF = {"1", "true", "1"}) + public void addRule() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + "<script>\n" + + " function doTest() {\n" + + " var f = document.getElementById('myStyle');\n" + + " var s = f.sheet ? f.sheet : f.styleSheet;\n" + + " var rules = s.cssRules || s.rules;\n" + + " alert(rules.length);\n" + + " alert(s.addRule == undefined);\n" + + " if (s.addRule) {\n" + + " alert(s.addRule('div', 'color: red;'));\n" + + " alert(rules[rules.length - 1].selectorText);\n" + + " alert(rules[rules.length - 1].style.cssText);\n" + + " }\n" + + " alert(rules.length);\n" + + " }\n" + + "</script>\n" + "<style id='myStyle'>p { vertical-align:top }</style>\n" - + "</head><body onload='doTest()'>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + "</body></html>"; loadPageWithAlerts2(html); @@ -218,13 +221,12 @@ } /** - * Minimal test for addRule / insertRule. * @throws Exception if an error occurs */ @Test - @Alerts(DEFAULT = {"1", "-1", "div", "", "2"}, - IE = {"1", "1", "div", "", "2"}, - FF = {"1", "1"}) + @Alerts(DEFAULT = {"2", "-1", "div", "", "3"}, + IE = {"2", "2", "div", "", "3"}, + FF = {"2", "2"}) public void addRuleInvalidRule() throws Exception { final String html = "<html>\n" + "<head>\n" @@ -242,7 +244,7 @@ + " alert(rules.length);\n" + " }\n" + " </script>\n" - + " <style id='myStyle'>p { vertical-align:top }</style>\n" + + " <style id='myStyle'>p { vertical-align: top } h1 { color: blue; }</style>\n" + "</head>\n" + "<body onload='doTest()'>\n" + "</body></html>"; @@ -251,6 +253,120 @@ } /** + * Test that exception handling in addRule. + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "exception", + FF = "added") + public void addInvalidRule() throws Exception { + final String html = "<html><head><title>foo</title><script>\n" + + "function doTest() {\n" + + " var f = document.getElementById('myStyle');\n" + + " var s = f.sheet ? f.sheet : f.styleSheet;\n" + + " var rules = s.cssRules || s.rules;\n" + + " try {\n" + + " if (s.addRule)\n" + + " s.addRule('.testStyle1;', '', 1);\n" + + " alert('added');\n" + + " } catch(err) { alert('exception'); }\n" + + "}</script>\n" + + "<style id='myStyle'></style>\n" + + "</head><body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * Minimal test for insertRule. + * @throws Exception if an error occurs + */ + @Test + @Alerts({"1", "false", "0", "div", "color: red;", "2"}) + public void insertRule() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + "<script>\n" + + " function doTest() {\n" + + " var f = document.getElementById('myStyle');\n" + + " var s = f.sheet ? f.sheet : f.styleSheet;\n" + + " var rules = s.cssRules || s.rules;\n" + + " alert(rules.length);\n" + + " alert(s.insertRule == undefined);\n" + + " if (s.insertRule) {\n" + + " alert(s.insertRule('div { color: red; }', 0));\n" + + " alert(rules[0].selectorText);\n" + + " alert(rules[0].style.cssText);\n" + + " }\n" + + " alert(rules.length);\n" + + " }\n" + + "</script>\n" + + "<style id='myStyle'>p { vertical-align:top }</style>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts({"1", "false", "0", "div", "", "2"}) + public void insertRuleInvalidRule() throws Exception { + final String html = "<html>\n" + + "<head>\n" + + "<script>\n" + + " function doTest() {\n" + + " var f = document.getElementById('myStyle');\n" + + " var s = f.sheet ? f.sheet : f.styleSheet;\n" + + " var rules = s.cssRules || s.rules;\n" + + " alert(rules.length);\n" + + " alert(s.insertRule == undefined);\n" + + " if (s.insertRule) {\n" + + " alert(s.insertRule('div {invalid}', 0));\n" + + " alert(rules[0].selectorText);\n" + + " alert(rules[0].style.cssText);\n" + + " }\n" + + " alert(rules.length);\n" + + " }\n" + + "</script>\n" + + "<style id='myStyle'>p { vertical-align:top }</style>\n" + + "</head>\n" + + "<body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * Test that exception handling in insertRule. + * @throws Exception if an error occurs + */ + @Test + @Alerts("exception") + public void insertInvalidRule() throws Exception { + final String html = "<html><head><title>foo</title><script>\n" + + "function doTest() {\n" + + " var f = document.getElementById('myStyle');\n" + + " var s = f.sheet ? f.sheet : f.styleSheet;\n" + + " var rules = s.cssRules || s.rules;\n" + + " try {\n" + + " if (s.insertRule)\n" + + " s.insertRule('.testStyle1', 0);\n" + + " alert('inserted');\n" + + " } catch(err) { alert('exception'); }\n" + + "}</script>\n" + + "<style id='myStyle'></style>\n" + + "</head><body onload='doTest()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** * Minimal test for removeRule / deleteRule. * @throws Exception if an error occurs */ @@ -406,33 +522,6 @@ } /** - * Test that exception handling in insertRule. - * @throws Exception if an error occurs - */ - @Test - @Alerts("exception") - public void insertInvalidRule() throws Exception { - final String html = "<html><head><title>foo</title><script>\n" - + "function doTest() {\n" - + " var f = document.getElementById('myStyle');\n" - + " var s = f.sheet ? f.sheet : f.styleSheet;\n" - + " var rules = s.cssRules || s.rules;\n" - + " try {\n" - + " if (s.insertRule)\n" - + " s.insertRule('.testStyle1', 0);\n" - + " else\n" - + " s.addRule('.testStyle1;', '', 1);\n" - + " alert('inserted');\n" - + " } catch(err) { alert('exception'); }\n" - + "}</script>\n" - + "<style id='myStyle'></style>\n" - + "</head><body onload='doTest()'>\n" - + "</body></html>"; - - loadPageWithAlerts2(html); - } - - /** * @throws Exception on test failure */ @Test |
From: <rb...@us...> - 2017-12-31 16:53:46
|
Revision: 15053 http://sourceforge.net/p/htmlunit/code/15053 Author: rbri Date: 2017-12-31 16:53:44 +0000 (Sun, 31 Dec 2017) Log Message: ----------- Invalid 'Origin' header was sent as part of XMLHttpRequest if the request url was absolute and the page contains a base tag Issue 1944 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest2Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2017-12-31 11:20:00 UTC (rev 15052) +++ trunk/htmlunit/src/changes/changes.xml 2017-12-31 16:53:44 UTC (rev 15053) @@ -8,6 +8,10 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes"> + <action type="fix" dev="rbri" issue="1944"> + JavaScript: Invalid 'Origin' header was sent as part of XMLHttpRequest + if the request url was absolute and the page contains a base tag + </action> <action type="fix" dev="rbri" issue="1943"> JavaScript: CSSStyleSheet#addRule fixed error handling </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2017-12-31 11:20:00 UTC (rev 15052) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2017-12-31 16:53:44 UTC (rev 15053) @@ -679,8 +679,6 @@ * @exception MalformedURLException if an error occurred when creating a URL object */ public URL getFullyQualifiedUrl(String relativeUrl) throws MalformedURLException { - final URL baseUrl = getBaseURL(); - // to handle http: and http:/ in FF (Bug #474) if (hasFeature(URL_MISSING_SLASHES)) { boolean incorrectnessNotified = false; @@ -693,7 +691,7 @@ } } - return WebClient.expandUrl(baseUrl, relativeUrl); + return WebClient.expandUrl(getBaseURL(), relativeUrl); } /** Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest.java 2017-12-31 11:20:00 UTC (rev 15052) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest.java 2017-12-31 16:53:44 UTC (rev 15053) @@ -527,8 +527,8 @@ containingPage_ = (HtmlPage) getWindow().getWebWindow().getEnclosedPage(); try { + final URL pageRequestUrl = containingPage_.getUrl(); final URL fullUrl = containingPage_.getFullyQualifiedUrl(url); - final URL originUrl = containingPage_.getFullyQualifiedUrl(""); if (!isAllowCrossDomainsFor(fullUrl)) { throw Context.reportRuntimeError("Access to restricted URI denied"); } @@ -537,11 +537,11 @@ request.setCharset(UTF_8); request.setAdditionalHeader(HttpHeader.REFERER, containingPage_.getUrl().toExternalForm()); - if (!isSameOrigin(originUrl, fullUrl)) { - final StringBuilder origin = new StringBuilder().append(originUrl.getProtocol()).append("://") - .append(originUrl.getHost()); - if (originUrl.getPort() != -1) { - origin.append(':').append(originUrl.getPort()); + if (!isSameOrigin(pageRequestUrl, fullUrl)) { + final StringBuilder origin = new StringBuilder().append(pageRequestUrl.getProtocol()).append("://") + .append(pageRequestUrl.getHost()); + if (pageRequestUrl.getPort() != -1) { + origin.append(':').append(pageRequestUrl.getPort()); } request.setAdditionalHeader(HttpHeader.ORIGIN, origin.toString()); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest2Test.java 2017-12-31 11:20:00 UTC (rev 15052) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest2Test.java 2017-12-31 16:53:44 UTC (rev 15053) @@ -40,12 +40,13 @@ import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.openqa.selenium.WebDriver; import com.gargoylesoftware.htmlunit.BrowserRunner; -import com.gargoylesoftware.htmlunit.HttpHeader; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; import com.gargoylesoftware.htmlunit.BrowserRunner.BuggyWebDriver; import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented; +import com.gargoylesoftware.htmlunit.HttpHeader; import com.gargoylesoftware.htmlunit.WebDriverTestCase; import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.javascript.host.xml.XMLHttpRequestTest.BasicAuthenticationServlet; @@ -642,6 +643,136 @@ loadPageWithAlerts2(html); } + /** + * Test the correct origin header. + * @throws Exception if the test fails. + */ + @Test + @Alerts({"ok", "4", "<null>"}) + public void baseUrlAbsoluteRequest() throws Exception { + final String html = "<html><head>\n" + + "<base href='" + URL_CROSS_ORIGIN_BASE + "'>\n" + + "<script>\n" + + "function test() {\n" + + " var xhr = new XMLHttpRequest();\n" + + " try {\n" + + " xhr.open('GET', '" + URL_SECOND + "', false);\n" + + " alert('ok');\n" + + " xhr.send();\n" + + " alert(xhr.readyState);\n" + + " } catch(e) { alert('exception'); }\n" + + "}\n" + + "</script>\n" + + "</head>\n" + + "<body onload='test()'></body></html>"; + + final List<NameValuePair> responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("access-control-allow-origin", "*")); + getMockWebConnection().setResponse(URL_SECOND, + "<empty/>", + 200, + "OK", + "text/xml", + UTF_8, responseHeaders); + + final WebDriver driver = loadPage2(html); + verifyAlerts(driver, Arrays.copyOfRange(getExpectedAlerts(), 0, 2)); + + final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders(); + String origin = lastAdditionalHeaders.get(HttpHeader.ORIGIN); + if (origin == null) { + origin = "<null>"; + } + assertEquals(getExpectedAlerts()[2], origin); + } + + /** + * Test the correct origin header. + * @throws Exception if the test fails. + */ + @Test + @Alerts(DEFAULT = {"ok", "4", "http://localhost:12345"}, + IE = {"ok", "4", "<null>"}) + public void baseUrlAbsoluteRequestOtherUrl() throws Exception { + final String html = "<html><head>\n" + + "<base href='" + URL_CROSS_ORIGIN_BASE + "'>\n" + + "<script>\n" + + "function test() {\n" + + " var xhr = new XMLHttpRequest();\n" + + " try {\n" + + " xhr.open('GET', '" + URL_CROSS_ORIGIN2 + "', false);\n" + + " alert('ok');\n" + + " xhr.send();\n" + + " alert(xhr.readyState);\n" + + " } catch(e) { alert('exception'); }\n" + + "}\n" + + "</script>\n" + + "</head>\n" + + "<body onload='test()'></body></html>"; + + final List<NameValuePair> responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("access-control-allow-origin", "*")); + getMockWebConnection().setResponse(URL_CROSS_ORIGIN2, + "<empty/>", + 200, + "OK", + "text/xml", + UTF_8, responseHeaders); + + final WebDriver driver = loadPage2(html); + verifyAlerts(driver, Arrays.copyOfRange(getExpectedAlerts(), 0, 2)); + + final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders(); + String origin = lastAdditionalHeaders.get(HttpHeader.ORIGIN); + if (origin == null) { + origin = "<null>"; + } + assertEquals(getExpectedAlerts()[2], origin); + } + + /** + * Test the correct origin header. + * @throws Exception if the test fails. + */ + @Test + @Alerts(DEFAULT = {"ok", "4", "http://localhost:12345"}, + IE = {"ok", "4", "<null>"}) + public void baseUrlRelativeRequest() throws Exception { + final String html = "<html><head>\n" + + "<base href='" + URL_CROSS_ORIGIN_BASE + "'>\n" + + "<script>\n" + + "function test() {\n" + + " var xhr = new XMLHttpRequest();\n" + + " try {\n" + + " xhr.open('GET', 'corsAllowAll', false);\n" + + " alert('ok');\n" + + " xhr.send();\n" + + " alert(xhr.readyState);\n" + + " } catch(e) { alert('exception ' + e); }\n" + + "}\n" + + "</script>\n" + + "</head>\n" + + "<body onload='test()'></body></html>"; + + final List<NameValuePair> responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("access-control-allow-origin", "*")); + getMockWebConnection().setResponse(new URL(URL_CROSS_ORIGIN_BASE, "/corsAllowAll"), + "<empty/>", + 200, + "OK", + "text/xml", + UTF_8, responseHeaders); + final WebDriver driver = loadPage2(html); + verifyAlerts(driver, Arrays.copyOfRange(getExpectedAlerts(), 0, 2)); + + final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders(); + String origin = lastAdditionalHeaders.get(HttpHeader.ORIGIN); + if (origin == null) { + origin = "<null>"; + } + assertEquals(getExpectedAlerts()[2], origin); + } + @Override protected boolean needThreeConnections() { return true; |
From: <rb...@us...> - 2018-01-01 19:03:29
|
Revision: 15056 http://sourceforge.net/p/htmlunit/code/15056 Author: rbri Date: 2018-01-01 19:03:26 +0000 (Mon, 01 Jan 2018) Log Message: ----------- latest ff52 ESR Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/NavigatorTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java 2018-01-01 12:07:11 UTC (rev 15055) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java 2018-01-01 19:03:26 UTC (rev 15056) @@ -153,7 +153,7 @@ // FF52 FIREFOX_52.applicationVersion_ = "5.0 (Windows)"; FIREFOX_52.userAgent_ = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0"; - FIREFOX_52.buildId_ = "20171206101620"; + FIREFOX_52.buildId_ = "20171226003912"; FIREFOX_52.productSub_ = "20100101"; FIREFOX_52.headerNamesOrdered_ = new String[] { HttpHeader.HOST, Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/NavigatorTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/NavigatorTest.java 2018-01-01 12:07:11 UTC (rev 15055) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/NavigatorTest.java 2018-01-01 19:03:26 UTC (rev 15056) @@ -387,7 +387,7 @@ @Test @Alerts(DEFAULT = "undefined", FF45 = "20170411115307", - FF52 = "20171206101620") + FF52 = "20171226003912") public void buildID() throws Exception { final String html = "<html><head><title>First</title>\n" |
From: <rb...@us...> - 2018-01-02 19:14:49
|
Revision: 15057 http://sourceforge.net/p/htmlunit/code/15057 Author: rbri Date: 2018-01-02 19:14:46 +0000 (Tue, 02 Jan 2018) Log Message: ----------- URLSearchParams implementation finished (entries(), keys(), values()) URLSearchParams parser fixed (handling of '=' as first char of a part) Issue 1931 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParams.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParamsTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-01 19:03:26 UTC (rev 15056) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-02 19:14:46 UTC (rev 15057) @@ -7,7 +7,13 @@ </properties> <body> - <release version="2.30" date="xx, 2018" description="Bugfixes"> + <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented"> + <action type="add" dev="rbri"> + JavaScript: URLSearchParams implementation finished (entries(), keys(), values()). + </action> + <action type="fix" dev="rbri"> + JavaScript: URLSearchParams parser fixed (handling of '=' as first char of a part). + </action> <action type="fix" dev="rbri" issue="1944"> JavaScript: Invalid 'Origin' header was sent as part of XMLHttpRequest if the request url was absolute and the page contains a base tag Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParams.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParams.java 2018-01-01 19:03:26 UTC (rev 15056) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParams.java 2018-01-02 19:14:46 UTC (rev 15057) @@ -18,6 +18,7 @@ import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF; import java.util.AbstractMap; +import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -33,6 +34,7 @@ import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.NativeArray; import net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime; +import net.sourceforge.htmlunit.corejs.javascript.Scriptable; import net.sourceforge.htmlunit.corejs.javascript.TopLevel; import net.sourceforge.htmlunit.corejs.javascript.Undefined; @@ -46,6 +48,9 @@ @JsxClass({CHROME, FF}) public class URLSearchParams extends SimpleScriptable { + private static final String ITERATOR_NAME = "URLSearchParamsIterator"; + private static com.gargoylesoftware.htmlunit.javascript.host.Iterator ITERATOR_PROTOTYPE_; + private final List<Entry<String, String>> params_ = new LinkedList<>(); /** @@ -88,7 +93,7 @@ private Entry<String, String> splitQueryParameter(final String singleParam) { final int idx = singleParam.indexOf('='); - if (idx > 0) { + if (idx > -1) { final String key = singleParam.substring(0, idx); String value = null; if (idx < singleParam.length()) { @@ -217,6 +222,69 @@ } /** + * The URLSearchParams.entries() method returns an iterator allowing to go through + * all key/value pairs contained in this object. The key and value of each pair + * are USVString objects. + * + * @return an iterator. + */ + @JsxFunction + public Object entries() { + final SimpleScriptable object = + new com.gargoylesoftware.htmlunit.javascript.host.Iterator(ITERATOR_NAME, params_.iterator()); + object.setParentScope(getParentScope()); + setIteratorPrototype(object); + return object; + } + + /** + * The URLSearchParams.keys() method returns an iterator allowing to go through + * all keys contained in this object. The keys are USVString objects. + * + * @return an iterator. + */ + @JsxFunction + public Object keys() { + final List<String> keys = new ArrayList<>(params_.size()); + for (Entry<String, String> entry : params_) { + keys.add(entry.getKey()); + } + + final SimpleScriptable object = + new com.gargoylesoftware.htmlunit.javascript.host.Iterator(ITERATOR_NAME, keys.iterator()); + object.setParentScope(getParentScope()); + setIteratorPrototype(object); + return object; + } + + /** + * The URLSearchParams.values() method returns an iterator allowing to go through + * all values contained in this object. The values are USVString objects. + * + * @return an iterator. + */ + @JsxFunction + public Object values() { + final List<String> values = new ArrayList<>(params_.size()); + for (Entry<String, String> entry : params_) { + values.add(entry.getValue()); + } + + final SimpleScriptable object = + new com.gargoylesoftware.htmlunit.javascript.host.Iterator(ITERATOR_NAME, values.iterator()); + object.setParentScope(getParentScope()); + setIteratorPrototype(object); + return object; + } + + private static void setIteratorPrototype(final Scriptable scriptable) { + if (ITERATOR_PROTOTYPE_ == null) { + ITERATOR_PROTOTYPE_ = new com.gargoylesoftware.htmlunit.javascript.host.Iterator(ITERATOR_NAME, null); + } + scriptable.setPrototype(ITERATOR_PROTOTYPE_); + } + + /** * Calls for instance for implicit conversion to string. * @see com.gargoylesoftware.htmlunit.javascript.SimpleScriptable#getDefaultValue(java.lang.Class) * @param hint the type hint Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParamsTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParamsTest.java 2018-01-01 19:03:26 UTC (rev 15056) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/URLSearchParamsTest.java 2018-01-02 19:14:46 UTC (rev 15057) @@ -14,6 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host; +import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.CHROME; import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.FF45; import org.junit.Test; @@ -251,4 +252,133 @@ + "</html>"; loadPageWithAlerts2(html); } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = {"function keys() { [native code] }", "[object Iterator]", + "key1", "key2", "key1", "", "true"}, + FF = {"function keys() {\n [native code]\n}", "[object URLSearchParamsIterator]", + "key1", "key2", "key1", "", "true"}, + IE = {}) + @NotYetImplemented(CHROME) + public void keys() throws Exception { + final String html = + "<html>\n" + + "<head>\n" + + " <script>\n" + + " function test() {\n" + + " if (self.URLSearchParams) {\n" + + " var param = new URLSearchParams('key1=val1&key2=&key1=val3&=val4');\n" + + + " alert(param.keys);\n" + + " var iter = param.keys();\n" + + " alert(iter);\n" + + + " var entry = iter.next().value;\n" + + " alert(entry);\n" + + " entry = iter.next().value;\n" + + " alert(entry);\n" + + " entry = iter.next().value;\n" + + " alert(entry);\n" + + " entry = iter.next().value;\n" + + " alert(entry);\n" + + + " alert(iter.next().done);\n" + + " }\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='test()'>\n" + + "</body>\n" + + "</html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = {"function values() { [native code] }", "[object Iterator]", + "val1", "", "val3", "val4", "true"}, + FF = {"function values() {\n [native code]\n}", "[object URLSearchParamsIterator]", + "val1", "", "val3", "val4", "true"}, + IE = {}) + @NotYetImplemented(CHROME) + public void values() throws Exception { + final String html = + "<html>\n" + + "<head>\n" + + " <script>\n" + + " function test() {\n" + + " if (self.URLSearchParams) {\n" + + " var param = new URLSearchParams('key1=val1&key2=&key1=val3&=val4');\n" + + + " alert(param.values);\n" + + " var iter = param.values();\n" + + " alert(iter);\n" + + + " var entry = iter.next().value;\n" + + " alert(entry);\n" + + " entry = iter.next().value;\n" + + " alert(entry);\n" + + " entry = iter.next().value;\n" + + " alert(entry);\n" + + " entry = iter.next().value;\n" + + " alert(entry);\n" + + + " alert(iter.next().done);\n" + + " }\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='test()'>\n" + + "</body>\n" + + "</html>"; + loadPageWithAlerts2(html, 666666); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = {"function entries() { [native code] }", "[object Iterator]", + "key1-val1", "key2-", "key1-val3", "-val4", "true"}, + FF = {"function entries() {\n [native code]\n}", "[object URLSearchParamsIterator]", + "key1-val1", "key2-", "key1-val3", "-val4", "true"}, + IE = {}) + @NotYetImplemented(CHROME) + public void entries() throws Exception { + final String html = + "<html>\n" + + "<head>\n" + + " <script>\n" + + " function test() {\n" + + " if (self.URLSearchParams) {\n" + + " var param = new URLSearchParams('key1=val1&key2=&key1=val3&=val4');\n" + + + " alert(param.entries);\n" + + " var iter = param.entries();\n" + + " alert(iter);\n" + + + " var entry = iter.next().value;\n" + + " alert(entry[0] + '-' + entry[1]);\n" + + " entry = iter.next().value;\n" + + " alert(entry[0] + '-' + entry[1]);\n" + + " entry = iter.next().value;\n" + + " alert(entry[0] + '-' + entry[1]);\n" + + " entry = iter.next().value;\n" + + " alert(entry[0] + '-' + entry[1]);\n" + + + " alert(iter.next().done);\n" + + " }\n" + + " }\n" + + " </script>\n" + + "</head>\n" + + "<body onload='test()'>\n" + + "</body>\n" + + "</html>"; + loadPageWithAlerts2(html); + } } |
From: <rb...@us...> - 2018-01-04 20:05:04
|
Revision: 15058 http://sourceforge.net/p/htmlunit/code/15058 Author: rbri Date: 2018-01-04 20:05:01 +0000 (Thu, 04 Jan 2018) Log Message: ----------- improve code based on spotbugs suggestions Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java trunk/htmlunit/src/main/java/netscape/javascript/JSObject.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/BrowserVersionFeaturesTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ExternalTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/NotYetImplementedTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebServerTestCase.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/general/HostTestsTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPage4Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/JQueryExtractor.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/SVN.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -100,7 +100,6 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpProcessorBuilder; -import org.apache.http.protocol.HttpRequestExecutor; import org.apache.http.protocol.RequestContent; import org.apache.http.protocol.RequestTargetHost; import org.apache.http.ssl.SSLContexts; @@ -1007,11 +1006,6 @@ publicSuffixMatcher = PublicSuffixMatcherLoader.getDefault(); } - HttpRequestExecutor requestExec = getField(builder, "requestExec"); - if (requestExec == null) { - requestExec = new HttpRequestExecutor(); - } - LayeredConnectionSocketFactory sslSocketFactory = getField(builder, "sslSocketFactory"); final SocketConfig defaultSocketConfig = getField(builder, "defaultSocketConfig"); final ConnectionConfig defaultConnectionConfig = getField(builder, "defaultConnectionConfig"); Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -383,7 +383,7 @@ final Attr result = super.setAttributeNode(attribute); - if ("src".equals(qualifiedName) && WebClient.ABOUT_BLANK != attributeValue) { + if ("src".equals(qualifiedName) && !WebClient.ABOUT_BLANK.equals(attributeValue)) { if (isAttachedToPage()) { loadSrc(); } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlArea.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -22,6 +22,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.util.Arrays; import java.util.Locale; import java.util.Map; @@ -288,7 +289,7 @@ } } catch (final NumberFormatException e) { - LOG.warn("Invalid rect coords '" + coords + "'", e); + LOG.warn("Invalid rect coords '" + Arrays.toString(coords) + "'", e); } final Rectangle2D rectangle = new Rectangle2D.Double(leftX, topY, @@ -332,7 +333,7 @@ } } catch (final NumberFormatException e) { - LOG.warn("Invalid poly coords '" + coords + "'", e); + LOG.warn("Invalid poly coords '" + Arrays.toString(coords) + "'", e); } path.closePath(); Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -3141,7 +3141,6 @@ || valueString.endsWith("mm") || valueString.endsWith("in") || valueString.endsWith("pc") - || valueString.endsWith("pc") || valueString.endsWith("ch") || valueString.endsWith("vh") || valueString.endsWith("vw")) { Modified: trunk/htmlunit/src/main/java/netscape/javascript/JSObject.java =================================================================== --- trunk/htmlunit/src/main/java/netscape/javascript/JSObject.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/main/java/netscape/javascript/JSObject.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -15,6 +15,7 @@ package netscape.javascript; import java.applet.Applet; +import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -62,7 +63,7 @@ */ public Object call(final String methodName, final Object[] args) throws JSException { if (LOG.isInfoEnabled()) { - LOG.info("JSObject call '" + methodName + "(" + args + ")'"); + LOG.info("JSObject call '" + methodName + "(" + Arrays.toString(args) + ")'"); } final Object jsResult = ScriptableObject.callMethod(scriptableObject_, methodName, args); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/BrowserVersionFeaturesTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/BrowserVersionFeaturesTest.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/BrowserVersionFeaturesTest.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -142,17 +142,20 @@ } private void unusedCheck(final File dir, final List<String> unusedFeatures) throws IOException { - for (final File file : dir.listFiles()) { - if (file.isDirectory() && !".svn".equals(file.getName())) { - unusedCheck(file, unusedFeatures); - } - else if (file.getName().endsWith(".java")) { - final List<String> lines = FileUtils.readLines(file, ISO_8859_1); - final String browserVersionFeatures = BrowserVersionFeatures.class.getSimpleName(); - for (final String line : lines) { - for (final Iterator<String> it = unusedFeatures.iterator(); it.hasNext();) { - if (line.contains(browserVersionFeatures + '.' + it.next())) { - it.remove(); + final File[] files = dir.listFiles(); + if (files != null) { + for (final File file : files) { + if (file.isDirectory() && !".svn".equals(file.getName())) { + unusedCheck(file, unusedFeatures); + } + else if (file.getName().endsWith(".java")) { + final List<String> lines = FileUtils.readLines(file, ISO_8859_1); + final String browserVersionFeatures = BrowserVersionFeatures.class.getSimpleName(); + for (final String line : lines) { + for (final Iterator<String> it = unusedFeatures.iterator(); it.hasNext();) { + if (line.contains(browserVersionFeatures + '.' + it.next())) { + it.remove(); + } } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -982,7 +982,12 @@ } private void testTests(final File dir) throws Exception { - for (final File file : dir.listFiles()) { + final File[] files = dir.listFiles(); + if (files == null) { + return; + } + + for (final File file : files) { if (file.isDirectory()) { if (!".svn".equals(file.getName())) { testTests(file); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ExternalTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ExternalTest.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ExternalTest.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -48,7 +48,7 @@ public class ExternalTest { /** Chrome driver. */ - static String CHROME_DRIVER_ = "2.34"; + static String CHROME_DRIVER_ = "2.33"; private static final DateFormat TEAM_CITY_FORMAT_ = new SimpleDateFormat("dd MMM yy HH:mm", Locale.ROOT); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/NotYetImplementedTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/NotYetImplementedTest.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/NotYetImplementedTest.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -47,23 +47,26 @@ } private void process(final File dir) throws IOException { - for (final File file : dir.listFiles()) { - final String fileName = file.getName(); - if (file.isDirectory() - && !"huge".equals(fileName) - && !".svn".equals(fileName)) { - process(file); - } - else { - if (fileName.endsWith(".java") - && !"SimpleWebTestCase.java".equals(fileName) - && !"NotYetImplementedTest.java".equals(fileName) - && !"CodeStyleTest.java".equals(fileName)) { - final List<String> lines = FileUtils.readLines(file, ISO_8859_1); - final String relativePath = file.getAbsolutePath().substring( - new File(".").getAbsolutePath().length() - 1).replace('\\', '/'); - process(lines, relativePath); + final File[] files = dir.listFiles(); + if (files != null) { + for (final File file : files) { + final String fileName = file.getName(); + if (file.isDirectory() + && !"huge".equals(fileName) + && !".svn".equals(fileName)) { + process(file); } + else { + if (fileName.endsWith(".java") + && !"SimpleWebTestCase.java".equals(fileName) + && !"NotYetImplementedTest.java".equals(fileName) + && !"CodeStyleTest.java".equals(fileName)) { + final List<String> lines = FileUtils.readLines(file, ISO_8859_1); + final String relativePath = file.getAbsolutePath().substring( + new File(".").getAbsolutePath().length() - 1).replace('\\', '/'); + process(lines, relativePath); + } + } } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -494,7 +494,7 @@ } LAST_TEST_MockWebConnection_ = Boolean.TRUE; if (STATIC_SERVER_ == null) { - STATIC_SERVER_ = new Server(PORT); + final Server server = new Server(PORT); final WebAppContext context = new WebAppContext(); context.setContextPath("/"); @@ -521,27 +521,30 @@ context.addFilter(AsciiEncodingFilter.class, "/*", EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST)); } - STATIC_SERVER_.setHandler(context); - STATIC_SERVER_.start(); + server.setHandler(context); + server.start(); + STATIC_SERVER_ = server; } MockWebConnectionServlet.MockConnection_ = mockConnection; if (STATIC_SERVER2_ == null && needThreeConnections()) { - STATIC_SERVER2_ = new Server(PORT2); + Server server = new Server(PORT2); final WebAppContext context2 = new WebAppContext(); context2.setContextPath("/"); context2.setResourceBase("./"); context2.addServlet(MockWebConnectionServlet.class, "/*"); - STATIC_SERVER2_.setHandler(context2); - STATIC_SERVER2_.start(); + server.setHandler(context2); + server.start(); + STATIC_SERVER2_ = server; - STATIC_SERVER3_ = new Server(PORT3); + server = new Server(PORT3); final WebAppContext context3 = new WebAppContext(); context3.setContextPath("/"); context3.setResourceBase("./"); context3.addServlet(MockWebConnectionServlet.class, "/*"); - STATIC_SERVER3_.setHandler(context3); - STATIC_SERVER3_.start(); + server.setHandler(context3); + server.start(); + STATIC_SERVER3_ = server; /* * The mock connection servlet call sit under both servers, so long as tests * keep the URLs distinct. Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebServerTestCase.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebServerTestCase.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebServerTestCase.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -319,7 +319,7 @@ } LAST_TEST_MockWebConnection_ = Boolean.TRUE; if (STATIC_SERVER_ == null) { - STATIC_SERVER_ = new Server(PORT); + final Server server = new Server(PORT); final WebAppContext context = new WebAppContext(); context.setContextPath("/"); @@ -341,8 +341,9 @@ } context.addServlet(MockWebConnectionServlet.class, "/*"); - STATIC_SERVER_.setHandler(context); - STATIC_SERVER_.start(); + server.setHandler(context); + server.start(); + STATIC_SERVER_ = server; } MockWebConnectionServlet.setMockconnection(mockConnection); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/general/HostTestsTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/general/HostTestsTest.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/general/HostTestsTest.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -72,16 +72,19 @@ } private void collectionObjectNames(final File dir, final Set<String> set) throws IOException { - for (final File file : dir.listFiles()) { - if (file.isDirectory() && !".svn".equals(file.getName())) { - collectionObjectNames(file, set); - } - else if (file.getName().endsWith(".java")) { - final List<String> lines = FileUtils.readLines(file, ISO_8859_1); - for (final String line : lines) { - final Matcher matcher = pattern_.matcher(line); - while (matcher.find()) { - set.add(matcher.group(1)); + final File[] files = dir.listFiles(); + if (files != null) { + for (final File file : files) { + if (file.isDirectory() && !".svn".equals(file.getName())) { + collectionObjectNames(file, set); + } + else if (file.getName().endsWith(".java")) { + final List<String> lines = FileUtils.readLines(file, ISO_8859_1); + for (final String line : lines) { + final Matcher matcher = pattern_.matcher(line); + while (matcher.find()) { + set.add(matcher.group(1)); + } } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPage4Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPage4Test.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPage4Test.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -202,6 +202,9 @@ return name.startsWith("htmlunit"); } }); + if (list == null) { + return 0; + } return list.length; } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/JQueryExtractor.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/JQueryExtractor.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/JQueryExtractor.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -157,12 +157,15 @@ } } final Map<String, Expectations> browserExpectations = new HashMap<>(); - for (final File file : dir.listFiles()) { - if (file.isFile() && file.getName().endsWith(".txt")) { - for (final TestedBrowser b : browsers) { - final String browserName = b.name(); - if (file.getName().equalsIgnoreCase("results." + browserName.replace('_', '.') + ".txt")) { - browserExpectations.put(browserName, Expectations.readExpectations(file)); + final File[] files = dir.listFiles(); + if (files != null) { + for (final File file : files) { + if (file.isFile() && file.getName().endsWith(".txt")) { + for (final TestedBrowser b : browsers) { + final String browserName = b.name(); + if (file.getName().equalsIgnoreCase("results." + browserName.replace('_', '.') + ".txt")) { + browserExpectations.put(browserName, Expectations.readExpectations(file)); + } } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/SVN.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/SVN.java 2018-01-02 19:14:46 UTC (rev 15057) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/source/SVN.java 2018-01-04 20:05:01 UTC (rev 15058) @@ -54,14 +54,17 @@ * @throws IOException if an exception happens */ public static void deleteSVN(final File dir) throws IOException { - for (final File f : dir.listFiles()) { - if (f.isDirectory()) { - if (".svn".equals(f.getName())) { - FileUtils.deleteDirectory(f); + final File[] files = dir.listFiles(); + if (files != null) { + for (final File f : files) { + if (f.isDirectory()) { + if (".svn".equals(f.getName())) { + FileUtils.deleteDirectory(f); + } + else { + deleteSVN(f); + } } - else { - deleteSVN(f); - } } } } @@ -72,18 +75,21 @@ * @throws IOException if an exception happens */ public static void consistentNewlines(final File dir) throws IOException { - for (final File f : dir.listFiles()) { - if (f.isDirectory()) { - if (!".svn".equals(f.getName())) { - consistentNewlines(f); + final File[] files = dir.listFiles(); + if (files != null) { + for (final File f : files) { + if (f.isDirectory()) { + if (!".svn".equals(f.getName())) { + consistentNewlines(f); + } } - } - else { - final String fileName = f.getName().toLowerCase(Locale.ROOT); - for (final String extension : EOL_EXTENSIONS_) { - if (fileName.endsWith(extension)) { - FileUtils.writeLines(f, FileUtils.readLines(f, ISO_8859_1)); - break; + else { + final String fileName = f.getName().toLowerCase(Locale.ROOT); + for (final String extension : EOL_EXTENSIONS_) { + if (fileName.endsWith(extension)) { + FileUtils.writeLines(f, FileUtils.readLines(f, ISO_8859_1)); + break; + } } } } |
From: <rb...@us...> - 2018-01-06 10:41:12
|
Revision: 15060 http://sourceforge.net/p/htmlunit/code/15060 Author: rbri Date: 2018-01-06 10:41:09 +0000 (Sat, 06 Jan 2018) Log Message: ----------- NPE in com.gargoylesoftware.htmlunit.html.HtmlPage.cleanUp() Issue 1946 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPageTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-06 08:48:43 UTC (rev 15059) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-06 10:41:09 UTC (rev 15060) @@ -8,6 +8,9 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented"> + <action type="fix" dev="rbri" issue="1946"> + NPE in com.gargoylesoftware.htmlunit.html.HtmlPage.cleanUp(). + </action> <action type="add" dev="rbri"> JavaScript: URLSearchParams implementation finished (entries(), keys(), values()). </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2018-01-06 08:48:43 UTC (rev 15059) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2018-01-06 10:41:09 UTC (rev 15060) @@ -331,9 +331,6 @@ cleaning_ = false; if (autoCloseableList_ != null) { for (final AutoCloseable closeable : new ArrayList<>(autoCloseableList_)) { - if (closeable == null) { - continue; - } try { closeable.close(); } @@ -2326,6 +2323,10 @@ * @param autoCloseable the autoclosable */ public void addAutoCloseable(final AutoCloseable autoCloseable) { + if (autoCloseable == null) { + return; + } + if (autoCloseableList_ == null) { autoCloseableList_ = new ArrayList<>(); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPageTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPageTest.java 2018-01-06 08:48:43 UTC (rev 15059) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlPageTest.java 2018-01-06 10:41:09 UTC (rev 15060) @@ -1902,6 +1902,17 @@ page.addAutoCloseable(new WebSocket()); } }); + page.cleanUp(); } + /** + * @exception Exception If the test fails + */ + @Test + public void addAutoCloseableNull() throws Exception { + final String html = ""; + final HtmlPage page = loadPage(html); + page.addAutoCloseable(null); + page.cleanUp(); + } } |
From: <rb...@us...> - 2018-01-15 20:16:05
|
Revision: 15079 http://sourceforge.net/p/htmlunit/code/15079 Author: rbri Date: 2018-01-15 20:16:02 +0000 (Mon, 15 Jan 2018) Log Message: ----------- Array.from() now supports user defined iterators also Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-13 16:57:54 UTC (rev 15078) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-15 20:16:02 UTC (rev 15079) @@ -9,6 +9,9 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented"> <action type="change" dev="rbri"> + JavaScript: Array.from() now supports user defined iterators also. + </action> + <action type="change" dev="rbri"> Samples on page Get Started updated. </action> <action type="fix" dev="rbri" issue="1946"> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java 2018-01-13 16:57:54 UTC (rev 15078) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java 2018-01-15 20:16:02 UTC (rev 15079) @@ -21,8 +21,11 @@ import net.sourceforge.htmlunit.corejs.javascript.BaseFunction; import net.sourceforge.htmlunit.corejs.javascript.Context; +import net.sourceforge.htmlunit.corejs.javascript.ES6Iterator; import net.sourceforge.htmlunit.corejs.javascript.Function; +import net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; +import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; import net.sourceforge.htmlunit.corejs.javascript.Undefined; /** @@ -48,7 +51,7 @@ final Object arrayLike = args[0]; Object[] array = null; if (arrayLike instanceof Scriptable) { - final Scriptable scriptable = (Scriptable) arrayLike; + Scriptable scriptable = (Scriptable) arrayLike; final Object length = scriptable.get("length", scriptable); if (length != Scriptable.NOT_FOUND) { final int size = (int) Context.toNumber(length); @@ -60,21 +63,52 @@ final Object iterator = scriptable.get(Symbol.ITERATOR_STRING, scriptable); if (iterator != Scriptable.NOT_FOUND) { - final List<Object> list = new ArrayList<>(); - final Iterator it = (Iterator) ((BaseFunction) iterator) + final Object obj = ((BaseFunction) iterator) .call(context, thisObj.getParentScope(), scriptable, new Object[0]); - SimpleScriptable next = it.next(); - boolean done = (boolean) next.get("done"); - Object value = next.get("value"); - while (!done) { - if (value != Undefined.instance) { - list.add(value); + + if (obj instanceof Iterator) { + final Iterator it = (Iterator) obj; + SimpleScriptable next = it.next(); + boolean done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + Object value = next.get(ES6Iterator.VALUE_PROPERTY); + + final List<Object> list = new ArrayList<>(); + while (!done) { + if (value != Undefined.instance) { + list.add(value); + } + next = it.next(); + done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + value = next.get(ES6Iterator.VALUE_PROPERTY); } - next = it.next(); - done = (boolean) next.get("done"); - value = next.get("value"); + array = list.toArray(); } - array = list.toArray(); + else if (obj instanceof Scriptable) { + scriptable = (Scriptable) obj; + // handle user defined iterator + final Object nextFunct = scriptable.get(ES6Iterator.NEXT_METHOD, (Scriptable) obj); + if (!(nextFunct instanceof BaseFunction)) { + throw ScriptRuntime.typeError("undefined is not a function"); + } + final Object nextObj = ((BaseFunction) nextFunct) + .call(context, thisObj.getParentScope(), scriptable, new Object[0]); + + ScriptableObject next = (ScriptableObject) nextObj; + boolean done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + Object value = next.get(ES6Iterator.VALUE_PROPERTY); + + final List<Object> list = new ArrayList<>(); + while (!done) { + if (value != Undefined.instance) { + list.add(value); + } + next = (ScriptableObject) ((BaseFunction) nextFunct) + .call(context, thisObj.getParentScope(), scriptable, new Object[0]); + done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + value = next.get(ES6Iterator.VALUE_PROPERTY); + } + array = list.toArray(); + } } } else if (arrayLike instanceof String) { Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java 2018-01-13 16:57:54 UTC (rev 15078) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/NativeArrayTest.java 2018-01-15 20:16:02 UTC (rev 15079) @@ -14,6 +14,8 @@ */ package com.gargoylesoftware.htmlunit.javascript; +import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.CHROME; +import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.FF; import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.FF45; import static com.gargoylesoftware.htmlunit.BrowserRunner.TestedBrowser.IE; @@ -27,8 +29,8 @@ import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented; +import com.gargoylesoftware.htmlunit.WebDriverTestCase; import com.gargoylesoftware.htmlunit.annotations.BuildServerDiscrepancy; -import com.gargoylesoftware.htmlunit.WebDriverTestCase; /** * Array is a native JavaScript object and therefore provided by Rhino but behavior should be @@ -307,6 +309,36 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = {"3", "a", "b", "c"}, + IE = "not supported") + @NotYetImplemented({CHROME, FF}) + public void fromArrayIterator() throws Exception { + final String html + = "<html>\n" + + "<head>\n" + + "<script>\n" + + " if (Array.from) {\n" + + " var input = ['a', 'b', 'c'];\n" + + " var arr = Array.from(input[Symbol.iterator]());\n" + + " alert(arr.length);\n" + + " for (var i = 0; i < arr.length; i++) {\n" + + " alert(arr[i]);\n" + + " }\n" + + " } else {\n" + + " alert('not supported');\n" + + " }\n" + + "</script>\n" + + "</head>\n" + + "<body>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(DEFAULT = {"2", "abc", "[object Window]"}, IE = "not supported") public void fromSet() throws Exception { @@ -365,9 +397,8 @@ * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = {"3", "1", "two", "3"}, + @Alerts(DEFAULT = {"1", "by"}, IE = "not supported") - @NotYetImplemented public void fromUserDefinedIterable() throws Exception { final String html = "<html>\n" @@ -375,11 +406,19 @@ + "<script>\n" + " if (Array.from) {\n" + " var myIterable = {};\n" - + " myIterable[Symbol.iterator] = function*() {\n" - + " yield 1;\n" - + " yield 'two';\n" - + " yield 3;\n" + + " myIterable[Symbol.iterator] = function() {\n" + + " return {\n" + + " next: function(){\n" + + " if (this._first) {;\n" + + " this._first = false;\n" + + " return { value: 'by', done: false };\n" + + " }\n" + + " return { done: true };\n" + + " },\n" + + " _first: true\n" + " };\n" + + " };\n" + + " var arr = Array.from(myIterable);\n" + " alert(arr.length);\n" + " for (var i = 0; i < arr.length; i++) {\n" @@ -400,6 +439,37 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = {"TypeError"}, + IE = "not supported") + public void fromObject() throws Exception { + final String html + = "<html>\n" + + "<head>\n" + + "<script>\n" + + " if (Array.from) {\n" + + " var myIterable = {};\n" + + " myIterable[Symbol.iterator] = function() {\n" + + " return { done: true };\n" + + " };\n" + + + " try {\n" + + " Array.from(myIterable);\n" + + " } catch(e) { alert('TypeError'); }\n" + + " } else {\n" + + " alert('not supported');\n" + + " }\n" + + "</script>\n" + + "</head>\n" + + "<body>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(DEFAULT = "0", IE = "not supported") public void fromNativeObject() throws Exception { @@ -428,6 +498,36 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = {"1", "abc"}, + IE = "not supported") + public void fromArguments() throws Exception { + final String html + = "<html>\n" + + "<head>\n" + + "<script>\n" + + " function test(a) { return Array.from(arguments); }\n" + + + " if (Array.from) {\n" + + " var arr = test('abc') \n" + + " alert(arr.length);\n" + + " for (var i = 0; i < arr.length; i++) {\n" + + " alert(arr[i]);\n" + + " }\n" + + " } else {\n" + + " alert('not supported');\n" + + " }\n" + + "</script>\n" + + "</head>\n" + + "<body>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts({"true", "true", "true", "true", "false", "false", "false", "false", "false", "false", "false", "false", "false"}) public void isArray() throws Exception { @@ -460,7 +560,9 @@ * @throws Exception if the test fails */ @Test - @Alerts({"function", "20"}) + @Alerts(DEFAULT = {"function", "20"}, + IE = "undefined") + @NotYetImplemented(IE) public void find() throws Exception { final String html = "<html>\n" @@ -470,7 +572,9 @@ + "\n" + " var arr = [1, 20, 7, 17];\n" + " alert(typeof arr.find);\n" - + " alert(arr.find(isBig));\n" + + " if (typeof arr.find == 'function') {\n" + + " alert(arr.find(isBig));\n" + + " }\n" + "</script>\n" + "</head>\n" + "<body>\n" @@ -483,7 +587,9 @@ * @throws Exception if the test fails */ @Test - @Alerts({"function", "20"}) + @Alerts(DEFAULT = {"function", "20"}, + IE = "undefined") + @NotYetImplemented(IE) public void findPrototype() throws Exception { final String html = "<html>\n" @@ -494,7 +600,9 @@ + " var arr = [1, 20, 7, 17];\n" + " var find = Array.prototype.find;\n" + " alert(typeof find);\n" - + " alert(find.call(arr, isBig));\n" + + " if (typeof find == 'function') {\n" + + " alert(find.call(arr, isBig));\n" + + " }\n" + "</script>\n" + "</head>\n" + "<body>\n" @@ -532,7 +640,9 @@ * @throws Exception if the test fails */ @Test - @Alerts({"function", "1"}) + @Alerts(DEFAULT = {"function", "1"}, + IE = "undefined") + @NotYetImplemented(IE) public void findIndex() throws Exception { final String html = "<html>\n" @@ -542,7 +652,9 @@ + "\n" + " var arr = [1, 20, 7, 17];\n" + " alert(typeof arr.findIndex);\n" - + " alert(arr.findIndex(isBig));\n" + + " if (typeof arr.findIndex == 'function') {\n" + + " alert(arr.findIndex(isBig));\n" + + " }\n" + "</script>\n" + "</head>\n" + "<body>\n" @@ -555,7 +667,9 @@ * @throws Exception if the test fails */ @Test - @Alerts({"function", "1"}) + @Alerts(DEFAULT = {"function", "1"}, + IE = "undefined") + @NotYetImplemented(IE) public void findIndexPrototype() throws Exception { final String html = "<html>\n" @@ -566,7 +680,9 @@ + " var arr = [1, 20, 7, 17];\n" + " var findIndex = Array.prototype.findIndex;\n" + " alert(typeof findIndex);\n" - + " alert(findIndex.call(arr, isBig));\n" + + " if (typeof findIndex == 'function') {\n" + + " alert(findIndex.call(arr, isBig));\n" + + " }\n" + "</script>\n" + "</head>\n" + "<body>\n" |
From: <rb...@us...> - 2018-01-17 20:04:41
|
Revision: 15081 http://sourceforge.net/p/htmlunit/code/15081 Author: rbri Date: 2018-01-17 20:04:38 +0000 (Wed, 17 Jan 2018) Log Message: ----------- Set and Map constructor now supports user defined iterators also Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Iterator.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MapTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-17 20:04:38 UTC (rev 15081) @@ -8,7 +8,10 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented"> - <action type="change" dev="rbri"> + <action type="add" dev="rbri"> + JavaScript: Set and Map constructor now supports user defined iterators also. + </action> + <action type="add" dev="rbri"> JavaScript: Array.from() now supports user defined iterators also. </action> <action type="change" dev="rbri"> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2018-01-17 20:04:38 UTC (rev 15081) @@ -1068,9 +1068,9 @@ @BrowserFeature(FF) JS_LOCATION_HREF_HASH_IS_ENCODED, - /** Map supports the argument constructor. */ - @BrowserFeature({CHROME, FF}) - JS_MAP_CONSTRUCTOR_ARGUMENT, + /** Map ignores the argument constructor. */ + @BrowserFeature(IE) + JS_MAP_CONSTRUCTOR_IGNORE_ARGUMENT, /** Indicates that an empty media list is represented by the string 'all'. */ @BrowserFeature(IE) @@ -1216,6 +1216,10 @@ @BrowserFeature(IE) JS_SELECT_SET_VALUES_CHECKS_ONLY_VALUE_ATTRIBUTE, + /** Set ignores the constructor argument. */ + @BrowserFeature(IE) + JS_SET_CONSTRUCTOR_IGNORE_ARGUMENT, + /** Whether to get any property from the items first. */ @BrowserFeature(IE) JS_STORAGE_GET_FROM_ITEMS, Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ArrayCustom.java 2018-01-17 20:04:38 UTC (rev 15081) @@ -17,15 +17,9 @@ import java.util.ArrayList; import java.util.List; -import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; - -import net.sourceforge.htmlunit.corejs.javascript.BaseFunction; import net.sourceforge.htmlunit.corejs.javascript.Context; -import net.sourceforge.htmlunit.corejs.javascript.ES6Iterator; import net.sourceforge.htmlunit.corejs.javascript.Function; -import net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; -import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; import net.sourceforge.htmlunit.corejs.javascript.Undefined; /** @@ -51,7 +45,7 @@ final Object arrayLike = args[0]; Object[] array = null; if (arrayLike instanceof Scriptable) { - Scriptable scriptable = (Scriptable) arrayLike; + final Scriptable scriptable = (Scriptable) arrayLike; final Object length = scriptable.get("length", scriptable); if (length != Scriptable.NOT_FOUND) { final int size = (int) Context.toNumber(length); @@ -60,55 +54,16 @@ array[i] = scriptable.get(i, scriptable); } } - - final Object iterator = scriptable.get(Symbol.ITERATOR_STRING, scriptable); - if (iterator != Scriptable.NOT_FOUND) { - final Object obj = ((BaseFunction) iterator) - .call(context, thisObj.getParentScope(), scriptable, new Object[0]); - - if (obj instanceof Iterator) { - final Iterator it = (Iterator) obj; - SimpleScriptable next = it.next(); - boolean done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); - Object value = next.get(ES6Iterator.VALUE_PROPERTY); - - final List<Object> list = new ArrayList<>(); - while (!done) { + else { + final List<Object> list = new ArrayList<>(); + if (Iterator.iterate(context, thisObj, scriptable, + value -> { if (value != Undefined.instance) { list.add(value); } - next = it.next(); - done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); - value = next.get(ES6Iterator.VALUE_PROPERTY); - } + })) { array = list.toArray(); } - else if (obj instanceof Scriptable) { - scriptable = (Scriptable) obj; - // handle user defined iterator - final Object nextFunct = scriptable.get(ES6Iterator.NEXT_METHOD, (Scriptable) obj); - if (!(nextFunct instanceof BaseFunction)) { - throw ScriptRuntime.typeError("undefined is not a function"); - } - final Object nextObj = ((BaseFunction) nextFunct) - .call(context, thisObj.getParentScope(), scriptable, new Object[0]); - - ScriptableObject next = (ScriptableObject) nextObj; - boolean done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); - Object value = next.get(ES6Iterator.VALUE_PROPERTY); - - final List<Object> list = new ArrayList<>(); - while (!done) { - if (value != Undefined.instance) { - list.add(value); - } - next = (ScriptableObject) ((BaseFunction) nextFunct) - .call(context, thisObj.getParentScope(), scriptable, new Object[0]); - done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); - value = next.get(ES6Iterator.VALUE_PROPERTY); - } - array = list.toArray(); - } } } else if (arrayLike instanceof String) { Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Iterator.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Iterator.java 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Iterator.java 2018-01-17 20:04:38 UTC (rev 15081) @@ -14,11 +14,16 @@ */ package com.gargoylesoftware.htmlunit.javascript.host; +import java.util.function.Consumer; + import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; +import net.sourceforge.htmlunit.corejs.javascript.BaseFunction; import net.sourceforge.htmlunit.corejs.javascript.Context; +import net.sourceforge.htmlunit.corejs.javascript.ES6Iterator; import net.sourceforge.htmlunit.corejs.javascript.FunctionObject; import net.sourceforge.htmlunit.corejs.javascript.NativeArray; +import net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; import net.sourceforge.htmlunit.corejs.javascript.Undefined; @@ -95,4 +100,65 @@ return object; } + /** + * Helper to support objects implementing the iterator interface. + * + * @param context the Context + * @param thisObj the this Object + * @param scriptable the scriptable + * @param processor the method to be called for every object + * @return true if @@iterator property was available + */ + public static boolean iterate(final Context context, + final Scriptable thisObj, + final Scriptable scriptable, + final Consumer<Object> processor) { + final Object iterator = scriptable.get(Symbol.ITERATOR_STRING, scriptable); + if (iterator == Scriptable.NOT_FOUND) { + return false; + } + + final Object obj = ((BaseFunction) iterator).call(context, thisObj.getParentScope(), scriptable, new Object[0]); + + if (obj instanceof Iterator) { + final Iterator it = (Iterator) obj; + SimpleScriptable next = it.next(); + boolean done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + Object value = next.get(ES6Iterator.VALUE_PROPERTY); + + while (!done) { + processor.accept(value); + + next = it.next(); + done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + value = next.get(ES6Iterator.VALUE_PROPERTY); + } + return true; + } + if (obj instanceof Scriptable) { + // handle user defined iterator + final Scriptable scriptableIterator = (Scriptable) obj; + final Object nextFunct = scriptableIterator.get(ES6Iterator.NEXT_METHOD, (Scriptable) obj); + if (!(nextFunct instanceof BaseFunction)) { + throw ScriptRuntime.typeError("undefined is not a function"); + } + final Object nextObj = ((BaseFunction) nextFunct) + .call(context, thisObj.getParentScope(), scriptableIterator, new Object[0]); + + ScriptableObject next = (ScriptableObject) nextObj; + boolean done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + Object value = next.get(ES6Iterator.VALUE_PROPERTY); + + while (!done) { + processor.accept(value); + + next = (ScriptableObject) ((BaseFunction) nextFunct) + .call(context, thisObj.getParentScope(), scriptableIterator, new Object[0]); + done = (boolean) next.get(ES6Iterator.DONE_PROPERTY); + value = next.get(ES6Iterator.VALUE_PROPERTY); + } + return true; + } + return false; + } } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java 2018-01-17 20:04:38 UTC (rev 15081) @@ -14,7 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host; -import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_MAP_CONSTRUCTOR_ARGUMENT; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_MAP_CONSTRUCTOR_IGNORE_ARGUMENT; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.EDGE; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF; @@ -40,6 +40,7 @@ * A JavaScript object for {@code Map}. * * @author Ahmed Ashour + * @author Ronald Brill */ @JsxClass public class Map extends SimpleScriptable { @@ -56,41 +57,91 @@ /** * Creates an instance. - * @param iterable an Array or other iterable object + * @param arrayLike an Array or other iterable object */ @JsxConstructor - public Map(final Object iterable) { - if (iterable != Undefined.instance) { - final Window window = (Window) ScriptRuntime.getTopCallScope(Context.getCurrentContext()); - if (window.getBrowserVersion().hasFeature(JS_MAP_CONSTRUCTOR_ARGUMENT)) { - if (iterable instanceof NativeArray) { - final NativeArray array = (NativeArray) iterable; - for (int i = 0; i < array.getLength(); i++) { - final Object entryObject = array.get(i); - if (entryObject instanceof NativeArray) { - final Object[] entry = toArray((NativeArray) entryObject); + public Map(final Object arrayLike) { + if (arrayLike == Undefined.instance) { + return; + } + + final Context context = Context.getCurrentContext(); + final Window window = (Window) ScriptRuntime.getTopCallScope(context); + if (window.getBrowserVersion().hasFeature(JS_MAP_CONSTRUCTOR_IGNORE_ARGUMENT)) { + return; + } + + if (arrayLike instanceof NativeArray) { + final NativeArray array = (NativeArray) arrayLike; + for (int i = 0; i < array.getLength(); i++) { + final Object entryObject = array.get(i); + if (entryObject instanceof NativeArray) { + final Object[] entry = toArray((NativeArray) entryObject); + if (entry.length > 0) { + final Object key = entry[0]; + final Object value = entry.length > 1 ? entry[1] : null; + set(key, value); + } + } + else { + throw Context.reportRuntimeError("TypeError: object is not iterable (" + + entryObject.getClass().getName() + ")"); + } + } + return; + } + + if (arrayLike instanceof Map) { + final Map map = (Map) arrayLike; + map_.putAll(map.map_); + return; + } + + if (arrayLike instanceof Scriptable) { + final Scriptable scriptable = (Scriptable) arrayLike; + final Object length = scriptable.get("length", scriptable); + if (length != Scriptable.NOT_FOUND) { + final int size = (int) Context.toNumber(length); + for (int i = 0; i < size; i++) { + final Object entryObject = scriptable.get(i, scriptable); + if (entryObject instanceof NativeArray) { + final Object[] entry = toArray((NativeArray) entryObject); + if (entry.length > 0) { + final Object key = entry[0]; + final Object value = entry.length > 1 ? entry[1] : null; + set(key, value); + } + } + else { + throw Context.reportRuntimeError("TypeError: object is not iterable (" + + entryObject.getClass().getName() + ")"); + } + } + return; + } + + if (Iterator.iterate(context, this, scriptable, + value -> { + if (value != Undefined.instance) { + if (value instanceof NativeArray) { + final Object[] entry = toArray((NativeArray) value); if (entry.length > 0) { - final Object key = entry[0]; - final Object value = entry.length > 1 ? entry[1] : null; - set(key, value); + final Object entryKey = entry[0]; + final Object entryValue = entry.length > 1 ? entry[1] : null; + set(entryKey, entryValue); } } else { throw Context.reportRuntimeError("TypeError: object is not iterable (" - + entryObject.getClass().getName() + ")"); + + value.getClass().getName() + ")"); } } - } - else if (iterable instanceof Map) { - final Map map = (Map) iterable; - map_.putAll(map.map_); - } - else { - throw Context.reportRuntimeError("TypeError: object is not iterable (" - + iterable.getClass().getName() + ")"); - } + })) { + return; } } + + throw Context.reportRuntimeError("TypeError: object is not iterable (" + arrayLike.getClass().getName() + ")"); } /** @@ -245,19 +296,21 @@ */ @JsxFunction public void forEach(final Function callback, final Object thisArg) { - if (getBrowserVersion().hasFeature(JS_MAP_CONSTRUCTOR_ARGUMENT)) { - final Scriptable thisArgument; - if (thisArg instanceof Scriptable) { - thisArgument = (Scriptable) thisArg; - } - else { - thisArgument = getWindow(); - } - for (final java.util.Map.Entry<Object, Object> entry : map_.entrySet()) { - callback.call(Context.getCurrentContext(), getParentScope(), thisArgument, - new Object[] {entry.getValue(), entry.getKey(), this}); - } + if (getBrowserVersion().hasFeature(JS_MAP_CONSTRUCTOR_IGNORE_ARGUMENT)) { + return; } + + final Scriptable thisArgument; + if (thisArg instanceof Scriptable) { + thisArgument = (Scriptable) thisArg; + } + else { + thisArgument = getWindow(); + } + + for (final java.util.Map.Entry<Object, Object> entry : map_.entrySet()) { + callback.call(Context.getCurrentContext(), getParentScope(), thisArgument, + new Object[] {entry.getValue(), entry.getKey(), this}); + } } - } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java 2018-01-17 20:04:38 UTC (rev 15081) @@ -14,7 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host; -import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_MAP_CONSTRUCTOR_ARGUMENT; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_SET_CONSTRUCTOR_IGNORE_ARGUMENT; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.EDGE; import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF; @@ -41,6 +41,7 @@ * A JavaScript object for {@code Set}. * * @author Ahmed Ashour + * @author Ronald Brill */ @JsxClass public class Set extends SimpleScriptable { @@ -61,48 +62,70 @@ */ @JsxConstructor public Set(final Object iterable) { - if (iterable != Undefined.instance) { - final Window window = (Window) ScriptRuntime.getTopCallScope(Context.getCurrentContext()); - if (window.getBrowserVersion().hasFeature(JS_MAP_CONSTRUCTOR_ARGUMENT)) { - if (iterable instanceof NativeArray) { - final NativeArray array = (NativeArray) iterable; - for (int i = 0; i < array.getLength(); i++) { - add(ScriptableObject.getProperty(array, i)); - } - } - else if (iterable instanceof ArrayBufferViewBase) { - final ArrayBufferViewBase array = (ArrayBufferViewBase) iterable; - for (int i = 0; i < array.getLength(); i++) { - add(ScriptableObject.getProperty(array, i)); - } - } - else if (iterable instanceof String) { - final String string = (String) iterable; - for (int i = 0; i < string.length(); i++) { - add(String.valueOf(string.charAt(i))); - } - } - else if (iterable instanceof Set) { - final Set set = (Set) iterable; - for (Object object : set.set_) { - add(object); - } - } - else if (iterable instanceof Map) { - final Iterator iterator = (Iterator) ((Map) iterable).entries(); + if (iterable == Undefined.instance) { + return; + } + final Window window = (Window) ScriptRuntime.getTopCallScope(Context.getCurrentContext()); + if (window.getBrowserVersion().hasFeature(JS_SET_CONSTRUCTOR_IGNORE_ARGUMENT)) { + return; + } - SimpleScriptable object = iterator.next(); - while (Undefined.instance != object.get("value", null)) { - add(object); - object = iterator.next(); + if (iterable instanceof NativeArray) { + final NativeArray array = (NativeArray) iterable; + for (int i = 0; i < array.getLength(); i++) { + add(ScriptableObject.getProperty(array, i)); + } + return; + } + + if (iterable instanceof ArrayBufferViewBase) { + final ArrayBufferViewBase array = (ArrayBufferViewBase) iterable; + for (int i = 0; i < array.getLength(); i++) { + add(ScriptableObject.getProperty(array, i)); + } + return; + } + + if (iterable instanceof String) { + final String string = (String) iterable; + for (int i = 0; i < string.length(); i++) { + add(String.valueOf(string.charAt(i))); + } + return; + } + + if (iterable instanceof Set) { + final Set set = (Set) iterable; + for (Object object : set.set_) { + add(object); + } + return; + } + + if (iterable instanceof Map) { + final Iterator iterator = (Iterator) ((Map) iterable).entries(); + + SimpleScriptable object = iterator.next(); + while (Undefined.instance != object.get("value", null)) { + add(object); + object = iterator.next(); + } + return; + } + + if (iterable instanceof Scriptable) { + final Scriptable scriptable = (Scriptable) iterable; + if (Iterator.iterate(Context.getCurrentContext(), this, scriptable, + value -> { + if (value != Undefined.instance) { + add(value); } - } - else { - throw Context.reportRuntimeError("TypeError: object is not iterable (" - + iterable.getClass().getName() + ")"); - } + })) { + return; } } + + throw Context.reportRuntimeError("TypeError: object is not iterable (" + iterable.getClass().getName() + ")"); } /** @@ -198,19 +221,20 @@ */ @JsxFunction public void forEach(final Function callback, final Object thisArg) { - if (getBrowserVersion().hasFeature(JS_MAP_CONSTRUCTOR_ARGUMENT)) { - final Scriptable thisArgument; - if (thisArg instanceof Scriptable) { - thisArgument = (Scriptable) thisArg; - } - else { - thisArgument = getWindow(); - } - for (final Object object : set_) { - callback.call(Context.getCurrentContext(), getParentScope(), thisArgument, - new Object[] {object, object, this}); - } + if (getBrowserVersion().hasFeature(JS_SET_CONSTRUCTOR_IGNORE_ARGUMENT)) { + return; } + + final Scriptable thisArgument; + if (thisArg instanceof Scriptable) { + thisArgument = (Scriptable) thisArg; + } + else { + thisArgument = getWindow(); + } + for (final Object object : set_) { + callback.call(Context.getCurrentContext(), getParentScope(), thisArgument, + new Object[] {object, object, this}); + } } - } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MapTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MapTest.java 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MapTest.java 2018-01-17 20:04:38 UTC (rev 15081) @@ -31,6 +31,7 @@ * Tests for {@link Map}. * * @author Ahmed Ashour + * @author Ronald Brill */ @RunWith(BrowserRunner.class) public class MapTest extends WebDriverTestCase { @@ -209,9 +210,28 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = "2", + IE = "0") + public void constructorArray() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " var myMap = new Map([[ 1, 'one' ],[ 2, 'two' ]]);\n" + + " alert(myMap.size);\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(DEFAULT = "exception", IE = "0") - public void constructor() throws Exception { + public void constructorInt32Array() throws Exception { final String html = "<html><head><title>foo</title><script>\n" + "function test() {\n" @@ -300,6 +320,46 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = {"1", "77", "one"}, + IE = "exception") + public void constructorIteratorParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function logElement(value, key) {\n" + + " alert(key);\n" + + " alert(value);\n" + + "}\n" + + "function test() {\n" + + " try {\n" + + " var myIterable = {};\n" + + " myIterable[Symbol.iterator] = function() {\n" + + " return {\n" + + " next: function() {\n" + + " if (this._first) {;\n" + + " this._first = false;\n" + + " return { value: [ 77, 'one' ], done: false };\n" + + " }\n" + + " return { done: true };\n" + + " },\n" + + " _first: true\n" + + " };\n" + + " };\n" + + " var myMap = new Map(myIterable);\n" + + " alert(myMap.size);\n" + + " myMap.forEach(logElement);\n" + + " }catch(e) { alert('exception'); }" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(DEFAULT = {"value1", "key1", "[object Map]", "[object Window]", "[object Object]", "key2", "[object Map]", "[object Window]", "null", "key3", "[object Map]", "[object Window]", Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java 2018-01-17 16:27:10 UTC (rev 15080) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java 2018-01-17 20:04:38 UTC (rev 15081) @@ -31,6 +31,7 @@ * Tests for {@link Set}. * * @author Ahmed Ashour + * @author Ronald Brill */ @RunWith(BrowserRunner.class) public class SetTest extends WebDriverTestCase { @@ -139,10 +140,29 @@ @Test @Alerts(DEFAULT = "2", IE = "0") - public void constructor() throws Exception { + public void constructorArray() throws Exception { final String html = "<html><head><title>foo</title><script>\n" + "function test() {\n" + + " var mySet = new Set([2, 7]);\n" + + " alert(mySet.size);\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "2", + IE = "0") + public void constructorInt32Array() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + " var array = new Int32Array([2, 7]);\n" + " var mySet = new Set(array);\n" + " alert(mySet.size);\n" @@ -222,6 +242,45 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = {"1", "#77"}, + IE = "exception") + public void constructorIteratorParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function logElement(value) {\n" + + " alert(value);\n" + + "}\n" + + "function test() {\n" + + " try {\n" + + " var myIterable = {};\n" + + " myIterable[Symbol.iterator] = function() {\n" + + " return {\n" + + " next: function() {\n" + + " if (this._first) {;\n" + + " this._first = false;\n" + + " return { value: '#77', done: false };\n" + + " }\n" + + " return { done: true };\n" + + " },\n" + + " _first: true\n" + + " };\n" + + " };\n" + + " var mySet = new Set(myIterable);\n" + + " alert(mySet.size);\n" + + " mySet.forEach(logElement);\n" + + " }catch(e) { alert('exception'); }" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(DEFAULT = {"ab", "ab", "[object Set]", "[object Window]", "undefined", "undefined", "[object Set]", "[object Window]", "null", "null", "[object Set]", "[object Window]"}, |
From: <rb...@us...> - 2018-01-19 07:48:02
|
Revision: 15083 http://sourceforge.net/p/htmlunit/code/15083 Author: rbri Date: 2018-01-19 07:47:59 +0000 (Fri, 19 Jan 2018) Log Message: ----------- Fix the broken initialization of the canvas context that empties the canvas every time canvas.getContext("2d") was called Issue 1674 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLCanvasElement.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-18 19:56:26 UTC (rev 15082) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-19 07:47:59 UTC (rev 15083) @@ -7,7 +7,10 @@ </properties> <body> - <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented"> + <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented, start adding support of user defined iterators"> + <action type="fix" dev="rbri" issue="1674"> + Fix the broken initialization of the canvas context that empties the canvas every time canvas.getContext("2d") was called. + </action> <action type="add" dev="rbri"> JavaScript: Set and Map constructor now supports user defined iterators also. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLCanvasElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLCanvasElement.java 2018-01-18 19:56:26 UTC (rev 15082) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLCanvasElement.java 2018-01-19 07:47:59 UTC (rev 15083) @@ -40,7 +40,7 @@ @JsxClass(domClass = HtmlCanvas.class) public class HTMLCanvasElement extends HTMLElement { - private Object context_; + private CanvasRenderingContext2D context2d_; /** * Creates an instance. @@ -117,11 +117,13 @@ @JsxFunction public Object getContext(final String contextId) { if ("2d".equals(contextId)) { - final CanvasRenderingContext2D context = new CanvasRenderingContext2D(this); - context.setParentScope(getParentScope()); - context.setPrototype(getPrototype(context.getClass())); - context_ = context; - return context; + if (context2d_ == null) { + final CanvasRenderingContext2D context = new CanvasRenderingContext2D(this); + context.setParentScope(getParentScope()); + context.setPrototype(getPrototype(context.getClass())); + context2d_ = context; + } + return context2d_; } return null; } @@ -134,13 +136,14 @@ */ @JsxFunction public String toDataURL(final Object type) { - if (context_ instanceof CanvasRenderingContext2D) { + if (context2d_ != null) { String typeInUse = type.toString(); if (type == Undefined.instance) { typeInUse = null; } - return ((CanvasRenderingContext2D) context_).toDataURL(typeInUse); + return context2d_.toDataURL(typeInUse); } + if (getBrowserVersion().hasFeature(JS_CANVAS_DATA_URL_IE_PNG)) { return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAAAXNSR0IArs4c6QAAAARnQU1BAA" + "Cxjwv8YQUAAADGSURBVHhe7cExAQAAAMKg9U9tCF8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
From: <rb...@us...> - 2018-01-19 08:43:08
|
Revision: 15084 http://sourceforge.net/p/htmlunit/code/15084 Author: rbri Date: 2018-01-19 08:43:06 +0000 (Fri, 19 Jan 2018) Log Message: ----------- Setter for history.scrollRestoration added Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/History.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/History2Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-19 07:47:59 UTC (rev 15083) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-19 08:43:06 UTC (rev 15084) @@ -8,6 +8,9 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented, start adding support of user defined iterators"> + <action type="add" dev="rbri"> + JavaScript: Setter for history.scrollRestoration added. + </action> <action type="fix" dev="rbri" issue="1674"> Fix the broken initialization of the canvas context that empties the canvas every time canvas.getContext("2d") was called. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/History.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/History.java 2018-01-19 07:47:59 UTC (rev 15083) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/History.java 2018-01-19 08:43:06 UTC (rev 15084) @@ -32,6 +32,7 @@ import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter; +import com.gargoylesoftware.htmlunit.javascript.configuration.JsxSetter; import net.sourceforge.htmlunit.corejs.javascript.Context; @@ -47,7 +48,11 @@ */ @JsxClass public class History extends SimpleScriptable { + private static final String SCROLL_RESTAURATION_AUTO = "auto"; + private static final String SCROLL_RESTAURATION_MANUAL = "manual"; + private String scrollRestoration_ = SCROLL_RESTAURATION_AUTO; + /** * Creates an instance. */ @@ -165,7 +170,21 @@ */ @JsxGetter({CHROME, FF52}) public String getScrollRestoration() { - return "auto"; + return scrollRestoration_; } + /** + * @param scrollRestoration the new value + */ + @JsxSetter({CHROME, FF52}) + public void setScrollRestoration(final String scrollRestoration) { + if (SCROLL_RESTAURATION_AUTO.equals(scrollRestoration)) { + scrollRestoration_ = SCROLL_RESTAURATION_AUTO; + return; + } + if (SCROLL_RESTAURATION_MANUAL.equals(scrollRestoration)) { + scrollRestoration_ = SCROLL_RESTAURATION_MANUAL; + return; + } + } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/History2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/History2Test.java 2018-01-19 07:47:59 UTC (rev 15083) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/History2Test.java 2018-01-19 08:43:06 UTC (rev 15084) @@ -767,4 +767,39 @@ loadPage2(html2, URL_SECOND); assertEquals("page2", driver.getTitle()); } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = {"auto", "manual", "auto", "auto", "auto", "auto"}, + FF45 = {"undefined", "manual", "auto", "MaNUaL", "unknown", "undefined"}, + IE = {"undefined", "manual", "auto", "MaNUaL", "unknown", "undefined"}) + public void scrollRestoration() throws Exception { + final String html = "<html><head><script>\n" + + " function test() {\n" + + " alert(history.scrollRestoration);\n" + + + " history.scrollRestoration = 'manual';\n" + + " alert(history.scrollRestoration);\n" + + + " history.scrollRestoration = 'auto';\n" + + " alert(history.scrollRestoration);\n" + + + " history.scrollRestoration = 'MaNUaL';\n" + + " alert(history.scrollRestoration);\n" + + + " history.scrollRestoration = 'unknown';\n" + + " alert(history.scrollRestoration);\n" + + + " history.scrollRestoration = undefined;\n" + + " alert(history.scrollRestoration);\n" + + + " }\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } } |
From: <rb...@us...> - 2018-01-19 08:43:40
|
Revision: 15085 http://sourceforge.net/p/htmlunit/code/15085 Author: rbri Date: 2018-01-19 08:43:37 +0000 (Fri, 19 Jan 2018) Log Message: ----------- code cleanup Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java 2018-01-19 08:43:06 UTC (rev 15084) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Set.java 2018-01-19 08:43:37 UTC (rev 15085) @@ -65,6 +65,7 @@ if (iterable == Undefined.instance) { return; } + final Window window = (Window) ScriptRuntime.getTopCallScope(Context.getCurrentContext()); if (window.getBrowserVersion().hasFeature(JS_SET_CONSTRUCTOR_IGNORE_ARGUMENT)) { return; Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java 2018-01-19 08:43:06 UTC (rev 15084) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/SetTest.java 2018-01-19 08:43:37 UTC (rev 15085) @@ -268,7 +268,7 @@ + " var mySet = new Set(myIterable);\n" + " alert(mySet.size);\n" + " mySet.forEach(logElement);\n" - + " }catch(e) { alert('exception'); }" + + " } catch(e) { alert('exception'); }" + "}\n" + "</script></head>\n" + "<body onload='test()'>\n" |
From: <rb...@us...> - 2018-01-20 23:42:46
|
Revision: 15087 http://sourceforge.net/p/htmlunit/code/15087 Author: rbri Date: 2018-01-20 23:42:44 +0000 (Sat, 20 Jan 2018) Log Message: ----------- some improvements Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSet.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSetTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSet.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSet.java 2018-01-20 22:49:57 UTC (rev 15086) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSet.java 2018-01-20 23:42:44 UTC (rev 15087) @@ -29,6 +29,7 @@ import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.Delegator; import net.sourceforge.htmlunit.corejs.javascript.NativeArray; +import net.sourceforge.htmlunit.corejs.javascript.Scriptable; import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; import net.sourceforge.htmlunit.corejs.javascript.Undefined; @@ -36,6 +37,7 @@ * A JavaScript object for {@code WeakSet}. * * @author Ahmed Ashour + * @author Ronald Brill */ @JsxClass({CHROME, FF, EDGE}) public class WeakSet extends SimpleScriptable { @@ -54,18 +56,36 @@ */ @JsxConstructor public WeakSet(final Object iterable) { - if (iterable != Undefined.instance) { - if (iterable instanceof NativeArray) { - final NativeArray array = (NativeArray) iterable; - for (int i = 0; i < array.getLength(); i++) { - add(array.get(i)); + if (iterable == Undefined.instance) { + return; + } + + if (iterable instanceof NativeArray) { + final NativeArray array = (NativeArray) iterable; + for (int i = 0; i < array.getLength(); i++) { + final Object value = ScriptableObject.getProperty(array, i); + if (Undefined.instance != value + && value instanceof ScriptableObject) { + add(ScriptableObject.getProperty(array, i)); } } - else { - throw Context.reportRuntimeError("TypeError: object is not iterablee (" - + iterable.getClass().getName() + ")"); + return; + } + + if (iterable instanceof Scriptable) { + final Scriptable scriptable = (Scriptable) iterable; + if (Iterator.iterate(Context.getCurrentContext(), this, scriptable, + value -> { + if (Undefined.instance != value + && value instanceof ScriptableObject) { + add(value); + } + })) { + return; } } + + throw Context.reportRuntimeError("TypeError: object is not iterable (" + iterable.getClass().getName() + ")"); } /** @@ -78,9 +98,11 @@ if (value instanceof Delegator) { value = ((Delegator) value).getDelegee(); } + if (!(value instanceof ScriptableObject)) { throw Context.reportRuntimeError("TypeError: key is not an object"); } + set_.add(value); return this; } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSetTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSetTest.java 2018-01-20 22:49:57 UTC (rev 15086) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakSetTest.java 2018-01-20 23:42:44 UTC (rev 15087) @@ -25,6 +25,7 @@ * Tests for {@link WeakSet}. * * @author Ahmed Ashour + * @author Ronald Brill */ @RunWith(BrowserRunner.class) public class WeakSetTest extends WebDriverTestCase { @@ -33,6 +34,121 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = "true", + IE = {}) + public void constructorArray() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " if (window.WeakSet) {\n" + + " var obj = {};\n" + + " var foo = {};\n" + + " var mySet = new WeakSet([obj, foo]);\n" + + " alert(mySet.has(foo));\n" + + " }\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = { "false", "true"}, + IE = {}) + public void constructorSetParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " if (window.WeakSet) {\n" + + " var obj = {};\n" + + " var foo = {};\n" + + " var mySet = new WeakSet(new Set([foo]));\n" + + " alert(mySet.has(obj));\n" + + " alert(mySet.has(foo));\n" + + " }\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"false", "false", "false"}, + IE = {}) + public void constructorMapParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " if (window.WeakSet) {\n" + + " var obj = {};\n" + + " var foo = {};\n" + + " var kvArray = [['key1', obj], ['key2', foo]];\n" + + " var myMap = new Map(kvArray);\n" + + " var mySet = new WeakSet(myMap);\n" + + " alert(mySet.has('key1'));\n" + + " alert(mySet.has(obj));\n" + + " alert(mySet.has(kvArray[1]));\n" + + " }\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"true", "false"}, + IE = {}) + public void constructorIteratorParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function logElement(value) {\n" + + " alert(value);\n" + + "}\n" + + "function test() {\n" + + " if (window.WeakSet) {\n" + + " var obj = {};\n" + + " var foo = {};\n" + + " var myIterable = {};\n" + + " myIterable[Symbol.iterator] = function() {\n" + + " return {\n" + + " next: function() {\n" + + " if (this._first) {;\n" + + " this._first = false;\n" + + " return { value: foo, done: false };\n" + + " }\n" + + " return { done: true };\n" + + " },\n" + + " _first: true\n" + + " };\n" + + " };\n" + + " var mySet = new WeakSet(myIterable);\n" + + " alert(mySet.has(foo));\n" + + " alert(mySet.has(obj));\n" + + " }\n" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(DEFAULT = {"undefined", "true"}, IE = {}) public void has() throws Exception { @@ -52,4 +168,34 @@ + "</body></html>"; loadPageWithAlerts2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"Type error", "Type error", "true"}, + IE = {}) + public void add() throws Exception { + final String html = "<html><head><script>\n" + + " function test() {\n" + + " if (window.WeakSet) {\n" + + " var mySet = new WeakSet();\n" + + + " try {\n" + + " mySet.add(7);\n" + + " } catch(e) { alert('Type error'); }\n" + + + " try {\n" + + " mySet.add('seven');\n" + + " } catch(e) { alert('Type error'); }\n" + + + " var foo = {};\n" + + " mySet.add(foo);\n" + + " alert(mySet.has(foo));\n" + + " }\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } } |
From: <rb...@us...> - 2018-01-22 18:44:17
|
Revision: 15089 http://sourceforge.net/p/htmlunit/code/15089 Author: rbri Date: 2018-01-22 18:44:13 +0000 (Mon, 22 Jan 2018) Log Message: ----------- doing Ctrl+Click on an anchor now opens a new window also if the href is javascript based Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor2Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-22 16:58:07 UTC (rev 15088) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-22 18:44:13 UTC (rev 15089) @@ -8,6 +8,9 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented, start adding support of user defined iterators"> + <action type="fix" dev="rbri"> + Doing Ctrl+Click on an anchor now opens a new window also if the href is javascript based. + </action> <action type="add" dev="rbri"> JavaScript: Setter for history.scrollRestoration added. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor.java 2018-01-22 16:58:07 UTC (rev 15088) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor.java 2018-01-22 18:44:13 UTC (rev 15089) @@ -131,12 +131,18 @@ builder.append(ch); } - if (hasFeature(ANCHOR_IGNORE_TARGET_FOR_JS_HREF)) { + if (hasFeature(ANCHOR_IGNORE_TARGET_FOR_JS_HREF) && !shiftKey && !ctrlKey) { page.executeJavaScript(builder.toString(), "javascript url", getStartLineNumber()); } else { - final WebWindow win = page.getWebClient().openTargetWindow(page.getEnclosingWindow(), - page.getResolvedTarget(getTargetAttribute()), "_self"); + final String target; + if (shiftKey || ctrlKey) { + target = "_blank"; + } + else { + target = page.getResolvedTarget(getTargetAttribute()); + } + final WebWindow win = page.getWebClient().openTargetWindow(page.getEnclosingWindow(), target, "_self"); Page enclosedPage = win.getEnclosedPage(); if (enclosedPage == null) { win.getWebClient().getPage(win, new WebRequest(WebClient.URL_ABOUT_BLANK)); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor2Test.java 2018-01-22 16:58:07 UTC (rev 15088) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlAnchor2Test.java 2018-01-22 18:44:13 UTC (rev 15089) @@ -42,6 +42,7 @@ * @author Marc Guillemot * @author Stefan Anzinger * @author Ahmed Ashour + * @author Ronald Brill */ @RunWith(BrowserRunner.class) public class HtmlAnchor2Test extends SimpleWebTestCase { @@ -640,4 +641,123 @@ assertEquals("First", secondPage.getTitleText()); } + /** + * @throws Exception if the test fails + */ + @Test + public void clickCtrlShift() throws Exception { + final String first + = "<html><head><title>First</title></head><body>\n" + + " <a href='" + URL_SECOND + "' id='a2'>link to foo2</a>\n" + + "</body></html>"; + final String second + = "<html><head><title>Second</title></head><body></body></html>"; + + final WebClient client = getWebClient(); + final List<String> collectedAlerts = new ArrayList<>(); + client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); + + final MockWebConnection webConnection = new MockWebConnection(); + webConnection.setResponse(URL_FIRST, first); + webConnection.setResponse(URL_SECOND, second); + client.setWebConnection(webConnection); + + assertEquals(1, getWebClient().getTopLevelWindows().size()); + final HtmlPage page = client.getPage(URL_FIRST); + final HtmlAnchor anchor = page.getHtmlElementById("a2"); + + final HtmlPage secondPage = anchor.click(true, true, false); + assertEquals(2, getWebClient().getTopLevelWindows().size()); + assertEquals("First", secondPage.getTitleText()); + } + + /** + * @throws Exception if the test fails + */ + @Test + public void clickShiftJavascript() throws Exception { + final String first + = "<html><head><title>First</title></head><body>\n" + + " <a href='javascript: window.location=\"" + URL_SECOND + "\"' id='a2'>link to foo2</a>\n" + + "</body></html>"; + final String second + = "<html><head><title>Second</title></head><body></body></html>"; + + final WebClient client = getWebClient(); + final List<String> collectedAlerts = new ArrayList<>(); + client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); + + final MockWebConnection webConnection = new MockWebConnection(); + webConnection.setResponse(URL_FIRST, first); + webConnection.setResponse(URL_SECOND, second); + client.setWebConnection(webConnection); + + assertEquals(1, getWebClient().getTopLevelWindows().size()); + final HtmlPage page = client.getPage(URL_FIRST); + final HtmlAnchor anchor = page.getHtmlElementById("a2"); + + final HtmlPage secondPage = anchor.click(true, false, false); + assertEquals(2, getWebClient().getTopLevelWindows().size()); + assertEquals("Second", secondPage.getTitleText()); + } + + /** + * @throws Exception if the test fails + */ + @Test + public void clickCtrlJavascript() throws Exception { + final String first + = "<html><head><title>First</title></head><body>\n" + + " <a href='javascript: window.location=\"" + URL_SECOND + "\"' id='a2'>link to foo2</a>\n" + + "</body></html>"; + final String second + = "<html><head><title>Second</title></head><body></body></html>"; + + final WebClient client = getWebClient(); + final List<String> collectedAlerts = new ArrayList<>(); + client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); + + final MockWebConnection webConnection = new MockWebConnection(); + webConnection.setResponse(URL_FIRST, first); + webConnection.setResponse(URL_SECOND, second); + client.setWebConnection(webConnection); + + assertEquals(1, getWebClient().getTopLevelWindows().size()); + final HtmlPage page = client.getPage(URL_FIRST); + final HtmlAnchor anchor = page.getHtmlElementById("a2"); + + final HtmlPage secondPage = anchor.click(false, true, false); + assertEquals(2, getWebClient().getTopLevelWindows().size()); + assertEquals("First", secondPage.getTitleText()); + } + + /** + * @throws Exception if the test fails + */ + @Test + public void clickShiftCtrlJavascript() throws Exception { + final String first + = "<html><head><title>First</title></head><body>\n" + + " <a href='javascript: window.location=\"" + URL_SECOND + "\"' id='a2'>link to foo2</a>\n" + + "</body></html>"; + final String second + = "<html><head><title>Second</title></head><body></body></html>"; + + final WebClient client = getWebClient(); + final List<String> collectedAlerts = new ArrayList<>(); + client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); + + final MockWebConnection webConnection = new MockWebConnection(); + webConnection.setResponse(URL_FIRST, first); + webConnection.setResponse(URL_SECOND, second); + client.setWebConnection(webConnection); + + assertEquals(1, getWebClient().getTopLevelWindows().size()); + final HtmlPage page = client.getPage(URL_FIRST); + final HtmlAnchor anchor = page.getHtmlElementById("a2"); + + final HtmlPage secondPage = anchor.click(true, true, false); + assertEquals(2, getWebClient().getTopLevelWindows().size()); + assertEquals("First", secondPage.getTitleText()); + } } |
From: <rb...@us...> - 2018-01-22 20:09:19
|
Revision: 15090 http://sourceforge.net/p/htmlunit/code/15090 Author: rbri Date: 2018-01-22 20:09:16 +0000 (Mon, 22 Jan 2018) Log Message: ----------- WeakSet and WeakMap constructor now supports user defined iterators also Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMap.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMapTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-22 18:44:13 UTC (rev 15089) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-22 20:09:16 UTC (rev 15090) @@ -8,6 +8,9 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented, start adding support of user defined iterators"> + <action type="add" dev="rbri"> + JavaScript: WeakSet and WeakMap constructor now supports user defined iterators also. + </action> <action type="fix" dev="rbri"> Doing Ctrl+Click on an anchor now opens a new window also if the href is javascript based. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2018-01-22 18:44:13 UTC (rev 15089) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2018-01-22 20:09:16 UTC (rev 15090) @@ -1338,9 +1338,9 @@ @BrowserFeature({CHROME, FF}) JS_TYPE_ACCEPTS_ARBITRARY_VALUES, - /** WeakMap supports the argument constructor. */ - @BrowserFeature({CHROME, FF}) - JS_WEAKMAP_CONSTRUCTOR_ARGUMENT, + /** WeakMap ignores the constructor argument. */ + @BrowserFeature(IE) + JS_WEAKMAP_CONSTRUCTOR_IGNORE_ARGUMENT, /** Allow inheriting parent constants * in {@link com.gargoylesoftware.htmlunit.javascript.host.event.WebGLContextEvent}. */ Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java 2018-01-22 18:44:13 UTC (rev 15089) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Map.java 2018-01-22 20:09:16 UTC (rev 15090) @@ -99,43 +99,22 @@ if (arrayLike instanceof Scriptable) { final Scriptable scriptable = (Scriptable) arrayLike; - final Object length = scriptable.get("length", scriptable); - if (length != Scriptable.NOT_FOUND) { - final int size = (int) Context.toNumber(length); - for (int i = 0; i < size; i++) { - final Object entryObject = scriptable.get(i, scriptable); - if (entryObject instanceof NativeArray) { - final Object[] entry = toArray((NativeArray) entryObject); + if (Iterator.iterate(Context.getCurrentContext(), this, scriptable, + value -> { + if (Undefined.instance != value && value instanceof NativeArray) { + final Object[] entry = toArray((NativeArray) value); if (entry.length > 0) { final Object key = entry[0]; - final Object value = entry.length > 1 ? entry[1] : null; - set(key, value); + if (Undefined.instance != key) { + final Object entryValue = entry.length > 1 ? entry[1] : null; + set(key, entryValue); + } } } else { throw Context.reportRuntimeError("TypeError: object is not iterable (" - + entryObject.getClass().getName() + ")"); + + value.getClass().getName() + ")"); } - } - return; - } - - if (Iterator.iterate(context, this, scriptable, - value -> { - if (value != Undefined.instance) { - if (value instanceof NativeArray) { - final Object[] entry = toArray((NativeArray) value); - if (entry.length > 0) { - final Object entryKey = entry[0]; - final Object entryValue = entry.length > 1 ? entry[1] : null; - set(entryKey, entryValue); - } - } - else { - throw Context.reportRuntimeError("TypeError: object is not iterable (" - + value.getClass().getName() + ")"); - } - } })) { return; } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMap.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMap.java 2018-01-22 18:44:13 UTC (rev 15089) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMap.java 2018-01-22 20:09:16 UTC (rev 15090) @@ -14,7 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host; -import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_WEAKMAP_CONSTRUCTOR_ARGUMENT; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_WEAKMAP_CONSTRUCTOR_IGNORE_ARGUMENT; import java.util.WeakHashMap; @@ -27,6 +27,7 @@ import net.sourceforge.htmlunit.corejs.javascript.Delegator; import net.sourceforge.htmlunit.corejs.javascript.NativeArray; import net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime; +import net.sourceforge.htmlunit.corejs.javascript.Scriptable; import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; import net.sourceforge.htmlunit.corejs.javascript.Undefined; @@ -48,40 +49,86 @@ /** * Creates an instance. - * @param iterable an Array or other iterable object + * @param arrayLike an Array or other iterable object */ @JsxConstructor - public WeakMap(final Object iterable) { - if (iterable != Undefined.instance) { - final Window window = (Window) ScriptRuntime.getTopCallScope(Context.getCurrentContext()); - if (window.getBrowserVersion().hasFeature(JS_WEAKMAP_CONSTRUCTOR_ARGUMENT)) { - if (iterable instanceof NativeArray) { - final NativeArray array = (NativeArray) iterable; - for (int i = 0; i < array.getLength(); i++) { - final Object entryObject = array.get(i); - if (entryObject instanceof NativeArray) { - final Object[] entry = ((NativeArray) entryObject).toArray(); - if (entry.length > 0) { - final Object key = entry[0]; - final Object value = entry.length > 1 ? entry[1] : null; - set(key, value); - } + public WeakMap(final Object arrayLike) { + if (arrayLike == Undefined.instance) { + return; + } + + final Context context = Context.getCurrentContext(); + final Window window = (Window) ScriptRuntime.getTopCallScope(context); + if (window.getBrowserVersion().hasFeature(JS_WEAKMAP_CONSTRUCTOR_IGNORE_ARGUMENT)) { + return; + } + + if (arrayLike instanceof NativeArray) { + final NativeArray array = (NativeArray) arrayLike; + for (int i = 0; i < array.getLength(); i++) { + final Object entryObject = array.get(i); + if (entryObject instanceof NativeArray) { + final Object[] entry = toArray((NativeArray) entryObject); + if (entry.length > 0) { + final Object key = entry[0]; + if (Undefined.instance != key && key instanceof ScriptableObject) { + final Object value = entry.length > 1 ? entry[1] : null; + set(key, value); } - else { - throw Context.reportRuntimeError("TypeError: object is not iterable (" - + entryObject.getClass().getName() + ")"); - } } } else { throw Context.reportRuntimeError("TypeError: object is not iterable (" - + iterable.getClass().getName() + ")"); + + entryObject.getClass().getName() + ")"); } } + return; } + + if (arrayLike instanceof Scriptable) { + final Scriptable scriptable = (Scriptable) arrayLike; + if (Iterator.iterate(Context.getCurrentContext(), this, scriptable, + value -> { + if (Undefined.instance != value && value instanceof NativeArray) { + final Object[] entry = toArray((NativeArray) value); + if (entry.length > 0) { + final Object key = entry[0]; + if (Undefined.instance != key && key instanceof ScriptableObject) { + final Object entryValue = entry.length > 1 ? entry[1] : null; + set(key, entryValue); + } + } + } + else { + throw Context.reportRuntimeError("TypeError: object is not iterable (" + + value.getClass().getName() + ")"); + } + })) { + return; + } + } + + throw Context.reportRuntimeError("TypeError: object is not iterable (" + arrayLike.getClass().getName() + ")"); } /** + * Replacement of {@link NativeArray#toArray()}. + */ + private static Object[] toArray(final NativeArray narray) { + final long longLen = narray.getLength(); + if (longLen > Integer.MAX_VALUE) { + throw new IllegalStateException(); + } + + final int len = (int) longLen; + final Object[] arr = new Object[len]; + for (int i = 0; i < len; i++) { + arr[i] = ScriptableObject.getProperty(narray, i); + } + return arr; + } + + /** * Returns the value of the given key. * @param key the key * @return the value Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMapTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMapTest.java 2018-01-22 18:44:13 UTC (rev 15089) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WeakMapTest.java 2018-01-22 20:09:16 UTC (rev 15090) @@ -25,6 +25,7 @@ * Tests for {@link WeakMap}. * * @author Ahmed Ashour + * @author Ronald Brill */ @RunWith(BrowserRunner.class) public class WeakMapTest extends WebDriverTestCase { @@ -33,6 +34,118 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = {"true", "one"}, + IE = {"false", "undefined"}) + public void constructorArray() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " var obj = {};\n" + + " var foo = {};\n" + + " var myMap = new WeakMap([[ obj, 'one' ],[ foo, 'two' ]]);\n" + + " alert(myMap.has(foo));\n" + + " alert(myMap.get(obj));\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "exception", + IE = {"false"}) + public void constructorSetParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " try {\n" + + " var myMap = new WeakMap(new Set('test'));\n" + + " alert(myMap.has('test'));\n" + + " } catch(e) {\n" + + " alert('exception');\n" + + " }\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "true", + IE = "false") + public void constructorMapParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " var obj = {};\n" + + " var foo = {};\n" + + " var testMap = new Map([[ obj, 'one' ],[ foo, 'two' ]]);\n" + + " try {\n" + + " var myMap = new WeakMap(testMap);\n" + + " alert(myMap.has(foo));\n" + + " } catch(e) {\n" + + " alert('exception');\n" + + " }\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "true", + IE = {}) + public void constructorIteratorParam() throws Exception { + final String html + = "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " if (window.WeakSet) {\n" + + " var obj = {};\n" + + " var foo = {};\n" + + " var myIterable = {};\n" + + " myIterable[Symbol.iterator] = function() {\n" + + " return {\n" + + " next: function() {\n" + + " if (this._first) {;\n" + + " this._first = false;\n" + + " return { value: [ foo, 'one' ], done: false };\n" + + " }\n" + + " return { done: true };\n" + + " },\n" + + " _first: true\n" + + " };\n" + + " };\n" + + " try {\n" + + " var myMap = new WeakMap(myIterable);\n" + + " alert(myMap.has(foo));\n" + + " } catch(e) {\n" + + " alert('exception');\n" + + " }\n" + + " }" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(DEFAULT = {"undefined", "value2"}, IE = {"undefined", "undefined"}) public void get() throws Exception { |
From: <rb...@us...> - 2018-01-25 16:44:46
|
Revision: 15092 http://sourceforge.net/p/htmlunit/code/15092 Author: rbri Date: 2018-01-25 16:44:43 +0000 (Thu, 25 Jan 2018) Log Message: ----------- fix some problem to be able to run our test suite with edge Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2018-01-24 20:35:20 UTC (rev 15091) +++ trunk/htmlunit/src/changes/changes.xml 2018-01-25 16:44:43 UTC (rev 15092) @@ -8,6 +8,9 @@ <body> <release version="2.30" date="xx, 2018" description="Bugfixes, URLSearchParams implemented, start adding support of user defined iterators"> + <action type="fix" dev="rbri" due-to="Frank Danek"> + Fix some problem to be able to run our test suite with edge. + </action> <action type="add" dev="rbri"> JavaScript: WeakSet and WeakMap constructor now supports user defined iterators also. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2018-01-24 20:35:20 UTC (rev 15091) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2018-01-25 16:44:43 UTC (rev 15092) @@ -1220,7 +1220,7 @@ if (event == null) { return false; } - else if (!(event.getSrcElement() instanceof HTMLElement)) { + if (!(event.getSrcElement() instanceof HTMLElement)) { return false; } final HTMLElement srcElement = (HTMLElement) event.getSrcElement(); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java 2018-01-24 20:35:20 UTC (rev 15091) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java 2018-01-25 16:44:43 UTC (rev 15092) @@ -40,6 +40,7 @@ Pattern.compile("Starting ChromeDriver " + ExternalTest.CHROME_DRIVER_.replace(".", "\\.") + "\\.[0-9]+ ?\\(?[0-9a-f]*\\)? on port \\d*\r?\n" + "Only local connections are allowed\\.\r?\n"), + Pattern.compile(".*Unable to retrieve document state unexpected alert open\r?\n"), Pattern.compile(".*FirefoxOptions toCapabilities\r?\n"), Pattern.compile(".*Preferring the firefox binary in these options \\(.*\\)\r?\n"), Pattern.compile(".*geckodriver.*\r?\n"), @@ -49,7 +50,7 @@ Pattern.compile(".*\taddons\\..*\r?\n"), Pattern.compile("\\*\\*\\* Blocklist::.*\r?\n"), Pattern.compile("Started InternetExplorerDriver server \\(\\d\\d\\-bit\\)\r?\n" - + "3\\.6\\.0\\.0\r?\n" + + "3\\.8\\.0\\.0\r?\n" + "Listening on port \\d*\r?\n" + "Only local connections are allowed\r?\n"), // edge Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java 2018-01-24 20:35:20 UTC (rev 15091) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebDriverTestCase.java 2018-01-25 16:44:43 UTC (rev 15092) @@ -14,6 +14,7 @@ */ package com.gargoylesoftware.htmlunit; +import static com.gargoylesoftware.htmlunit.BrowserVersion.EDGE; import static com.gargoylesoftware.htmlunit.BrowserVersion.INTERNET_EXPLORER; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static org.junit.Assert.fail; @@ -357,6 +358,13 @@ } /** + * Closes the real Edge browser drivers. + */ + protected static void shutDownRealEdge() { + shutDownReal(EDGE); + } + + /** * Stops all WebServers. * @throws Exception if it fails */ @@ -805,7 +813,7 @@ WebDriver driver = getWebDriver(); if (!(driver instanceof HtmlUnitDriver)) { try { - driver.manage().window().setSize(new Dimension(1272, 768)); + resizeIfNeeded(driver); } catch (final NoSuchSessionException e) { // maybe the driver was killed by the test before; setup a new one @@ -812,7 +820,7 @@ shutDownRealBrowsers(); driver = getWebDriver(); - driver.manage().window().setSize(new Dimension(1272, 768)); + resizeIfNeeded(driver); } } driver.get(url.toExternalForm()); @@ -849,12 +857,32 @@ startWebServer("./", null, servlets); - final WebDriver driver = getWebDriver(); + WebDriver driver = getWebDriver(); + if (!(driver instanceof HtmlUnitDriver)) { + try { + resizeIfNeeded(driver); + } + catch (final NoSuchSessionException e) { + // maybe the driver was killed by the test before; setup a new one + shutDownRealBrowsers(); + + driver = getWebDriver(); + resizeIfNeeded(driver); + } + } driver.get(url.toExternalForm()); return driver; } + private void resizeIfNeeded(final WebDriver driver) { + final Dimension size = driver.manage().window().getSize(); + if (size.getWidth() != 1272 || size.getHeight() != 768) { + // only resize if needed because it may be quite expensive (e.g. Edge) + driver.manage().window().setSize(new Dimension(1272, 768)); + } + } + /** * Defines the provided HTML as the response for {@link WebTestCase#URL_FIRST} * and loads the page with this URL using the current WebDriver version; finally, asserts that the @@ -1054,7 +1082,19 @@ while (collectedAlerts.size() < alertsLength && System.currentTimeMillis() < maxWait) { try { final Alert alert = driver.switchTo().alert(); - collectedAlerts.add(alert.getText()); + String text = alert.getText(); + + if (useRealBrowser() && getBrowserVersion().isEdge()) { + // EdgeDriver reads empty strings as null -> harmonize + if (text == null) { + text = ""; + } + + // alerts for real Edge need some time until they may be accepted + Thread.sleep(100); + } + + collectedAlerts.add(text); alert.accept(); // handling of alerts requires some time @@ -1061,9 +1101,17 @@ // at least for tests with many alerts we have to take this into account maxWait += 100; - if (useRealBrowser() && getBrowserVersion().isIE()) { - // alerts for real IE are really slow - maxWait += 5000; + if (useRealBrowser()) { + if (getBrowserVersion().isIE()) { + // alerts for real IE are really slow + maxWait += 5000; + } + else if (getBrowserVersion().isEdge()) { + // closing one alert and opening the next one takes some time in real Edge + // (most probably due to the 'nice' fade animations...) + Thread.sleep(500); + maxWait += 800; + } } } catch (final NoAlertPresentException e) { |