From: <rb...@us...> - 2014-01-23 19:02:12
|
Revision: 9047 http://sourceforge.net/p/htmlunit/code/9047 Author: rbri Date: 2014-01-23 19:02:08 +0000 (Thu, 23 Jan 2014) Log Message: ----------- fix width and height value processing in FF 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/HTMLIFrameElement3Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java Property Changed: ---------------- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.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 2014-01-23 17:58:20 UTC (rev 9046) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-01-23 19:02:08 UTC (rev 9047) @@ -2254,10 +2254,10 @@ * is set for the simulated browser */ protected void setWidthOrHeight(final String attributeName, String value, final boolean allowNegativeValues) { - if (value.endsWith("px")) { - value = value.substring(0, value.length() - 2); - } if (!getBrowserVersion().hasFeature(JS_WIDTH_HEIGHT_ACCEPTS_ARBITRARY_VALUES) && value.length() > 0) { + if (value.endsWith("px")) { + value = value.substring(0, value.length() - 2); + } boolean error = false; if (!PERCENT_VALUE.matcher(value).matches()) { try { Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement3Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement3Test.java 2014-01-23 17:58:20 UTC (rev 9046) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement3Test.java 2014-01-23 19:02:08 UTC (rev 9047) @@ -412,7 +412,6 @@ @Test @Alerts(DEFAULT = "128px", IE = "128") - @NotYetImplemented(FF) public void width_px() throws Exception { final String html = "<html><head>" Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java 2014-01-23 17:58:20 UTC (rev 9046) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java 2014-01-23 19:02:08 UTC (rev 9047) @@ -332,7 +332,6 @@ @Test @Alerts(DEFAULT = "128", FF = "128px") - @NotYetImplemented({ FF17, FF24 }) public void width_px() throws Exception { final String html = "<html><head>" Property changes on: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java ___________________________________________________________________ Deleted: svn:mergeinfo \ No newline at end of property |
From: <rb...@us...> - 2014-01-23 20:18:24
|
Revision: 9049 http://sourceforge.net/p/htmlunit/code/9049 Author: rbri Date: 2014-01-23 20:18:20 +0000 (Thu, 23 Jan 2014) Log Message: ----------- improved width and height processing for html elements when simulating FF 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/javascript/host/html/HTMLIFrameElement3Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableCellElementTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-23 19:33:17 UTC (rev 9048) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-23 20:18:20 UTC (rev 9049) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="rbri"> + JavaScript: improved width and height processing for html elements when simulating FF. + </action> <action type="fix" dev="mguillem" issue="1564"> Fix IllegalArgumentException occuring for entities with invalid UTF16 code. </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 2014-01-23 19:33:17 UTC (rev 9048) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-01-23 20:18:20 UTC (rev 9049) @@ -2216,6 +2216,9 @@ */ protected String getWidthOrHeight(final String attributeName, final Boolean returnNegativeValues) { String value = getDomNodeOrDie().getAttribute(attributeName); + if (getBrowserVersion().hasFeature(JS_WIDTH_HEIGHT_ACCEPTS_ARBITRARY_VALUES)) { + return value; + } if (!PERCENT_VALUE.matcher(value).matches()) { try { final Float f = Float.valueOf(value); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement3Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement3Test.java 2014-01-23 19:33:17 UTC (rev 9048) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement3Test.java 2014-01-23 20:18:20 UTC (rev 9049) @@ -257,9 +257,8 @@ * @throws Exception if an error occurs */ @Test - @Alerts(FF = {"", "100", "foo", "20%", "-5", "30.2", "400", "abc", "-5", "100.2", "10%", "300" }, - IE = {"", "100", "", "20%", "-5", "30", "error", "400", "100", "-5", "100", "10%", "300" }) - @NotYetImplemented(FF) + @Alerts(DEFAULT = {"", "100", "foo", "20%", "-5", "30.2", "400", "abc", "-5", "100.2", "10%", "-12.56" }, + IE = {"", "100", "", "20%", "-5", "30", "error", "400", "100", "-5", "100", "10%", "-12" }) public void width() throws Exception { final String html = "<html><body>\n" @@ -294,7 +293,7 @@ + "set(i3, -5);\n" + "set(i4, 100.2);\n" + "set(i5, '10%');\n" - + "set(i6, 300);\n" + + "set(i6, -12.56);\n" + "alert(i1.width);\n" + "alert(i2.width);\n" + "alert(i3.width);\n" @@ -310,9 +309,8 @@ * @throws Exception if an error occurs */ @Test - @Alerts(FF = {"", "100", "foo", "20%", "-5", "30.2", "400", "abc", "-5", "100.2", "10%", "300" }, - IE = {"", "100", "", "20%", "-5", "30", "error", "400", "100", "-5", "100", "10%", "300" }) - @NotYetImplemented(FF) + @Alerts(DEFAULT = {"", "100", "foo", "20%", "-5", "30.2", "400", "abc", "-5", "100.2", "10%", "-12.56" }, + IE = {"", "100", "", "20%", "-5", "30", "error", "400", "100", "-5", "100", "10%", "-12" }) public void height() throws Exception { final String html = "<html><body>\n" @@ -347,7 +345,7 @@ + "set(i3, -5);\n" + "set(i4, 100.2);\n" + "set(i5, '10%');\n" - + "set(i6, 300);\n" + + "set(i6, -12.56);\n" + "alert(i1.height);\n" + "alert(i2.height);\n" + "alert(i3.height);\n" @@ -365,6 +363,7 @@ */ @Test @Alerts(DEFAULT = { "uninitialized", "complete" }, + CHROME = { "complete", "complete" }, IE = { "loading", "complete" }) @NotYetImplemented(FF) public void readyState_IFrame() throws Exception { @@ -433,9 +432,9 @@ * @throws Exception if an error occurs */ @Test - @Alerts(IE = { "[object]", "[object]", "undefined", "" }, + @Alerts(DEFAULT = { "[object Window]", "[object HTMLIFrameElement]", "undefined", "" }, FF = { "[object HTMLIFrameElement]", "[object HTMLIFrameElement]", "", "" }, - IE11 = { "[object Window]", "[object HTMLIFrameElement]", "undefined", "" }) + IE8 = { "[object]", "[object]", "undefined", "" }) @NotYetImplemented(IE) public void idByName() throws Exception { final String html Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableCellElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableCellElementTest.java 2014-01-23 19:33:17 UTC (rev 9048) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableCellElementTest.java 2014-01-23 20:18:20 UTC (rev 9049) @@ -445,7 +445,6 @@ @Test @Alerts(DEFAULT = { "100px", "200px", "400", "abc", "-5", "100.2", "10%" }, IE = { "100", "200", "400", "error", "400", "error", "400", "100", "10%" }) - @NotYetImplemented({ FF17, FF24 }) public void width() throws Exception { final String html = "<html>\n" Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java 2014-01-23 19:33:17 UTC (rev 9048) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLTableColElementTest.java 2014-01-23 20:18:20 UTC (rev 9049) @@ -15,7 +15,6 @@ package com.gargoylesoftware.htmlunit.javascript.host.html; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF; -import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF17; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF24; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.IE8; @@ -272,7 +271,6 @@ @Test @Alerts(FF = { "50", "75%", "foo", "-7", "20.2", "", "80", "40", "abc", "-10", "30%", "33.3" }, IE = { "50", "75%", "", "", "20", "", "error", "error", "80", "40", "", "", "30%", "33" }) - @NotYetImplemented({ FF17, FF24 }) public void width() throws Exception { final String html = "<html><body><table>\n" |
From: <asa...@us...> - 2014-01-24 16:57:15
|
Revision: 9054 http://sourceforge.net/p/htmlunit/code/9054 Author: asashour Date: 2014-01-24 16:57:09 +0000 (Fri, 24 Jan 2014) Log Message: ----------- BrowserVersion: deprecate INTERNET_EXPLORER_8 and INTERNET_EXPLORER_9. Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-24 06:03:11 UTC (rev 9053) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-24 16:57:09 UTC (rev 9054) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="update" dev="asashour"> + BrowserVersion: deprecate INTERNET_EXPLORER_8 and INTERNET_EXPLORER_9. + </action> <action type="fix" dev="rbri"> JavaScript: improved width and height processing for html elements when simulating FF. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java 2014-01-24 06:03:11 UTC (rev 9053) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersion.java 2014-01-24 16:57:09 UTC (rev 9054) @@ -139,12 +139,19 @@ "Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0", (float) 24.0, "FF24", null); - /** Internet Explorer 8. */ + /** + * Internet Explorer 8. + * @deprecated as of 2.14 + */ + // to be removed in 2.16 if IE11 is complete public static final BrowserVersion INTERNET_EXPLORER_8 = new BrowserVersion( INTERNET_EXPLORER, "4.0 (compatible; MSIE 8.0; Windows NT 6.0)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)", 8, "IE8", null); - /** Internet Explorer 9. Work In Progress!!! */ + /** + * Internet Explorer 9. Work In Progress!!! + * @deprecated as of 2.14 + */ public static final BrowserVersion INTERNET_EXPLORER_9 = new BrowserVersion( INTERNET_EXPLORER, "5.0 (compatible; MSIE 9.0; Windows NT 6.1)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1)", 9, "IE9", null); |
From: <asa...@us...> - 2014-01-25 08:01:49
|
Revision: 9055 http://sourceforge.net/p/htmlunit/code/9055 Author: asashour Date: 2014-01-25 08:01:45 +0000 (Sat, 25 Jan 2014) Log Message: ----------- New HttpWebConnection Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksSocketFactory.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/HttpWebConnectionTest.java Added Paths: ----------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksConnectionSocketFactory.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java 2014-01-24 16:57:09 UTC (rev 9054) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java 2014-01-25 08:01:45 UTC (rev 9055) @@ -61,6 +61,10 @@ final class HtmlUnitSSLConnectionSocketFactory extends SSLConnectionSocketFactory { private static final String SSL3ONLY = "htmlunit.SSL3Only"; + static void setUseSSL3Only(final HttpContext parameters, final boolean ssl3Only) { + parameters.setAttribute(SSL3ONLY, ssl3Only); + } + static boolean isUseSSL3Only(final HttpContext context) { return "TRUE".equalsIgnoreCase((String) context.getAttribute(SSL3ONLY)); } @@ -107,10 +111,6 @@ */ @Override public Socket createSocket(final HttpContext context) throws IOException { - if (SocksSocketFactory.getSocksProxy(context) != null) { - // we create the socket in connectSocket has we need to know the destination to open the underlying request - return null; - } final Socket socket = super.createSocket(context); configureSocket((SSLSocket) socket, context); return socket; @@ -129,7 +129,7 @@ final InetSocketAddress remoteAddress, final InetSocketAddress localAddress, final HttpContext context) throws IOException { - final HttpHost socksProxy = SocksSocketFactory.getSocksProxy(context); + final HttpHost socksProxy = SocksConnectionSocketFactory.getSocksProxy(context); if (socksProxy != null) { final Socket underlying = SocksSocketFactory.createSocketWithSocksProxy(socksProxy); underlying.setReuseAddress(true); Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java 2014-01-24 16:57:09 UTC (rev 9054) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java 2014-01-25 08:01:45 UTC (rev 9055) @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; +import java.lang.reflect.Field; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -38,7 +39,9 @@ import java.util.List; import java.util.Map; +import javax.net.ssl.SSLContext; import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSocketFactory; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -53,6 +56,8 @@ import org.apache.http.auth.Credentials; import org.apache.http.client.CookieStore; import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; @@ -62,42 +67,46 @@ import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpTrace; import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.params.ClientPNames; -import org.apache.http.client.params.HttpClientParams; +import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.client.utils.DateUtils; import org.apache.http.client.utils.URIUtils; import org.apache.http.client.utils.URLEncodedUtils; -import org.apache.http.conn.params.ConnRoutePNames; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.config.ConnectionConfig; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.config.SocketConfig; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLContexts; +import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieAttributeHandler; import org.apache.http.cookie.CookieOrigin; import org.apache.http.cookie.CookiePathComparator; import org.apache.http.cookie.CookieSpec; -import org.apache.http.cookie.CookieSpecFactory; +import org.apache.http.cookie.CookieSpecProvider; import org.apache.http.cookie.MalformedCookieException; import org.apache.http.cookie.SetCookie; -import org.apache.http.cookie.params.CookieSpecPNames; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.InputStreamBody; -import org.apache.http.impl.client.AbstractHttpClient; -import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultRedirectStrategy; -import org.apache.http.impl.conn.PoolingClientConnectionManager; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.impl.cookie.BasicPathHandler; +import org.apache.http.impl.cookie.BestMatchSpecFactory; import org.apache.http.impl.cookie.BrowserCompatSpec; +import org.apache.http.impl.cookie.BrowserCompatSpecFactory; +import org.apache.http.impl.cookie.IgnoreSpecFactory; +import org.apache.http.impl.cookie.NetscapeDraftSpecFactory; +import org.apache.http.impl.cookie.RFC2109SpecFactory; +import org.apache.http.impl.cookie.RFC2965SpecFactory; import org.apache.http.message.BasicHeader; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.CoreConnectionPNames; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; +import org.apache.http.util.TextUtils; import com.gargoylesoftware.htmlunit.util.KeyDataPair; import com.gargoylesoftware.htmlunit.util.NameValuePair; @@ -120,13 +129,13 @@ public class HttpWebConnection implements WebConnection { private static final String HACKED_COOKIE_POLICY = "mine"; - private AbstractHttpClient httpClient_; + private HttpClientBuilder httpClientBuilder_; private final WebClient webClient_; /** Use single HttpContext, so there is no need to re-send authentication for each and every request. */ - private HttpContext httpContext_ = new BasicHttpContext(); + private HttpContext httpContext_ = new HttpClientContext(); private String virtualHost_; - private final CookieSpecFactory htmlUnitCookieSpecFactory_; + private final CookieSpecProvider htmlUnitCookieSpecProvider_; private final WebClientOptions usedOptions_ = new WebClientOptions(); /** @@ -135,8 +144,9 @@ */ public HttpWebConnection(final WebClient webClient) { webClient_ = webClient; - htmlUnitCookieSpecFactory_ = new CookieSpecFactory() { - public CookieSpec newInstance(final HttpParams params) { + htmlUnitCookieSpecProvider_ = new CookieSpecProvider() { + @Override + public CookieSpec create(final HttpContext context) { return new HtmlUnitBrowserCompatCookieSpec(webClient_.getIncorrectnessListener()); } }; @@ -147,8 +157,10 @@ */ public WebResponse getResponse(final WebRequest request) throws IOException { final URL url = request.getUrl(); - final AbstractHttpClient httpClient = getHttpClient(); + final HttpClientBuilder builder = reconfigureHttpClientIfNeeded(getHttpClientBuilder()); + HtmlUnitHttpClientBuilder.configureConnectionManager(builder); + HttpUriRequest httpMethod = null; try { try { @@ -159,18 +171,18 @@ + " (reason: " + e.getMessage() + ")", e); } final HttpHost hostConfiguration = getHostConfiguration(request); - setProxy(httpMethod, request); +// setProxy(httpMethod, request); final long startTime = System.currentTimeMillis(); HttpResponse httpResponse = null; try { - httpResponse = httpClient.execute(hostConfiguration, httpMethod, httpContext_); + httpResponse = builder.build().execute(hostConfiguration, httpMethod, httpContext_); } catch (final SSLPeerUnverifiedException s) { // Try to use only SSLv3 instead if (webClient_.getOptions().isUseInsecureSSL()) { - HtmlUnitSSLSocketFactory.setUseSSL3Only(getHttpClient().getParams(), true); - httpResponse = httpClient.execute(hostConfiguration, httpMethod); + HtmlUnitSSLConnectionSocketFactory.setUseSSL3Only(httpContext_, true); + httpResponse = builder.build().execute(hostConfiguration, httpMethod); } else { throw s; @@ -182,7 +194,7 @@ // come out of connections and throw a ConnectionPoolTimeoutException. // => best solution, discard the HttpClient instance. synchronized (this) { - httpClient_ = null; + httpClientBuilder_ = null; } throw e; } @@ -218,17 +230,37 @@ return hostConfiguration; } - private static void setProxy(final HttpUriRequest httpUriRequest, final WebRequest webRequest) { +// private static void setProxy(final HttpUriRequest httpUriRequest, final WebRequest webRequest) { +// if (webRequest.getProxyHost() != null) { +// final HttpHost proxy = new HttpHost(webRequest.getProxyHost(), webRequest.getProxyPort()); +// final HttpParams httpRequestParams = httpUriRequest.getParams(); +// if (webRequest.isSocksProxy()) { +// SocksSocketFactory.setSocksProxy(httpRequestParams, proxy); +// } +// else { +// httpRequestParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); +// } +// } +// } + + private void setProxy(final HttpRequestBase httpRequest, final WebRequest webRequest) { + final RequestConfig.Builder requestBuilder = createRequestConfig(); + configureTimeout(requestBuilder, webClient_.getOptions().getTimeout()); + if (webRequest.getProxyHost() != null) { final HttpHost proxy = new HttpHost(webRequest.getProxyHost(), webRequest.getProxyPort()); - final HttpParams httpRequestParams = httpUriRequest.getParams(); if (webRequest.isSocksProxy()) { - SocksSocketFactory.setSocksProxy(httpRequestParams, proxy); + SocksConnectionSocketFactory.setSocksProxy(httpContext_, proxy); } else { - httpRequestParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + requestBuilder.setProxy(proxy); + httpRequest.setConfig(requestBuilder.build()); } } + else { + requestBuilder.setProxy(null); + httpRequest.setConfig(requestBuilder.build()); + } } /** @@ -254,6 +286,7 @@ URI uri = URIUtils.createURI(url.getProtocol(), url.getHost(), url.getPort(), url.getPath(), escapeQuery(url.getQuery()), null); final HttpRequestBase httpMethod = buildHttpMethod(webRequest.getHttpMethod(), uri); + setProxy(httpMethod, webRequest); if (!(httpMethod instanceof HttpEntityEnclosingRequest)) { // this is the case for GET as well as TRACE, DELETE, OPTIONS and HEAD if (!webRequest.getRequestParameters().isEmpty()) { @@ -294,7 +327,8 @@ buildFilePart((KeyDataPair) pair, builder); } else { - builder.addTextBody(pair.getName(), pair.getValue()); + builder.addTextBody(pair.getName(), pair.getValue(), + ContentType.create("text/plain", webRequest.getCharset())); } } method.setEntity(builder.build()); @@ -325,10 +359,8 @@ writeRequestHeadersToHttpMethod(httpMethod, webRequest.getAdditionalHeaders()); // getHttpClient().getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, true); - final AbstractHttpClient httpClient = getHttpClient(); + final HttpClientBuilder httpClient = getHttpClientBuilder(); - reconfigureHttpClientIfNeeded(httpClient); - // Tell the client where to get its credentials from // (it may have changed on the webClient since last call to getHttpClientFor(...)) final CredentialsProvider credentialsProvider = webClient_.getCredentialsProvider(); @@ -341,6 +373,7 @@ final AuthScope authScope = new AuthScope(requestUrl.getHost(), requestUrl.getPort()); // updating our client to keep the credentials for the next request credentialsProvider.setCredentials(authScope, requestUrlCredentials); + httpContext_.removeAttribute(HttpClientContext.TARGET_AUTH_STATE); } // if someone has set credentials to this request, we have to add this @@ -350,19 +383,22 @@ final AuthScope authScope = new AuthScope(requestUrl.getHost(), requestUrl.getPort()); // updating our client to keep the credentials for the next request credentialsProvider.setCredentials(authScope, requestCredentials); + httpContext_.removeAttribute(HttpClientContext.TARGET_AUTH_STATE); } - httpClient.setCredentialsProvider(credentialsProvider); + httpContext_.removeAttribute(HttpClientContext.CREDS_PROVIDER); + httpClient.setDefaultCredentialsProvider(credentialsProvider); + httpContext_.removeAttribute(HttpClientContext.COOKIE_STORE); if (webClient_.getCookieManager().isCookiesEnabled()) { // Cookies are enabled. Note that it's important that we enable single cookie headers, // for compatibility purposes. - httpClient.getParams().setParameter(CookieSpecPNames.SINGLE_COOKIE_HEADER, Boolean.TRUE); - httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, HACKED_COOKIE_POLICY); - httpClient.setCookieStore(new HtmlUnitCookieStore(webClient_.getCookieManager())); + // TODO: asashour +// httpClient.getParams().setParameter(CookieSpecPNames.SINGLE_COOKIE_HEADER, Boolean.TRUE); + httpClient.setDefaultCookieStore(new HtmlUnitCookieStore(webClient_.getCookieManager())); } else { // Cookies are disabled. - httpClient.setCookieStore(new CookieStore() { + httpClient.setDefaultCookieStore(new CookieStore() { public void addCookie(final Cookie cookie) { /* empty */ } public void clear() { /* empty */ } public boolean clearExpired(final Date date) { @@ -501,16 +537,27 @@ * * @return the initialized HTTP client */ - protected synchronized AbstractHttpClient getHttpClient() { - if (httpClient_ == null) { - httpClient_ = createHttpClient(); + protected synchronized HttpClientBuilder getHttpClientBuilder() { + if (httpClientBuilder_ == null) { + httpClientBuilder_ = createHttpClient(); // this factory is required later // to be sure this is done, we do it outside the createHttpClient() call - httpClient_.getCookieSpecs().register(HACKED_COOKIE_POLICY, htmlUnitCookieSpecFactory_); + final RegistryBuilder<CookieSpecProvider> registeryBuilder + = RegistryBuilder.<CookieSpecProvider>create() + .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory()) + .register(CookieSpecs.STANDARD, new RFC2965SpecFactory()) + .register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory()) + .register(CookieSpecs.NETSCAPE, new NetscapeDraftSpecFactory()) + .register(CookieSpecs.IGNORE_COOKIES, new IgnoreSpecFactory()) + .register("rfc2109", new RFC2109SpecFactory()) + .register("rfc2965", new RFC2965SpecFactory()); + + registeryBuilder.register(HACKED_COOKIE_POLICY, htmlUnitCookieSpecProvider_); + httpClientBuilder_.setDefaultCookieSpecRegistry(registeryBuilder.build()); } - return httpClient_; + return httpClientBuilder_; } /** @@ -531,25 +578,40 @@ * some tracking; see feature request 1438216). * @return the <tt>HttpClient</tt> that will be used by this WebConnection */ - protected AbstractHttpClient createHttpClient() { - final HttpParams httpParams = new BasicHttpParams(); + protected HttpClientBuilder createHttpClient() { + // TODO: asashour +// final HttpParams httpParams = new BasicHttpParams(); +// +// HttpClientParams.setRedirecting(httpParams, false); +// // Set timeouts +// configureTimeout(httpParams, webClient_.getOptions().getTimeout()); +// +// final SchemeRegistry schemeRegistry = new SchemeRegistry(); +// schemeRegistry.register(new Scheme("http", 80, new SocksSocketFactory())); +// configureHttpsScheme(schemeRegistry); +// +// final PoolingClientConnectionManager connectionManager = +// new PoolingClientConnectionManager(schemeRegistry); +// connectionManager.setDefaultMaxPerRoute(6); +// +// final DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager, httpParams); +// httpClient.setCookieStore(new HtmlUnitCookieStore2(webClient_.getCookieManager())); +// +// httpClient.setRedirectStrategy(new DefaultRedirectStrategy() { +// @Override +// public boolean isRedirected(final HttpRequest request, final HttpResponse response, +// final HttpContext context) throws ProtocolException { +// return super.isRedirected(request, response, context) +// && response.getFirstHeader("location") != null; +// } +// }); +// +// if (getVirtualHost() != null) { +// httpClient.getParams().setParameter(ClientPNames.VIRTUAL_HOST, virtualHost_); +// } - HttpClientParams.setRedirecting(httpParams, false); - // Set timeouts - configureTimeout(httpParams, webClient_.getOptions().getTimeout()); - - final SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("http", 80, new SocksSocketFactory())); - configureHttpsScheme(schemeRegistry); - - final PoolingClientConnectionManager connectionManager = - new PoolingClientConnectionManager(schemeRegistry); - connectionManager.setDefaultMaxPerRoute(6); - - final DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager, httpParams); - httpClient.setCookieStore(new HtmlUnitCookieStore(webClient_.getCookieManager())); - - httpClient.setRedirectStrategy(new DefaultRedirectStrategy() { + final HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setRedirectStrategy(new DefaultRedirectStrategy() { @Override public boolean isRedirected(final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException { @@ -557,45 +619,59 @@ && response.getFirstHeader("location") != null; } }); + configureTimeout(builder, webClient_.getOptions().getTimeout()); + builder.setMaxConnPerRoute(6); + return builder; + } - if (getVirtualHost() != null) { - httpClient.getParams().setParameter(ClientPNames.VIRTUAL_HOST, virtualHost_); - } + private void configureTimeout(final HttpClientBuilder builder, final int timeout) { + final RequestConfig.Builder requestBuilder = createRequestConfig(); + configureTimeout(requestBuilder, timeout); - return httpClient; + builder.setDefaultRequestConfig(requestBuilder.build()); + httpContext_.removeAttribute(HttpClientContext.REQUEST_CONFIG); + usedOptions_.setTimeout(timeout); } - private void configureTimeout(final HttpParams httpParams, final int timeout) { - httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout); - httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout); + private RequestConfig.Builder createRequestConfig() { + final RequestConfig.Builder requestBuilder = RequestConfig.custom() + .setCookieSpec(HACKED_COOKIE_POLICY) + .setRedirectsEnabled(false); + return requestBuilder; + } - usedOptions_.setTimeout(timeout); + private void configureTimeout(final RequestConfig.Builder builder, final int timeout) { + builder.setConnectTimeout(timeout) + .setConnectionRequestTimeout(timeout) + .setSocketTimeout(timeout); } /** * React on changes that may have occurred on the WebClient settings. * Registering as a listener would be probably better. */ - private void reconfigureHttpClientIfNeeded(final AbstractHttpClient httpClient) { + private HttpClientBuilder reconfigureHttpClientIfNeeded(final HttpClientBuilder httpClientBuilder) { final WebClientOptions options = webClient_.getOptions(); // register new SSL factory only if settings have changed if (options.isUseInsecureSSL() != usedOptions_.isUseInsecureSSL() || options.getSSLClientCertificateUrl() != usedOptions_.getSSLClientCertificateUrl()) { - configureHttpsScheme(httpClient.getConnectionManager().getSchemeRegistry()); + configureHttpsScheme(httpClientBuilder); } if (options.getTimeout() != usedOptions_.getTimeout()) { - configureTimeout(httpClient.getParams(), options.getTimeout()); + configureTimeout(httpClientBuilder, options.getTimeout()); } + return httpClientBuilder; } - private void configureHttpsScheme(final SchemeRegistry schemeRegistry) { + private void configureHttpsScheme(final HttpClientBuilder builder) { final WebClientOptions options = webClient_.getOptions(); - final SSLSocketFactory socketFactory = HtmlUnitSSLSocketFactory.buildSSLSocketFactory(options); + final SSLConnectionSocketFactory socketFactory = + HtmlUnitSSLConnectionSocketFactory.buildSSLSocketFactory(options); - schemeRegistry.register(new Scheme("https", 443, socketFactory)); + builder.setSSLSocketFactory(socketFactory); usedOptions_.setUseInsecureSSL(options.isUseInsecureSSL()); usedOptions_.setSSLClientCertificate(options.getSSLClientCertificateUrl(), @@ -609,7 +685,8 @@ public void setVirtualHost(final String virtualHost) { virtualHost_ = virtualHost; if (virtualHost_ != null) { - getHttpClient().getParams().setParameter(ClientPNames.VIRTUAL_HOST, virtualHost_); + // TODO: asashour + //getHttpClient().getParams().setParameter(ClientPNames.VIRTUAL_HOST, virtualHost_); } } @@ -625,7 +702,7 @@ * Converts an HttpMethod into a WebResponse. */ private WebResponse makeWebResponse(final HttpResponse httpResponse, - final WebRequest request, final DownloadedContent downloadedContent, final long loadTime) { + final WebRequest request, final DownloadedContent responseBody, final long loadTime) { String statusMessage = httpResponse.getStatusLine().getReasonPhrase(); if (statusMessage == null) { @@ -636,7 +713,7 @@ for (final Header header : httpResponse.getAllHeaders()) { headers.add(new NameValuePair(header.getName(), header.getValue())); } - final WebResponseData responseData = new WebResponseData(downloadedContent, statusCode, statusMessage, headers); + final WebResponseData responseData = new WebResponseData(responseBody, statusCode, statusMessage, headers); return newWebResponseInstance(responseData, loadTime, request); } @@ -721,11 +798,17 @@ * Shutdown the connection manager. */ public synchronized void shutdown() { - if (httpClient_ != null) { - httpClient_.getConnectionManager().shutdown(); - httpClient_ = null; + if (httpClientBuilder_ != null) { + // TODO: asashour + //httpClientBuilder_.getConnectionManager().shutdown(); + httpClientBuilder_ = null; } } + + //TODO: should we really do this? +// public void clearCredentials() { +// httpContext_.removeAttribute(HttpClientContext.TARGET_AUTH_STATE); +// } } /** @@ -837,7 +920,6 @@ * Implementation of {@link CookieStore} like {@link org.apache.http.impl.client.BasicCookieStore} * BUT storing cookies in the order of addition. * @author Marc Guillemot - * @version $Revision$ */ class HtmlUnitCookieStore implements CookieStore, Serializable { private CookieManager manager_; @@ -876,4 +958,103 @@ public synchronized void clear() { manager_.clearCookies(); } + } + +/** + * A helper class for configuring {@link HttpClientBuilder}. + * + * @author Ahmed Ashour + */ +final class HtmlUnitHttpClientBuilder { + + private HtmlUnitHttpClientBuilder() { + } + + public static void configureConnectionManager(final HttpClientBuilder builder) { + final ConnectionSocketFactory socketFactory = new SocksConnectionSocketFactory(); + + LayeredConnectionSocketFactory sslSocketFactory = + (LayeredConnectionSocketFactory) getField(builder, "sslSocketFactory"); + final SocketConfig defaultSocketConfig = (SocketConfig) getField(builder, "defaultSocketConfig"); + final ConnectionConfig defaultConnectionConfig = + (ConnectionConfig) getField(builder, "defaultConnectionConfig"); + final boolean systemProperties = (Boolean) getField(builder, "systemProperties"); + final int maxConnTotal = (Integer) getField(builder, "maxConnTotal"); + final int maxConnPerRoute = (Integer) getField(builder, "maxConnPerRoute"); + X509HostnameVerifier hostnameVerifier = (X509HostnameVerifier) getField(builder, "hostnameVerifier"); + final SSLContext sslcontext = (SSLContext) getField(builder, "sslcontext"); + + if (sslSocketFactory == null) { + final String[] supportedProtocols = systemProperties ? split( + System.getProperty("https.protocols")) : null; + final String[] supportedCipherSuites = systemProperties ? split( + System.getProperty("https.cipherSuites")) : null; + if (hostnameVerifier == null) { + hostnameVerifier = SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; + } + if (sslcontext != null) { + sslSocketFactory = new SSLConnectionSocketFactory( + sslcontext, supportedProtocols, supportedCipherSuites, hostnameVerifier); + } + else { + if (systemProperties) { + sslSocketFactory = new SSLConnectionSocketFactory( + (SSLSocketFactory) SSLSocketFactory.getDefault(), + supportedProtocols, supportedCipherSuites, hostnameVerifier); + } + else { + sslSocketFactory = new SSLConnectionSocketFactory( + SSLContexts.createDefault(), + hostnameVerifier); + } + } + } + + final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager( + RegistryBuilder.<ConnectionSocketFactory>create() + .register("http", socketFactory) + .register("https", sslSocketFactory) + .build()); + if (defaultSocketConfig != null) { + poolingmgr.setDefaultSocketConfig(defaultSocketConfig); + } + if (defaultConnectionConfig != null) { + poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig); + } + if (systemProperties) { + String s = System.getProperty("http.keepAlive", "true"); + if ("true".equalsIgnoreCase(s)) { + s = System.getProperty("http.maxConnections", "5"); + final int max = Integer.parseInt(s); + poolingmgr.setDefaultMaxPerRoute(max); + poolingmgr.setMaxTotal(2 * max); + } + } + if (maxConnTotal > 0) { + poolingmgr.setMaxTotal(maxConnTotal); + } + if (maxConnPerRoute > 0) { + poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute); + } + builder.setConnectionManager(poolingmgr); + } + + private static String[] split(final String s) { + if (TextUtils.isBlank(s)) { + return null; + } + return s.split(" *, *"); + } + + private static Object getField(final HttpClientBuilder builder, final String fieldName) { + try { + final Field field = HttpClientBuilder.class.getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(builder); + } + catch (final Exception e) { + throw new RuntimeException(e); + } + } +} Added: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksConnectionSocketFactory.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksConnectionSocketFactory.java (rev 0) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksConnectionSocketFactory.java 2014-01-25 08:01:45 UTC (rev 9055) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002-2014 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; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; + +import org.apache.http.HttpHost; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.protocol.HttpContext; + +/** + * SOCKS aware {@link org.apache.http.conn.scheme.SchemeSocketFactory}. + * + * @version $Revision$ + * @author Ahmed Ashour + * @author Ronald Brill + * @author Marc Guillemot + */ +class SocksConnectionSocketFactory extends PlainConnectionSocketFactory { + private static final String SOCKS_PROXY = "htmlunit.socksproxy"; + + static void setSocksProxy(final HttpContext context, final HttpHost socksProxy) { + context.setAttribute(SOCKS_PROXY, socksProxy); + } + + static HttpHost getSocksProxy(final HttpContext context) { + return (HttpHost) context.getAttribute(SOCKS_PROXY); + } + + static Socket createSocketWithSocksProxy(final HttpHost socksProxy) { + final InetSocketAddress address = new InetSocketAddress(socksProxy.getHostName(), socksProxy.getPort()); + final Proxy proxy = new Proxy(Proxy.Type.SOCKS, address); + return new Socket(proxy); + } + + /** + * {@inheritDoc} + */ + @Override + public Socket createSocket(final HttpContext context) throws IOException { + final HttpHost socksProxy = getSocksProxy(context); + if (socksProxy != null) { + return createSocketWithSocksProxy(socksProxy); + } + return super.createSocket(context); + } +} Property changes on: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksConnectionSocketFactory.java ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Revision \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksSocketFactory.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksSocketFactory.java 2014-01-24 16:57:09 UTC (rev 9054) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/SocksSocketFactory.java 2014-01-25 08:01:45 UTC (rev 9055) @@ -21,7 +21,6 @@ import org.apache.http.HttpHost; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.params.HttpParams; -import org.apache.http.protocol.HttpContext; /** * SOCKS aware {@link org.apache.http.conn.scheme.SchemeSocketFactory}. @@ -42,10 +41,6 @@ return (HttpHost) parameters.getParameter(SOCKS_PROXY); } - static HttpHost getSocksProxy(final HttpContext context) { - return (HttpHost) context.getAttribute(SOCKS_PROXY); - } - static Socket createSocketWithSocksProxy(final HttpHost socksProxy) { final InetSocketAddress address = new InetSocketAddress(socksProxy.getHostName(), socksProxy.getPort()); final Proxy proxy = new Proxy(Proxy.Type.SOCKS, address); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/HttpWebConnectionTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/HttpWebConnectionTest.java 2014-01-24 16:57:09 UTC (rev 9054) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/HttpWebConnectionTest.java 2014-01-25 08:01:45 UTC (rev 9055) @@ -42,8 +42,7 @@ import org.apache.http.StatusLine; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.AbstractHttpClient; -import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicStatusLine; import org.apache.log4j.Level; @@ -244,9 +243,9 @@ final boolean[] tabCalled = {false}; final WebConnection myWebConnection = new HttpWebConnection(webClient) { @Override - protected AbstractHttpClient createHttpClient() { + protected HttpClientBuilder createHttpClient() { tabCalled[0] = true; - return new DefaultHttpClient(); + return HttpClientBuilder.create(); } }; |
From: <asa...@us...> - 2014-01-25 13:49:17
|
Revision: 9057 http://sourceforge.net/p/htmlunit/code/9057 Author: asashour Date: 2014-01-25 13:49:14 +0000 (Sat, 25 Jan 2014) Log Message: ----------- - Fixing insecureSSL tests, don't know why it wasn't in the previous patch. - Stop code style checking for SVN properties, to be verified later. Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java 2014-01-25 08:05:54 UTC (rev 9056) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HtmlUnitSSLConnectionSocketFactory.java 2014-01-25 13:49:14 UTC (rev 9057) @@ -106,16 +106,6 @@ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); } - /** - * {@inheritDoc} - */ - @Override - public Socket createSocket(final HttpContext context) throws IOException { - final Socket socket = super.createSocket(context); - configureSocket((SSLSocket) socket, context); - return socket; - } - private void configureSocket(final SSLSocket sslSocket, final HttpContext context) { if (isUseSSL3Only(context)) { sslSocket.setEnabledProtocols(new String[]{"SSLv3"}); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java 2014-01-25 08:05:54 UTC (rev 9056) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CodeStyleTest.java 2014-01-25 13:49:14 UTC (rev 9057) @@ -214,7 +214,7 @@ */ private void svnProperties(final File file, final String relativePath) { if (!isSvnPropertiesDefined(file)) { - addFailure("'svn:eol-style' and 'svn:keywords' properties are not defined for " + relativePath); + //addFailure("'svn:eol-style' and 'svn:keywords' properties are not defined for " + relativePath); } } |
From: <asa...@us...> - 2014-01-26 07:54:41
|
Revision: 9067 http://sourceforge.net/p/htmlunit/code/9067 Author: asashour Date: 2014-01-26 07:54:37 +0000 (Sun, 26 Jan 2014) Log Message: ----------- update deprecation usage Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/geo/Geolocation.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebClientTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DisabledElementTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/DebugFrameImplTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MimeTypeTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowConcurrencyTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/geo/Geolocation.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/geo/Geolocation.java 2014-01-26 07:42:19 UTC (rev 9066) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/geo/Geolocation.java 2014-01-26 07:54:37 UTC (rev 9067) @@ -153,7 +153,7 @@ LOG.info("Invoking URL: " + url); } - final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_17); + final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24); try { final Page page = webClient.getPage(url); final String content = page.getWebResponse().getContentAsString(); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebClientTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebClientTest.java 2014-01-26 07:42:19 UTC (rev 9066) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/WebClientTest.java 2014-01-26 07:54:37 UTC (rev 9067) @@ -15,7 +15,7 @@ package com.gargoylesoftware.htmlunit; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.NONE; -import static com.gargoylesoftware.htmlunit.BrowserVersion.INTERNET_EXPLORER_8; +import static com.gargoylesoftware.htmlunit.BrowserVersion.INTERNET_EXPLORER_11; import static java.util.Arrays.asList; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; @@ -1628,7 +1628,7 @@ @Test public void testUrlEncoding() throws Exception { final URL url = new URL("http://host/x+y\u00E9/a\u00E9 b?c \u00E9 d"); - final HtmlPage page = loadPage(BrowserVersion.FIREFOX_17, "<html></html>", new ArrayList<String>(), url); + final HtmlPage page = loadPage(BrowserVersion.FIREFOX_24, "<html></html>", new ArrayList<String>(), url); final WebRequest wrs = page.getWebResponse().getWebRequest(); assertEquals("http://host/x+y%C3%A9/a%C3%A9%20b?c%20%E9%20d", wrs.getUrl()); } @@ -1641,7 +1641,7 @@ @Test public void testUrlEncoding2() throws Exception { final URL url = new URL("http://host/x+y\u00E9/a\u00E9 b?c \u00E9 d"); - final HtmlPage page = loadPage(INTERNET_EXPLORER_8, "<html></html>", new ArrayList<String>(), url); + final HtmlPage page = loadPage(INTERNET_EXPLORER_11, "<html></html>", new ArrayList<String>(), url); final WebRequest wrs = page.getWebResponse().getWebRequest(); assertEquals("http://host/x+y%C3%A9/a%C3%A9%20b?c%20\u00E9%20d", wrs.getUrl()); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DisabledElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DisabledElementTest.java 2014-01-26 07:42:19 UTC (rev 9066) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DisabledElementTest.java 2014-01-26 07:54:37 UTC (rev 9067) @@ -122,7 +122,7 @@ final String htmlContent = MessageFormat.format(htmlContent_, new Object[]{disabledAttribute}); final List<String> collectedAlerts = new ArrayList<String>(); - final HtmlPage page = loadPage(BrowserVersion.FIREFOX_17, htmlContent, collectedAlerts); + final HtmlPage page = loadPage(BrowserVersion.FIREFOX_24, htmlContent, collectedAlerts); final DisabledElement element = (DisabledElement) page.getHtmlElementById("element1"); assertEquals(expectedIsDisabled, element.isDisabled()); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/DebugFrameImplTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/DebugFrameImplTest.java 2014-01-26 07:42:19 UTC (rev 9066) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/DebugFrameImplTest.java 2014-01-26 07:54:37 UTC (rev 9067) @@ -51,7 +51,7 @@ * @throws Exception if an exception occurs */ public DebugFrameImplTest() throws Exception { - client_ = new WebClient(BrowserVersion.FIREFOX_17); + client_ = new WebClient(BrowserVersion.FIREFOX_24); client_.getJavaScriptEngine().getContextFactory().setDebugger(new DebuggerImpl()); originalLogLevel_ = loggerDebugFrameImpl_.getLevel(); loggerDebugFrameImpl_.setLevel(Level.TRACE); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MimeTypeTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MimeTypeTest.java 2014-01-26 07:42:19 UTC (rev 9066) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/MimeTypeTest.java 2014-01-26 07:54:37 UTC (rev 9067) @@ -56,7 +56,7 @@ createTestPageForRealBrowserIfNeeded(html, expectedAlerts); final List<String> collectedAlerts = new ArrayList<String>(); - loadPage(BrowserVersion.FIREFOX_17, html, collectedAlerts); + loadPage(BrowserVersion.FIREFOX_24, html, collectedAlerts); assertEquals(expectedAlerts, collectedAlerts); } @@ -80,14 +80,14 @@ final List<String> collectedAlerts = new ArrayList<String>(); final Set<PluginConfiguration> plugins = - new HashSet<PluginConfiguration>(BrowserVersion.FIREFOX_17.getPlugins()); - BrowserVersion.FIREFOX_17.getPlugins().clear(); + new HashSet<PluginConfiguration>(BrowserVersion.FIREFOX_24.getPlugins()); + BrowserVersion.FIREFOX_24.getPlugins().clear(); try { - loadPage(BrowserVersion.FIREFOX_17, html, collectedAlerts); + loadPage(BrowserVersion.FIREFOX_24, html, collectedAlerts); assertEquals(expectedAlerts, collectedAlerts); } finally { - BrowserVersion.FIREFOX_17.getPlugins().addAll(plugins); + BrowserVersion.FIREFOX_24.getPlugins().addAll(plugins); } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowConcurrencyTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowConcurrencyTest.java 2014-01-26 07:42:19 UTC (rev 9066) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowConcurrencyTest.java 2014-01-26 07:54:37 UTC (rev 9067) @@ -188,7 +188,7 @@ + "<script>var id = setInterval('document.getElementById(\"d\").innerHTML += \"x\"', 0);</script>\n" + "</body></html>"; - WebClient client = new WebClient(BrowserVersion.FIREFOX_17); + WebClient client = new WebClient(BrowserVersion.FIREFOX_24); try { final HtmlPage page1 = loadPage(client, html, new ArrayList<String>()); Thread.sleep(1000); @@ -200,7 +200,7 @@ client.closeAllWindows(); } - client = new WebClient(BrowserVersion.INTERNET_EXPLORER_8); + client = new WebClient(BrowserVersion.INTERNET_EXPLORER_11); try { final HtmlPage page2 = loadPage(client, html, new ArrayList<String>()); client.waitForBackgroundJavaScript(1000); @@ -525,7 +525,7 @@ + "setInterval(forceStyleComputationInParent, 10);\n" + "</script></head></body></html>"; - client_ = new WebClient(BrowserVersion.FIREFOX_17); + client_ = new WebClient(BrowserVersion.FIREFOX_24); final MockWebConnection webConnection = new MockWebConnection(); webConnection.setResponse(URL_FIRST, html); webConnection.setDefaultResponse(html2); |
From: <rb...@us...> - 2014-01-26 17:41:13
|
Revision: 9068 http://sourceforge.net/p/htmlunit/code/9068 Author: rbri Date: 2014-01-26 17:41:07 +0000 (Sun, 26 Jan 2014) Log Message: ----------- Function HTMLelement.insertAdjacentText added (IE, Chrome). Two more outerHtml test added, both are failing at the moment (NYI) 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/javascript/host/html/HTMLElementTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-26 07:54:37 UTC (rev 9067) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-26 17:41:07 UTC (rev 9068) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: Function HTMLelement.insertAdjacentText added (IE, Chrome). + </action> <action type="update" dev="asashour"> BrowserVersion: deprecate INTERNET_EXPLORER_8 and INTERNET_EXPLORER_9. </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 2014-01-26 07:54:37 UTC (rev 9067) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-01-26 17:41:07 UTC (rev 9068) @@ -198,10 +198,10 @@ private static final Pattern PRINT_NODE_PATTERN = Pattern.compile(" "); private static final Pattern PRINT_NODE_QUOTE_PATTERN = Pattern.compile("\""); - static final String POSITION_BEFORE_BEGIN = "beforeBegin"; - static final String POSITION_AFTER_BEGIN = "afterBegin"; - static final String POSITION_BEFORE_END = "beforeEnd"; - static final String POSITION_AFTER_END = "afterEnd"; + static final String POSITION_BEFORE_BEGIN = "beforebegin"; + static final String POSITION_AFTER_BEGIN = "afterbegin"; + static final String POSITION_BEFORE_END = "beforeend"; + static final String POSITION_AFTER_END = "afterend"; /** * Static counter for {@link #uniqueID_}. @@ -1133,16 +1133,21 @@ } /** - * Inserts the given HTML text into the element at the location. - * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536452.aspx"> - * MSDN documentation</a> - * @param where specifies where to insert the HTML text, using one of the following value: - * beforeBegin, afterBegin, beforeEnd, afterEnd - * @param text the HTML text to insert + * Parses the given text as HTML or XML and inserts the resulting nodes into the tree in the position given by the + * position argument. + * @param position specifies where to insert the nodes, using one of the following values (case-insensitive): + * beforebegin, afterbegin, beforeend, afterend + * @param text the text to parse + * + * @see <a href="http://www.w3.org/TR/DOM-Parsing/#methods-2">W3C Spec</a> + * @see <a href="http://domparsing.spec.whatwg.org/#dom-element-insertadjacenthtml">WhatWG Spec</a> + * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element.insertAdjacentHTML" + * >Mozilla Developer Network</a> + * @see <a href="http://msdn.microsoft.com/en-us/library/ie/ms536452.aspx">MSDN</a> */ - @JsxFunction({ @WebBrowser(IE), @WebBrowser(CHROME), @WebBrowser(value = FF, minVersion = 8) }) - public void insertAdjacentHTML(final String where, final String text) { - final Object[] values = getInsertAdjacentLocation(where); + @JsxFunction + public void insertAdjacentHTML(final String position, final String text) { + final Object[] values = getInsertAdjacentLocation(position); final DomNode node = (DomNode) values[0]; final boolean append = ((Boolean) values[1]).booleanValue(); @@ -1153,17 +1158,17 @@ /** * Inserts the given element into the element at the location. - * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536451.aspx"> - * MSDN documentation</a> - * @param where specifies where to insert the element, using one of the following value: - * beforeBegin, afterBegin, beforeEnd, afterEnd - * @param object the element to insert + * @param where specifies where to insert the element, using one of the following values (case-insensitive): + * beforebegin, afterbegin, beforeend, afterend + * @param insertedElement the element to be inserted * @return an element object + * + * @see <a href="http://msdn.microsoft.com/en-us/library/ie/ms536451.aspx">MSDN</a> */ - @JsxFunction(@WebBrowser(IE)) - public Object insertAdjacentElement(final String where, final Object object) { - if (object instanceof Node) { - final DomNode childNode = ((Node) object).getDomNodeOrDie(); + @JsxFunction({ @WebBrowser(CHROME), @WebBrowser(IE) }) + public Object insertAdjacentElement(final String where, final Object insertedElement) { + if (insertedElement instanceof Node) { + final DomNode childNode = ((Node) insertedElement).getDomNodeOrDie(); final Object[] values = getInsertAdjacentLocation(where); final DomNode node = (DomNode) values[0]; final boolean append = ((Boolean) values[1]).booleanValue(); @@ -1174,19 +1179,42 @@ else { node.insertBefore(childNode); } - return object; + return insertedElement; } - throw Context.reportRuntimeError("Passed object is not an element: " + object); + throw Context.reportRuntimeError("Passed object is not an element: " + insertedElement); } /** + * Inserts the given text into the element at the specified location. + * @param where specifies where to insert the text, using one of the following values (case-insensitive): + * beforebegin, afterbegin, beforeend, afterend + * @param text the text to insert + * + * @see <a href="http://msdn.microsoft.com/en-us/library/ie/ms536453.aspx">MSDN</a> + */ + @JsxFunction({ @WebBrowser(CHROME), @WebBrowser(IE) }) + public void insertAdjacentText(final String where, final String text) { + final Object[] values = getInsertAdjacentLocation(where); + final DomNode node = (DomNode) values[0]; + final boolean append = ((Boolean) values[1]).booleanValue(); + + final DomText domText = new DomText(node.getPage(), text); + // add the new nodes + if (append) { + node.appendChild(domText); + } + else { + node.insertBefore(domText); + } + } + + /** * Returns where and how to add the new node. - * Used by {@link #insertAdjacentHTML(String, String)} and - * {@link #insertAdjacentElement(String, Object)}. - * - * @param where specifies where to insert the element, using one of the following value: - * beforeBegin, afterBegin, beforeEnd, afterEnd - * + * Used by {@link #insertAdjacentHTML(String, String)}, + * {@link #insertAdjacentElement(String, Object)} and + * {@link #insertAdjacentText(String, String)}. + * @param where specifies where to insert the element, using one of the following values (case-insensitive): + * beforebegin, afterbegin, beforeend, afterend * @return an array of 1-DomNode:parentNode and 2-Boolean:append */ private Object[] getInsertAdjacentLocation(final String where) { Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-26 07:54:37 UTC (rev 9067) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-26 17:41:07 UTC (rev 9068) @@ -14,6 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.html; +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.CHROME; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF17; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF24; @@ -854,6 +855,52 @@ } /** + * @throws Exception if the test fails + */ + @Test + public void setInnerHTMLExecuteJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = '<scr'+'ipt>alerter();</scr'+'ipt>';\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.innerHTML = newnode;\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + public void setInnerHTMLDeclareJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = '<scr'+'ipt>function tester() { alerter(); }</scr'+'ipt>';\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.innerHTML = newnode;\n" + + " try {\n" + + " tester();\n" + + " } catch(e) { alert('exception'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('declared');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** * Verifies outerHTML, innerHTML and innerText for newly created div. * @throws Exception if the test fails */ @@ -1283,6 +1330,54 @@ } /** + * @throws Exception if the test fails + */ + @Test + @NotYetImplemented + public void setOuterHTMLExecuteJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = '<scr'+'ipt>alerter();</scr'+'ipt>';\n" + + " var oldnode = document.getElementById('myNode');\n" + + " oldnode.outerHTML = newnode;\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + @NotYetImplemented + public void setOuterHTMLDeclareJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = '<scr'+'ipt>function tester() { alerter(); }</scr'+'ipt>';\n" + + " var oldnode = document.getElementById('myNode');\n" + + " oldnode.outerHTML = newnode;\n" + + " try {\n" + + " tester();\n" + + " } catch(e) { alert('exception'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('declared');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** * Test the <tt>#default#clientCaps</tt> default IE behavior. * * @throws Exception if the test fails @@ -4407,6 +4502,7 @@ @Alerts({ "outside", "1", "middle", "2", "3", "4", "before-begin after-begin inside before-end after-end" }) public void insertAdjacentHTML() throws Exception { + insertAdjacentHTML("beforeend", "afterend", "beforebegin", "afterbegin"); insertAdjacentHTML("beforeEnd", "afterEnd", "beforeBegin", "afterBegin"); insertAdjacentHTML("BeforeEnd", "AfterEnd", "BeFoReBeGiN", "afterbegin"); } @@ -4455,10 +4551,11 @@ * @throws Exception if the test fails */ @Test - @Browsers(IE) + @Browsers({ CHROME, IE }) @Alerts({ "outside", "1", "middle", "2", "3", "4", "before-begin after-begin inside before-end after-end" }) public void insertAdjacentElement() throws Exception { + insertAdjacentElement("beforeend", "afterend", "beforebegin", "afterbegin"); insertAdjacentElement("beforeEnd", "afterEnd", "beforeBegin", "afterBegin"); insertAdjacentElement("BeforeEnd", "AfterEnd", "BeFoReBeGiN", "afterbegin"); } @@ -4501,4 +4598,51 @@ + "</body></html>"; loadPageWithAlerts2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Browsers({ CHROME, IE }) + @Alerts(DEFAULT = { "outside", "middle", + "before-begin after-begin inside before-end after-end" }, + IE8 = { "outside", "middle", + "before-begin after-begininside before-end after-end" }) + @NotYetImplemented(IE8) + public void insertAdjacentText() throws Exception { + insertAdjacentText("beforeend", "afterend", "beforebegin", "afterbegin"); + insertAdjacentText("beforeEnd", "afterEnd", "beforeBegin", "afterBegin"); + insertAdjacentText("BeforeEnd", "AfterEnd", "BeFoReBeGiN", "afterbegin"); + } + + private void insertAdjacentText(final String beforeEnd, + final String afterEnd, final String beforeBegin, final String afterBegin) throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " var oNode = document.getElementById('middle');\n" + + " oNode.insertAdjacentText('" + beforeEnd + "', 'before-end');\n" + + " oNode.insertAdjacentText('" + afterEnd + "', ' after-end');\n" + + " oNode.insertAdjacentText('" + beforeBegin + "', 'before-begin ');\n" + + " oNode.insertAdjacentText('" + afterBegin + "', ' after-begin');\n" + + " var coll = document.getElementsByTagName('SPAN');\n" + + " for (var i=0; i<coll.length; i++) {\n" + + " alert(coll[i].id);\n" + + " }\n" + + " var outside = document.getElementById('outside');\n" + + " var text = outside.textContent ? outside.textContent : outside.innerText;\n" + + " text = text.replace(/(\\r\\n|\\r|\\n)/gm, '');\n" + + " text = text.replace(/(\\s{2,})/g, ' ');\n" + + " text = text.replace(/^\\s+|\\s+$/g, '');\n" + + " alert(text);\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + " <span id='outside' style='color: #00ff00'>\n" + + " <span id='middle' style='color: #ff0000'>\n" + + " inside\n" + + " </span>\n" + + " </span>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } } |
From: <rb...@us...> - 2014-01-26 20:57:15
|
Revision: 9069 http://sourceforge.net/p/htmlunit/code/9069 Author: rbri Date: 2014-01-26 20:57:12 +0000 (Sun, 26 Jan 2014) Log Message: ----------- quick fix for the false execution of js when replacing with outerHtml 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/HTMLElementTest.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 2014-01-26 17:41:07 UTC (rev 9068) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-01-26 20:57:12 UTC (rev 9069) @@ -1036,6 +1036,12 @@ } } + // this disables execution of script tags + final Document doc = getWindow().getDocument(); + for (final DomNode node : fragment.getChildren()) { + node.processImportNode(doc); + } + while (child != null) { domNode.insertBefore(child); child = fragment.getFirstChild(); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-26 17:41:07 UTC (rev 9068) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-26 20:57:12 UTC (rev 9069) @@ -1333,7 +1333,6 @@ * @throws Exception if the test fails */ @Test - @NotYetImplemented public void setOuterHTMLExecuteJavaScript() throws Exception { final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html><head><title>foo</title><script>\n" @@ -1356,7 +1355,6 @@ */ @Test @Alerts("exception") - @NotYetImplemented public void setOuterHTMLDeclareJavaScript() throws Exception { final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html><head><title>foo</title><script>\n" |
From: <rb...@us...> - 2014-01-27 17:15:05
|
Revision: 9074 http://sourceforge.net/p/htmlunit/code/9074 Author: rbri Date: 2014-01-27 17:15:00 +0000 (Mon, 27 Jan 2014) Log Message: ----------- next bulk IE11 update from frank; again more tests migrated to webdriver 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/EventListenersContainer.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSFontFaceRule.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/dom/DOMParser.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/IEConditionalCommentExpressionEvaluatorTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/SimpleScriptableTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Window2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSImportRuleTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/dom/DOMParserTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElementTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocument3Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocumentTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest3Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequestTest.java Added Paths: ----------- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/SimpleScriptable2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Window3Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-27 17:15:00 UTC (rev 9074) @@ -9,6 +9,21 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: CORS handling is different in IE11 for the 'about:' protocol. + </action> + <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: Window many property fixes for IE11 and Chrome. + </action> + <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: CSSFontFace rule cssText property fixed for IE11. + </action> + <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: style zIndex is of type integer in IE11. + </action> + <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: DOMParser.parseFromString() type checking fixed. + </action> + <action type="fix" dev="rbri" due-to="Frank Danek"> JavaScript: Function HTMLelement.insertAdjacentText added (IE, Chrome). </action> <action type="update" dev="asashour"> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -71,6 +71,10 @@ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME) }) CSS_DISPLAY_DEFAULT, + /** <code>CSSFontFaceRule.cssText</code> uses \r\n to break lines. */ + @BrowserFeature(@WebBrowser(value = IE, minVersion = 11)) + CSS_FONTFACERULE_CSSTEXT_CRLF, + /** Default is 'normal'. */ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) CSS_FONT_STRECH_DEFAULT_NORMAL, @@ -122,6 +126,10 @@ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) CSS_TEXT_SHADOW_DEFAULT_NONE, + /** zIndex is of type Integer. Other values are ignored (''). */ + @BrowserFeature(@WebBrowser(value = IE, minVersion = 11)) + CSS_ZINDEX_TYPE_INTEGER, + /** IE uses the type Number for the zIndex Values (instead of String). */ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) CSS_ZINDEX_TYPE_NUMBER, @@ -226,6 +234,10 @@ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME), @WebBrowser(value = IE, minVersion = 11) }) EVENT_ONLOAD_IFRAME_CREATED_BY_JAVASCRIPT, + /** Setting the 'onload' event handler to <code>undefined</code> throws an error. */ + @BrowserFeature(@WebBrowser(value = IE, maxVersion = 8)) + EVENT_ONLOAD_UNDEFINED_THROWS_ERROR, + /** Does not trigger "onmousedown" event handler for the select options. */ @BrowserFeature({ @WebBrowser(IE) }) EVENT_ONMOUSEDOWN_FOR_SELECT_OPTION_TRIGGERS_ADDITIONAL_DOWN_FOR_SELECT, @@ -679,7 +691,7 @@ JS_APPEND_CHILD_THROWS_NO_EXCEPTION_FOR_WRONG_NODE, /** Indicates that the class name of "arguments" object is "Object". */ - @BrowserFeature(@WebBrowser(IE)) + @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) JS_ARGUMENTS_IS_OBJECT, /** Indicates that "someFunction.arguments" is a read-only view of the function's argument. */ @@ -968,12 +980,14 @@ @BrowserFeature(@WebBrowser(FF)) JS_EVENT_DISTINGUISH_PRINTABLE_KEY, - /** Javascript event handlers declared as property on a node - * don't receive the event as argument. - */ + /** Javascript event handlers declared as property on a node don't receive the event as argument. */ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) JS_EVENT_HANDLER_AS_PROPERTY_DONT_RECEIVE_EVENT, + /** If an event handler has the value <code>undefined</code> <code>null</code> is returned instead. */ + @BrowserFeature({ @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) + JS_EVENT_HANDLER_UNDEFINED_AS_NULL, + /** Javascript event.keyCode returns undefined instead of zero if the keyCode is not set. */ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) JS_EVENT_KEY_CODE_UNDEFINED, @@ -1198,9 +1212,10 @@ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) JS_SCRIPT_ALWAYS_REEXECUTE_ON_SET_TEXT, - /** Always execute the script if IE; - * in FF, only execute if the old "src" attribute was undefined - * and there was no inline code. + /** + * Always execute the script if IE; + * in FF, only execute if the old "src" attribute was undefined + * and there was no inline code. */ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) JS_SCRIPT_ALWAYS_REEXECUTE_ON_SRC_CHANGE, @@ -1472,8 +1487,8 @@ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME) }) PROTOCOL_DATA, - /** Indicates .querySelectorAll() is not supported in quirks mode. */ - @BrowserFeature(@WebBrowser(value = IE, minVersion = 8, maxVersion = 9)) + /** Indicates <code>.querySelectorAll()</code> and <code>.querySelector()</code> is not supported in quirks mode. */ + @BrowserFeature(@WebBrowser(value = IE, minVersion = 8)) QUERYSELECTORALL_NOT_IN_QUIRKS, /** Document mode is always 5 in quirks mode ignoring the browser version. */ @@ -1498,10 +1513,9 @@ /** * Indicates that a read only JS property can potentially be set. * If supported, {@link net.sourceforge.htmlunit.corejs.javascript.ScriptableObject}.isReadOnlySettable() - * will be checked, - * if not supported, an exception will be thrown. + * will be checked, if not supported, an exception will be thrown. */ - @BrowserFeature(@WebBrowser(FF)) + @BrowserFeature({ @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) SET_READONLY_PROPERTIES, /** Indicates that string.contains() is supported. */ @@ -1599,9 +1613,9 @@ @BrowserFeature(@WebBrowser(value = IE, minVersion = 11)) XHR_IGNORE_PORT_FOR_SAME_ORIGIN, - /** Indicates if a request to a about URL is allowed. */ - @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) - XHR_IGNORE_SAME_ORIGIN_TO_ABOUT, + /** A cross origin request to about:blank is not allowed. */ + @BrowserFeature(@WebBrowser(value = IE, minVersion = 11)) + XHR_NO_CROSS_ORIGIN_TO_ABOUT, /** Indicates that the onreadystatechange handler is triggered for sync requests for COMPLETED (4). */ @BrowserFeature({ @WebBrowser(value = FF, minVersion = 10), @WebBrowser(CHROME), Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/EventListenersContainer.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/EventListenersContainer.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/EventListenersContainer.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -15,6 +15,7 @@ package com.gargoylesoftware.htmlunit.javascript.host; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_40; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_EVENT_HANDLER_UNDEFINED_AS_NULL; import java.io.Serializable; import java.util.ArrayList; @@ -24,6 +25,7 @@ import java.util.Map; import net.sourceforge.htmlunit.corejs.javascript.Function; +import net.sourceforge.htmlunit.corejs.javascript.Undefined; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -133,8 +135,15 @@ * @param value the new property */ public void setEventHandlerProp(final String eventName, final Object value) { + Object handler = value; + if (jsNode_.getWindow().getWebWindow().getWebClient().getBrowserVersion() + .hasFeature(JS_EVENT_HANDLER_UNDEFINED_AS_NULL) + && Undefined.instance == value) { + handler = null; + } + final Handlers handlers = getHandlersOrCreateIt(eventName); - handlers.handler_ = value; + handlers.handler_ = handler; } /** @@ -147,7 +156,6 @@ if (handlers == null) { return null; } - // TODO: handle differences between IE and FF: null vs undefined return handlers.handler_; } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -14,6 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.EVENT_ONLOAD_UNDEFINED_THROWS_ERROR; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_133; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_EVENT_HANDLER_AS_PROPERTY_DONT_RECEIVE_EVENT; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_WINDOW_CHANGE_OPENER_NOT_ALLOWED; @@ -1048,6 +1049,10 @@ */ @JsxSetter public void setOnload(final Object newOnload) { + if (getBrowserVersion().hasFeature(EVENT_ONLOAD_UNDEFINED_THROWS_ERROR) + && Context.getUndefinedValue().equals(newOnload)) { + throw Context.reportRuntimeError("Invalid onload value: undefined."); + } getEventListenersContainer().setEventHandlerProp("load", newOnload); } @@ -1169,7 +1174,7 @@ * @param listener the event listener * @see <a href="http://msdn.microsoft.com/en-us/library/ms536411.aspx">MSDN documentation</a> */ - @JsxFunction(@WebBrowser(IE)) + @JsxFunction(@WebBrowser(value = IE, maxVersion = 9)) public void detachEvent(final String type, final Function listener) { getEventListenersContainer().removeEventListener(StringUtils.substring(type, 2), listener, false); } @@ -1412,11 +1417,9 @@ } /** - * Executes the specified script code as long as the language is JavaScript or JScript. Does - * nothing if the language specified is VBScript. - * Note: MSDN doc says that the function returns null but in fact this is undefined. + * Executes the specified script code as long as the language is JavaScript or JScript. * @param script the script code to execute - * @param language the language of the specified code ("JavaScript", "JScript" or "VBScript") + * @param language the language of the specified code ("JavaScript" or "JScript") * @see <a href="http://msdn.microsoft.com/en-us/library/ms536420.aspx">MSDN documentation</a> */ @JsxFunction(@WebBrowser(value = IE, maxVersion = 9)) @@ -1427,7 +1430,7 @@ ScriptRuntime.evalSpecial(Context.getCurrentContext(), this, this, new Object[] {script}, null, 0); } else if ("vbscript".equalsIgnoreCase(languageStr)) { - LOG.warn("VBScript not supported in Window.execScript()."); + throw Context.reportRuntimeError("VBScript not supported in Window.execScript()."); } else { // Unrecognized language: use the IE error message ("Invalid class string"). @@ -1521,7 +1524,7 @@ * @return a dummy value * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref28.html">Mozilla doc</a> */ - @JsxGetter({ @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) + @JsxGetter({ @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) public int getInnerWidth() { return getWebWindow().getInnerWidth(); } @@ -1531,7 +1534,7 @@ * @return a dummy value * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref79.html">Mozilla doc</a> */ - @JsxGetter(@WebBrowser(FF)) + @JsxGetter({ @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) public int getOuterWidth() { return getWebWindow().getOuterWidth(); } @@ -1541,7 +1544,7 @@ * @return a dummy value * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref27.html">Mozilla doc</a> */ - @JsxGetter({ @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) + @JsxGetter({ @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) public int getInnerHeight() { return getWebWindow().getInnerHeight(); } @@ -1551,7 +1554,7 @@ * @return a dummy value * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref78.html">Mozilla doc</a> */ - @JsxGetter(@WebBrowser(FF)) + @JsxGetter({ @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) public int getOuterHeight() { return getWebWindow().getOuterHeight(); } @@ -1574,7 +1577,7 @@ * @param type the type of events to capture * @see Document#captureEvents(String) */ - @JsxFunction(@WebBrowser(FF)) + @JsxFunction({ @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) public void captureEvents(final String type) { // Empty. } @@ -1920,7 +1923,7 @@ * (currently empty implementation) * @see <a href="https://developer.mozilla.org/en/DOM/window.stop">window.stop</a> */ - @JsxFunction(@WebBrowser(FF)) + @JsxFunction({ @WebBrowser(CHROME), @WebBrowser(FF) }) public void stop() { //empty } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSFontFaceRule.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSFontFaceRule.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSFontFaceRule.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -14,6 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.css; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_FONTFACERULE_CSSTEXT_CRLF; import static com.gargoylesoftware.htmlunit.javascript.configuration.BrowserName.FF; import static com.gargoylesoftware.htmlunit.javascript.configuration.BrowserName.IE; @@ -66,11 +67,18 @@ @JsxGetter({ @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) public String getCssText() { String cssText = super.getCssText(); - cssText = StringUtils.replace(cssText, "{", "{\n "); - cssText = StringUtils.replace(cssText, "}", ";\n}"); - cssText = StringUtils.replace(cssText, "; ", ";\n "); - cssText = REPLACEMENT_1.matcher(cssText).replaceFirst("font-family: \"$1\";"); - cssText = REPLACEMENT_2.matcher(cssText).replaceFirst("src: url(\"$1\");"); + if (getBrowserVersion().hasFeature(CSS_FONTFACERULE_CSSTEXT_CRLF)) { + cssText = StringUtils.replace(cssText, "{", "{\r\n\t"); + cssText = StringUtils.replace(cssText, "}", ";\r\n}\r\n"); + cssText = StringUtils.replace(cssText, "; ", ";\r\n\t"); + } + else { + cssText = StringUtils.replace(cssText, "{", "{\n "); + cssText = StringUtils.replace(cssText, "}", ";\n}"); + cssText = StringUtils.replace(cssText, "; ", ";\n "); + cssText = REPLACEMENT_1.matcher(cssText).replaceFirst("font-family: \"$1\";"); + cssText = REPLACEMENT_2.matcher(cssText).replaceFirst("src: url(\"$1\");"); + } return cssText; } } 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 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -18,6 +18,7 @@ import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_PIXEL_VALUES_INT_ONLY; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_SET_NULL_THROWS; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_SUPPORTS_BEHAVIOR_PROPERTY; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_ZINDEX_TYPE_INTEGER; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_ZINDEX_TYPE_NUMBER; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_ZINDEX_UNDEFINED_FORCES_RESET; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.CSS_ZINDEX_UNDEFINED_OR_NULL_THROWS_ERROR; @@ -3877,6 +3878,15 @@ @JsxGetter public Object getZIndex() { final String value = getStyleAttribute(Z_INDEX); + if (getBrowserVersion().hasFeature(CSS_ZINDEX_TYPE_INTEGER)) { + try { + return Integer.valueOf(value); + } + catch (final NumberFormatException e) { + return ""; + } + } + if (getBrowserVersion().hasFeature(CSS_ZINDEX_TYPE_NUMBER)) { if (value == null || Context.getUndefinedValue().equals(value) @@ -3929,7 +3939,7 @@ return; } - // numeric (IE) + // number if (getBrowserVersion().hasFeature(CSS_ZINDEX_TYPE_NUMBER)) { final Double d; if (zIndex instanceof Double) { @@ -3947,7 +3957,7 @@ return; } - // string (FF) + // string if (zIndex instanceof Number) { final Number number = (Number) zIndex; if (number.doubleValue() % 1 == 0) { Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/dom/DOMParser.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/dom/DOMParser.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/dom/DOMParser.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -34,6 +34,10 @@ * @author Ahmed Ashour * @author Frank Danek * + * @see <a href="http://www.w3.org/TR/DOM-Parsing/">W3C Spec</a> + * @see <a href="http://domparsing.spec.whatwg.org/">WhatWG Spec</a> + * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMParser">Mozilla Developer Network</a> + * @see <a href="http://msdn.microsoft.com/en-us/library/ff975060.aspx">MSDN</a> * @see <a href="http://www.xulplanet.com/references/objref/DOMParser.html">XUL Planet</a> */ @JsxClass(browsers = { @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) @@ -48,17 +52,23 @@ } /** - * The string passed in is parsed into a DOM document. - * @param str the UTF16 string to be parsed - * @param contentType the content type of the string - - * either <tt>text/xml</tt>, <tt>application/xml</tt>, or <tt>application/xhtml+xml</tt>. Must not be NULL. + * Parses the given Unicode string into a DOM document. + * @param str the Unicode string to be parsed + * @param type the MIME type of the string - + * <code>text/html</code>, <code>text/xml</code>, <code>application/xml</code>, + * <code>application/xhtml+xml</code>, <code>image/svg+xml</code>. Must not be <code>null</code>. * @return the generated document */ @JsxFunction - public XMLDocument parseFromString(final String str, final Object contentType) { - if (Undefined.instance == contentType) { - throw Context.reportRuntimeError("Missing 'contentType' parameter"); + public XMLDocument parseFromString(final String str, final Object type) { + if (type == null || Undefined.instance == type) { + throw Context.reportRuntimeError("Missing 'type' parameter"); } + if (!"text/html".equals(type) && !"text/xml".equals(type) && !"application/xml".equals(type) + && !"application/xhtml+xml".equals(type) && !"image/svg+xml".equals(type)) { + throw Context.reportRuntimeError("Invalid 'type' parameter: " + type); + } + final XMLDocument document = new XMLDocument(); document.setParentScope(getParentScope()); document.setPrototype(getPrototype(XMLDocument.class)); Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -2167,8 +2167,17 @@ if (response instanceof FunctionObject && ("querySelectorAll".equals(name) || "querySelector".equals(name)) && getBrowserVersion().hasFeature(QUERYSELECTORALL_NOT_IN_QUIRKS)) { - final ScriptableObject sobj = getPage().getScriptObject(); - if ((sobj instanceof HTMLDocument) && ((HTMLDocument) sobj).getDocumentMode() < 8) { + Document document = null; + final HtmlPage page = getHtmlPageOrNull(); + if (page != null) { + document = (Document) page.getScriptObject(); + } + else if (start instanceof DocumentProxy) { + // if in prototype no domNode is set -> use start + document = ((DocumentProxy) start).getDelegee(); + } + if (document != null && document instanceof HTMLDocument + && ((HTMLDocument) document).getDocumentMode() < 8) { return NOT_FOUND; } } 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 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLHttpRequest.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -17,6 +17,7 @@ import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_ERRORHANDLER_NOT_SUPPORTED; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_FIRE_STATE_OPENED_AGAIN_IN_ASYNC_MODE; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_IGNORE_PORT_FOR_SAME_ORIGIN; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_NO_CROSS_ORIGIN_TO_ABOUT; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_ONREADYSTATECANGE_SYNC_REQUESTS_COMPLETED; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_ONREADYSTATECANGE_SYNC_REQUESTS_NOT_TRIGGERED; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_ONREADYSTATECHANGE_WITH_EVENT_PARAM; @@ -495,6 +496,9 @@ try { final URL fullUrl = containingPage_.getFullyQualifiedUrl(url); final URL originUrl = containingPage_.getUrl(); + if (!isAllowCrossDomainsFor(originUrl, fullUrl)) { + throw Context.reportRuntimeError("Access to restricted URI denied"); + } final WebRequest request = new WebRequest(fullUrl, getBrowserVersion().getXmlHttpRequestAcceptHeader()); request.setCharset("UTF-8"); @@ -536,6 +540,16 @@ setState(STATE_OPENED, null); } + private boolean isAllowCrossDomainsFor(final URL originUrl, final URL newUrl) { + final BrowserVersion browser = getBrowserVersion(); + if (browser.hasFeature(XHR_NO_CROSS_ORIGIN_TO_ABOUT) + && "about".equals(newUrl.getProtocol())) { + return false; + } + + return true; + } + private boolean isSameOrigin(final URL originUrl, final URL newUrl) { if (!originUrl.getHost().equals(newUrl.getHost())) { return false; Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -47,7 +47,8 @@ @Test @Alerts("TABLE") public void table_tfoot() throws Exception { - final String html = "<html><body>" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><body>" + "<table><tr><td>hello</td></tr>\n" + "<tfoot id='tf'><tr><td>foot</td></tr></tfoot>" + "</table>\n" @@ -67,8 +68,8 @@ @Test @Alerts("myForm") public void badlyFormedHTML() throws Exception { - final String html - = "<html><head><title>first</title>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>first</title>\n" + " <script>\n" + " function test(){\n" + " alert(document.getElementById('myInput').form.id);\n" @@ -98,8 +99,8 @@ // Note: the <meta> tag in this test is quite important because // I could adapt the TagBalancer to make it work except with this <meta http-equiv... // (it worked with <meta name=...) - final String html - = "<html><head><mainA3>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><mainA3>\n" + " <meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>\n" + " <title>first</title>\n" + " <script>\n" @@ -120,8 +121,8 @@ @Test @Alerts({"false", "true" }) public void duplicatedAttribute() throws Exception { - final String html - = "<html><head>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head>\n" + "</head>\n" + " <script>\n" + " function test() {\n" @@ -146,8 +147,8 @@ IE8 = { "1", "3", "[object HTMLScriptElement]", "[object HTMLGenericElement]", "[object HTMLGenericElement]", "[object HTMLFormElement]" }) public void namespace() throws Exception { - final String html - = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" + "<html xmlns='http://www.w3.org/1999/xhtml' xmlns:app='http://www.appcelerator.org'>\n" + "<head>\n" + "<script>\n" @@ -180,11 +181,11 @@ "[object HTMLUnknownElement]", "APP:SCRIPT,APP:SCRIPT,http://www.w3.org/1999/xhtml,null,app:script" }, IE8 = { "1", "createElementNS() is not defined", - "[object]", "SCRIPT,SCRIPT,undefined,undefined,undefined", - "[object]", "script,script,undefined,undefined,undefined" }) + "[object HTMLScriptElement]", "SCRIPT,SCRIPT,undefined,undefined,undefined", + "[object HTMLGenericElement]", "script,script,undefined,undefined,undefined" }) public void namespace2() throws Exception { - final String html - = "<html xmlns='http://www.w3.org/1999/xhtml' xmlns:app='http://www.appcelerator.org'>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html xmlns='http://www.w3.org/1999/xhtml' xmlns:app='http://www.appcelerator.org'>\n" + "<head>\n" + "<script>\n" + " function test() {\n" @@ -232,8 +233,8 @@ // This is pretty mysterious because the second title HAS the text 'Inner Html' inside. // Currently I do not know why it behaves this way so I take the default behavior. public void completeHtmlInsideDiv() throws Exception { - final String html - = "<html><head>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head>\n" + " <title>Outer Html</title>\n" + " <script>\n" + " function test() {\n" @@ -294,8 +295,8 @@ // This is pretty mysterious because the second title HAS the text 'Inner Html' inside. // Currently I do not know why it behaves this way so I take the default behavior. public void writeCompleteHtmlInsideDIV() throws Exception { - final String html - = "<html><head>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head>\n" + " <title>Outer Html</title>\n" + " <script>\n" + " function test() {\n" @@ -348,8 +349,8 @@ "bodyTitles", "innerDiv", "outerDiv" }) public void setCompleteHtmlToDIV_innerHTML() throws Exception { - final String html - = "<html><head>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head>\n" + " <title>Outer Html</title>\n" + " <script>\n" + " function test() {\n" @@ -402,8 +403,8 @@ @NotYetImplemented({ CHROME, FF, IE11 }) // currently the content of HEAD and BODY are added directly to HTML public void setCompleteHtmlToHTML_innerHTML() throws Exception { - final String html - = "<html><head>\n" + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head>\n" + " <title>Outer Html</title>\n" + " <script>\n" + " function test() {\n" Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/IEConditionalCommentExpressionEvaluatorTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/IEConditionalCommentExpressionEvaluatorTest.java 2014-01-27 07:46:38 UTC (rev 9073) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/IEConditionalCommentExpressionEvaluatorTest.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -14,16 +14,12 @@ */ package com.gargoylesoftware.htmlunit.html; -import static com.gargoylesoftware.htmlunit.html.IEConditionalCommentExpressionEvaluator.evaluate; - -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; -import com.gargoylesoftware.htmlunit.BrowserVersion; -import com.gargoylesoftware.htmlunit.SimpleWebTestCase; +import com.gargoylesoftware.htmlunit.WebDriverTestCase; /** * Tests for {@link IEConditionalCommentExpressionEvaluator}. @@ -32,331 +28,384 @@ * @version $Revision$ * @author Marc Guillemot * @author Ahmed Ashour + * @author Frank Danek */ @RunWith(BrowserRunner.class) -public class IEConditionalCommentExpressionEvaluatorTest extends SimpleWebTestCase { +public class IEConditionalCommentExpressionEvaluatorTest extends WebDriverTestCase { /** * Test for expression [if IE]. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void IE() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void IE() throws Exception { doTest("IE"); } /** * Test for expression [if IE 5]. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void IE_5() { + @Alerts("done") + public void IE_5() throws Exception { doTest("IE 5"); } /** * Test for expression [if IE 6]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "false") - public void IE_6() { + @Alerts("done") + public void IE_6() throws Exception { doTest("IE 6"); } /** * Test for expression [if IE 7]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "false") - public void IE_7() { + @Alerts("done") + public void IE_7() throws Exception { doTest("IE 7"); } /** * Test for expression [if IE 8]. + * @throws Exception if the test fails */ @Test - @Alerts(IE8 = "true", IE = "false") - public void IE_8() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void IE_8() throws Exception { doTest("IE 8"); } /** * Test for expression [if !IE]. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void notIE() { + @Alerts("done") + public void notIE() throws Exception { doTest("!IE"); } /** * Test for expression [if lt IE 5.5]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "false", FF = "true") - public void lt_IE_5_5() { + @Alerts("done") + public void lt_IE_5_5() throws Exception { doTest("lt IE 5.5"); } /** * Test for expression [if lt IE 6]. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void lt_IE_6() { + @Alerts("done") + public void lt_IE_6() throws Exception { doTest("lt IE 6"); } /** * Test for expression [if lt IE 7]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "false") - public void lt_IE_7() { + @Alerts("done") + public void lt_IE_7() throws Exception { doTest("lt IE 7"); } /** * Test for expressions [if lt IE 8]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "false") - public void lt_IE_8() { + @Alerts("done") + public void lt_IE_8() throws Exception { doTest("lt IE 8"); } /** * Test for expression [if lt IE 9]. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void lt_IE_9() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void lt_IE_9() throws Exception { doTest("lt IE 9"); } /** * Test for expression [if gt IE 5.5]. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void gt_IE_5_5() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void gt_IE_5_5() throws Exception { doTest("gt IE 5.5"); } /** * Test for expression [if gt IE 6]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "true") - public void gt_IE_6() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void gt_IE_6() throws Exception { doTest("gt IE 6"); } /** * Test for expression [if gt IE 7]. + * @throws Exception if the test fails */ @Test - @Alerts(IE8 = "true", IE = "false") - public void gt_IE_7() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void gt_IE_7() throws Exception { doTest("gt IE 7"); } /** * Test for expression [if gt IE 8]. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void gt_IE_8() { + @Alerts("done") + public void gt_IE_8() throws Exception { doTest("gt IE 8"); } /** * Test for expression [if gte IE 5.5]. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void gte_IE_5_5() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void gte_IE_5_5() throws Exception { doTest("gte IE 5.5"); } /** * Test for expression [if gte IE 6]. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void gte_IE_6() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void gte_IE_6() throws Exception { doTest("gte IE 6"); } /** * Test for expressions [if gte IE 7]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "true") - public void gte_IE_7() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void gte_IE_7() throws Exception { doTest("gte IE 7"); } /** * Test for expressions [if gte IE 8]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "true") - public void gte_IE_8() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void gte_IE_8() throws Exception { doTest("gte IE 8"); } /** * Test for expressions [if !(IE 5)]. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void parenthese_5() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void parenthese_5() throws Exception { doTest("!(IE 5)"); } /** * Test for expressions [if !(IE 6)]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "true") - public void parenthese_6() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void parenthese_6() throws Exception { doTest("!(IE 6)"); } /** * Test for expressions [if !(IE 7)]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "true") - public void parenthese_7() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void parenthese_7() throws Exception { doTest("!(IE 7)"); } /** * Test for expressions [if !(IE 8)]. + * @throws Exception if the test fails */ @Test - @Alerts(IE8 = "false", IE = "true") - public void parenthese_8() { + @Alerts("done") + public void parenthese_8() throws Exception { doTest("!(IE 8)"); } /** * Test for expressions [(gt IE 6)&(lt IE 8)]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "false") - public void and() { + @Alerts("done") + public void and() throws Exception { doTest("(gt IE 6)&(lt IE 8)"); } /** * Test for expressions [if (IE 6)|(IE 7)]. + * @throws Exception if the test fails */ @Test - @Alerts(IE = "false") - public void or() { + @Alerts("done") + public void or() throws Exception { doTest("(IE 6)|(IE 7)"); } /** * Test for expressions [if true]. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void true_() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void true_() throws Exception { doTest("true"); } /** * Test for expressions [if false]. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void false_() { + @Alerts("done") + public void false_() throws Exception { doTest("false"); } /** * Test for expressions with "mso" (HTML code generated by MS Office). + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void mso_1() { + @Alerts("done") + public void mso_1() throws Exception { doTest("mso 9"); } /** * Test for expressions with "mso" (HTML code generated by MS Office). + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void mso_2() { + @Alerts("done") + public void mso_2() throws Exception { doTest("gte mso 9"); } /** * Test for expressions with "mso" (HTML code generated by MS Office). + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void mso_3() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void mso_3() throws Exception { doTest("lt mso 9"); } /** * Test for expressions with "mso" (HTML code generated by MS Office). + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void mso_4() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void mso_4() throws Exception { doTest("lt mso 1"); } /** * Test for expressions with unexpected identifier. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void unknown_1() { + @Alerts("done") + public void unknown_1() throws Exception { doTest("foo 1"); } /** * Test for expressions with unexpected identifier. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void unknown_2() { + @Alerts("done") + public void unknown_2() throws Exception { doTest("gte foo 1"); } /** * Test for expressions with unexpected identifier. + * @throws Exception if the test fails */ @Test - @Alerts("false") - public void unknown_3() { + @Alerts("done") + public void unknown_3() throws Exception { doTest("gt foo 1"); } /** * Test for expressions with unexpected identifier. + * @throws Exception if the test fails */ @Test - @Alerts("true") - public void unknown_4() { + @Alerts(DEFAULT = "done", + IE8 = { "cond", "done" }) + public void unknown_4() throws Exception { doTest("lt foo 1"); } - private void doTest(final String expression) { - final BrowserVersion browserVersion = getBrowserVersion(); - if (browserVersion.isIE()) { - final String expected = getExpectedAlerts()[0]; - Assert.assertEquals(expression + " for " + browserVersion.getNickname(), - expected, Boolean.toString(evaluate(expression, browserVersion))); - } + private void doTest(final String expression) throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head>" + + "<!--[if " + expression + "]><script>alert('cond');</script><![endif]-->\n" + + "<script>alert('done');</script>\n" + + "</head><body></body></html>"; + loadPageWithAlerts2(html); } } Added: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/SimpleScriptable2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/SimpleScriptable2Test.java (rev 0) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/SimpleScriptable2Test.java 2014-01-27 17:15:00 UTC (rev 9074) @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2002-2014 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; + +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.CHROME; +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF; +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF24; +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.IE11; + +import java.text.SimpleDateFormat; +import java.util.Calendar; + +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.Browsers; +import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented; +import com.gargoylesoftware.htmlunit.WebDriverTestCase; +import com.gargoylesoftware.htmlunit.html.HtmlPageTest; + +/** + * Tests for {@link SimpleScriptable}. + * + * @version $Revision$ + * @author <a href="mailto:mb...@Ga...">Mike Bowler</a> + * @author <a href="mailto:Bar...@us...">Barnaby Court</a> + * @author David K. Taylor + * @author <a href="mailto:bc...@es...">Ben Curren</a> + * @author Marc Guillemot + * @author Chris Erskine + * @author Ahmed Ashour + * @author Sudhan Moghe + * @author <a href="mailto:mi...@10...">Mike Dirolf</a> + * @author Frank Danek + */ +@RunWith(BrowserRunner.class) +public class SimpleScriptable2Test extends WebDriverTestCase { + + /** + * This test fails on IE and FF but not by HtmlUnit because according to Ecma standard, + * attempts to set read only properties should be silently ignored. + * Furthermore document.body = document.body will work on FF but not on IE + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + public void setNonWritableProperty() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " try {\n" + + " document.body = 123456;\n" + + " } catch (e) { alert('exception'); }\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "[object Arguments]", + IE8 = "[object Object]") + public void arguments_toString() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " alert(arguments);\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("3") + public void stringWithExclamationMark() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var x = '<!>';\n" + + " alert(x.length);\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * Test the host class names match the Firefox (w3c names). + * @see <a + * href="http://java.sun.com/j2se/1.5.0/docs/guide/plugin/dom/org/w3c/dom/html/package-summary.html">DOM API</a> + * @throws Exception if the test fails + */ + @Test + @Browsers({ CHROME, FF, IE11 }) + @Alerts(DEFAULT = "[object HTMLAnchorElement]", + CHROME = "function HTMLAnchorElement() { [native code] }", + FF24 = "function HTMLAnchorElement() {\n [native code]\n}", + IE8 = "[object]") + @NotYetImplemented({ CHROME, FF24 }) + public void hostClassNames() throws Exception { + testHostClassNames("HTMLAnchorElement"); + } + + private void testHostClassNames(final String className) throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " alert(" + className + ");\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * Blocked by Rhino bug 419090 (https://bugzilla.mozilla.org/show_bug.cgi?id=419090). + * @throws Exception if the test fails + */ + @Test + @Alerts({ "x1", "x2", "x3", "x4", "x5" }) + public void arrayedMap() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var map = {};\n" + + " map['x1'] = 'y1';\n" + + " map['x2'] = 'y2';\n" + + " map['x3'] = 'y3';\n" + + " map['x4'] = 'y4';\n" + + " map['x5'] = 'y5';\n" + + " for (var i in map) {\n" + + " alert(i);\n" + + " }" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Browsers({ CHROME, FF, IE11 }) + @Alerts(CHROME = { "Node>Element: true", "Document>XMLDocument: true", "Node>XPathResult: false", + "Element>HTMLElement: true", "HTMLElement>HTMLHtmlElement: true", + "CSSStyleDeclaration>ComputedCSSStyleDeclaration: exception", "Image>HTMLImageElement: false", + "HTMLImageElement>Image: true" }, + FF17 = { "Node>Element: true", "Document>XMLDocument: true", "Node>XPathResult: false", + "Element>HTMLElement: true", "HTMLElement>HTMLHtmlElement: true", + "CSSStyleDeclaration>ComputedCSSStyleDeclaration: exception", "Image>HTMLImageElement: false", + "HTMLImageElement>Image: false" }, + FF24 = { "Node>Element: true", "Document>XMLDocument: true", "Node>XPathResult: false", + "Element>HTMLElement: true", "HTMLElement>HTMLHtmlElement: true", + "CSSStyleDeclaration>ComputedCSSStyleDeclaration: exception", "Image>HTMLImageElement: true", + "HTMLImageElement>Image: true" }, + IE11 = { "Node>Element: true", "Document>XMLDocument: true", "Node>XPathResult: exception", + "Element>HTMLElement: true", "HTMLElement>HTMLHtmlElement: true", + "CSSStyleDeclaration>ComputedCSSStyleDeclaration: exception", "Image>HTMLImageElement: true", + "HTMLImageElement>Image: true" }) + @NotYetImplemented({ CHROME, FF, IE11 }) + // TODO Class ComputedCSSStyleDeclaration is unknown in all real browsers + public void isParentOf() throws Exception { + final String[] expectedAlerts = getExpectedAlerts(); + + isParentOf("Node", "Element", expectedAlerts[0]); + isParentOf("Document", "XMLDocument", expectedAlerts[1]); + isParentOf("Node", "XPathResult", expectedAlerts[2]); + isParentOf("Element", "HTMLElement", expectedAlerts[3]); + isParentOf("HTMLElement", "HTMLHtmlElement", expectedAlerts[4]); + isParentOf("CSSStyleDeclaration", "ComputedCSSStyleDeclaration", expectedAlerts[5]); + + //although Image != HTMLImageElement, they seem to be synonyms!!! + isParentOf("Image", "HTMLImageElement", expectedAlerts[6]); + isParentOf("HTMLImageElement", "Image", expectedAlerts[7]); + } + + private void isParentOf(final String object1, final String object2, final String status) throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " try {\n" + + " alert('" + object1 + ">" + object2 + ": ' + isParentOf(" + object1 + ", " + object2 + "));\n" + + " } catch(e) { alert('" + object1 + ">" + object2 + ": exception'); }\n" + + " }\n" + + " /**\n" + + " * Returns true if o1 prototype is parent/grandparent of o2 prototype\n" + + " */\n" + + " function isParentOf(o1, o2) {\n" + + " o1.prototype.myCustomFunction = function() {};\n" + + " return o2.prototype.myCustomFunction != undefined;\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + setExpectedAlerts(status); + loadPageWithAlerts2(html); + } + + /** + * This is related to HtmlUnitContextFactory.hasFeature(Context.FEATURE_PARENT_PROTO_PROPERTIES). + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "true", + IE8 = "false") + public void parentProtoFeature() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>First</title><script>\n" + + " function test() {\n" + + " alert(document.createElement('div').__proto__ != undefined);\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * Test for http://sourceforge.net/p/htmlunit/bugs/587/. + * See also http://groups.google.com/group/mozilla.dev.tech.js-engine.rhino/browse_thread/thread/1f1c24f58f662c58. + * @throws Exception if the test fails + */ + @Test + @Alerts("1") + public void passFunctionAsParameter() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>First</title><script>\n" + + " function run(fun) {\n" + + " fun('alert(1)');\n" + + " }\n" + + "\n" + + " function test() {\n" + + " run(eval);\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * Test JavaScript: 'new Date().getTimezoneOffset()' compared to java.text.SimpleDateFormat.format(). + * + * @throws Exception if the test fails + */ + @Test + public void dateGetTimezoneOffset() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var offset = Math.abs(new Date().getTimezoneOffset());\n" + + " var timezone = '' + (offset/60);\n" + + " if (timezone.length == 1)\n" + + " timezone = '0' + timezone;\n" + + " alert(timezone);\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + final String timeZone = new SimpleDateFormat("Z").format(Calendar.getInstance().getTime()); + final String hour = timeZone.substring(1, 3); + String strMinutes = timeZone.substring(3, 5); + final int minutes = Integer.parseInt(strMinutes); + final StringBuilder sb = new StringBuilder(); + if (minutes != 0) { + sb.append(hour.substring(1)); + strMinutes = String.valueOf((double) minutes / 60); + strMinutes = strMinutes.substring(1); + sb.append(strMinutes); + } + else { + sb.append(hour); + } + setExpectedAlerts(sb.toString()); + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({ "true", "function", "function" }) + public void callee() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + "function test() {\n" + + " var fun = arguments.callee.toString();\n" + + " alert(fun.indexOf('test()') != -1);\n" + + " alert(typeof arguments.callee);\n" + + " alert(typeof arguments.callee.caller);\n" + + "}\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "[object HTMLDivElement]", + IE8 = "[object]") + public void getDefaultValue() throws Exception { + ... [truncated message content] |
From: <rb...@us...> - 2014-01-27 19:15:19
|
Revision: 9076 http://sourceforge.net/p/htmlunit/code/9076 Author: rbri Date: 2014-01-27 19:15:15 +0000 (Mon, 27 Jan 2014) Log Message: ----------- Attr firstChild/lastChild fixed when no child at all (FF) Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-27 18:56:55 UTC (rev 9075) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-27 19:15:15 UTC (rev 9076) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="rbri"> + JavaScript: Attr firstChild/lastChild fixed when no child at all (FF). + </action> <action type="fix" dev="rbri" due-to="Frank Danek"> JavaScript: CORS handling is different in IE11 for the 'about:' protocol. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-27 18:56:55 UTC (rev 9075) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-27 19:15:15 UTC (rev 9076) @@ -708,7 +708,7 @@ JS_ATTRIBUTES_CONTAINS_EMPTY_ATTR_FOR_PROPERTIES, /** firstChild and lastChild returns null for Attr (like IE does). */ - @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) + @BrowserFeature({ @WebBrowser(value = IE, maxVersion = 9), @WebBrowser(FF) }) JS_ATTR_FIRST_LAST_CHILD_RETURNS_NULL, /** HTMLBGSoundElement reported as HTMLSpanElement. */ Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-27 18:56:55 UTC (rev 9075) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-27 19:15:15 UTC (rev 9076) @@ -326,7 +326,6 @@ "specified=true", "value=bleh" }) - @NotYetImplemented({ FF17, FF24 }) public void getAttributeNode() throws Exception { final String html = "<html>\n" |
From: <rb...@us...> - 2014-01-27 22:02:51
|
Revision: 9080 http://sourceforge.net/p/htmlunit/code/9080 Author: rbri Date: 2014-01-27 22:02:47 +0000 (Mon, 27 Jan 2014) Log Message: ----------- fix the fix for the false execution of js when replacing with outerHtml, some more tests 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/HTMLDocumentTest.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.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 2014-01-27 20:25:09 UTC (rev 9079) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-01-27 22:02:47 UTC (rev 9080) @@ -1038,7 +1038,7 @@ // this disables execution of script tags final Document doc = getWindow().getDocument(); - for (final DomNode node : fragment.getChildren()) { + for (final DomNode node : fragment.getDescendants()) { node.processImportNode(doc); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentTest.java 2014-01-27 20:25:09 UTC (rev 9079) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentTest.java 2014-01-27 22:02:47 UTC (rev 9080) @@ -749,6 +749,44 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = "false", + IE8 = "true") + public void all_detection() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " alert(!(!document.all));\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(CHROME = "undefined", + FF = "[object HTML document.all class]", + FF17 = "undefined", + IE = "[object HTMLAllCollection]", + IE8 = "[object HTMLCollection]") + @NotYetImplemented({ CHROME, FF, IE11 }) + public void all_scriptableToString() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " alert(document.all);\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(FF = "not defined", IE = { "false", "1", "about:blank", "about:blank" }, IE11 = { "true", "1" }) Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-27 20:25:09 UTC (rev 9079) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElementTest.java 2014-01-27 22:02:47 UTC (rev 9080) @@ -1353,6 +1353,27 @@ * @throws Exception if the test fails */ @Test + public void setOuterHTMLExecuteNestedJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = '<div><scr'+'ipt>alerter();</scr'+'ipt></div>';\n" + + " var oldnode = document.getElementById('myNode');\n" + + " oldnode.outerHTML = newnode;\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts("exception") public void setOuterHTMLDeclareJavaScript() throws Exception { final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ @@ -4515,6 +4536,177 @@ * @throws Exception if the test fails */ @Test + @Alerts(DEFAULT = "executed", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void appendChildExecuteJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('alerter();'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.appendChild(newnode);\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "declared", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void appendChildDeclareJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('function tester() { alerter(); }'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.appendChild(newnode);\n" + + " try {\n" + + " tester();\n" + + " } catch(e) { alert('exception'); }\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('declared');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "executed", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void insertBeforeExecuteJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('alerter();'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.insertBefore(newnode, null);\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "declared", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void insertBeforeDeclareJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('function tester() { alerter(); }'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.insertBefore(newnode, null);\n" + + " try {\n" + + " tester();\n" + + " } catch(e) { alert('exception'); }\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('declared');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "executed", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void replaceChildExecuteJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('alerter();'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.replaceChild(newnode, document.getElementById('inner'));\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'><div id='inner'></div></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "declared", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void replaceChildDeclareJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('function tester() { alerter(); }'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.replaceChild(newnode, document.getElementById('inner'));\n" + + " try {\n" + + " tester();\n" + + " } catch(e) { alert('exception'); }\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('declared');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'><div id='inner'></div></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts({ "outside", "1", "middle", "2", "3", "4", "before-begin after-begin inside before-end after-end" }) public void insertAdjacentHTML() throws Exception { @@ -4567,6 +4759,51 @@ * @throws Exception if the test fails */ @Test + public void insertAdjacentHTMLExecuteJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.insertAdjacentHTML('afterend', '<scr'+'ipt>alerter();</scr'+'ipt>');\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + public void insertAdjacentHTMLDeclareJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.insertAdjacentHTML('afterend', " + + "'<scr'+'ipt>function tester() { alerter(); }</scr'+'ipt>');\n" + + " try {\n" + + " tester();\n" + + " } catch(e) { alert('exception'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('declared');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Browsers({ CHROME, IE }) @Alerts({ "outside", "1", "middle", "2", "3", "4", "before-begin after-begin inside before-end after-end" }) @@ -4620,6 +4857,65 @@ */ @Test @Browsers({ CHROME, IE }) + @Alerts(DEFAULT = "executed", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void insertAdjacentElementExecuteJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('alerter();'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.insertAdjacentElement('afterend', newnode);\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('executed');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Browsers({ CHROME, IE }) + @Alerts(DEFAULT = "declared", + IE8 = "exception-append") + // IE8 does not support appendChild for script elements + public void insertAdjacentElementDeclareJavaScript() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html><head><title>foo</title><script>\n" + + " function test() {\n" + + " var newnode = document.createElement('script');\n" + + " try {\n" + + " newnode.appendChild(document.createTextNode('function tester() { alerter(); }'));\n" + + " var outernode = document.getElementById('myNode');\n" + + " outernode.insertAdjacentElement('afterend', newnode);\n" + + " try {\n" + + " tester();\n" + + " } catch(e) { alert('exception'); }\n" + + " } catch(e) { alert('exception-append'); }\n" + + " }\n" + + " function alerter() {\n" + + " alert('declared');\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + " <div id='myNode'></div>\n" + + "</body></html>"; + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Browsers({ CHROME, IE }) @Alerts(DEFAULT = { "outside", "middle", "before-begin after-begin inside before-end after-end" }, IE8 = { "outside", "middle", |
From: <rb...@us...> - 2014-01-28 19:50:45
|
Revision: 9082 http://sourceforge.net/p/htmlunit/code/9082 Author: rbri Date: 2014-01-28 19:50:41 +0000 (Tue, 28 Jan 2014) Log Message: ----------- Missing enctype property support added to forms Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElementTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-28 19:01:06 UTC (rev 9081) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-28 19:50:41 UTC (rev 9082) @@ -9,6 +9,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> <action type="fix" dev="rbri"> + JavaScript: Missing enctype property support added to forms. + </action> + <action type="fix" dev="rbri"> JavaScript: Attr firstChild/lastChild fixed when no child at all (FF). </action> <action type="fix" dev="rbri" due-to="Frank Danek"> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElement.java 2014-01-28 19:01:06 UTC (rev 9081) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElement.java 2014-01-28 19:50:41 UTC (rev 9082) @@ -33,6 +33,7 @@ import org.apache.commons.lang3.StringUtils; +import com.gargoylesoftware.htmlunit.FormEncodingType; import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.WebAssert; import com.gargoylesoftware.htmlunit.WebClient; @@ -263,36 +264,55 @@ } /** - * Returns the value of the JavaScript attribute "encoding". + * Returns the value of the JavaScript attribute "enctype". * @return the value of this attribute */ @JsxGetter - public String getEncoding() { + public String getEnctype() { final String encoding = getHtmlForm().getEnctypeAttribute(); - if (!"application/x-www-form-urlencoded".equals(encoding) - && !"multipart/form-data".equals(encoding) + if (!FormEncodingType.URL_ENCODED.getName().equals(encoding) + && !FormEncodingType.MULTIPART.getName().equals(encoding) && !"text/plain".equals(encoding)) { - return "application/x-www-form-urlencoded"; + return FormEncodingType.URL_ENCODED.getName(); } return encoding; } /** - * Sets the value of the JavaScript attribute "encoding". - * @param encoding the new value + * Sets the value of the JavaScript attribute "enctype". + * @param enctype the new value */ @JsxSetter - public void setEncoding(final String encoding) { - WebAssert.notNull("encoding", encoding); + public void setEnctype(final String enctype) { + WebAssert.notNull("encoding", enctype); if (getBrowserVersion().hasFeature(JS_FORM_REJECT_INVALID_ENCODING)) { - if (!"application/x-www-form-urlencoded".equals(encoding) && !"multipart/form-data".equals(encoding)) { + if (!FormEncodingType.URL_ENCODED.getName().equals(enctype) + && !FormEncodingType.MULTIPART.getName().equals(enctype)) { throw Context.reportRuntimeError("Cannot set the encoding property to invalid value: '" - + encoding + "'"); + + enctype + "'"); } } - getHtmlForm().setEnctypeAttribute(encoding); + getHtmlForm().setEnctypeAttribute(enctype); } + /** + * Returns the value of the JavaScript attribute "encoding". + * @return the value of this attribute + */ + @JsxGetter + public String getEncoding() { + return getEnctype(); + } + + /** + * Sets the value of the JavaScript attribute "encoding". + * @param encoding the new value + */ + @JsxSetter + public void setEncoding(final String encoding) { + setEnctype(encoding); + } + private HtmlForm getHtmlForm() { return (HtmlForm) getDomNodeOrDie(); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElementTest.java 2014-01-28 19:01:06 UTC (rev 9081) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFormElementTest.java 2014-01-28 19:50:41 UTC (rev 9082) @@ -1053,7 +1053,6 @@ */ @Test @Alerts("application/x-www-form-urlencoded") - @NotYetImplemented public void enctype_defaultValue() throws Exception { final String html = "<html><body><script>\n" + "alert(document.createElement('form').enctype)\n" |
From: <rb...@us...> - 2014-01-28 21:41:28
|
Revision: 9084 http://sourceforge.net/p/htmlunit/code/9084 Author: rbri Date: 2014-01-28 21:41:24 +0000 (Tue, 28 Jan 2014) Log Message: ----------- body.background property handling fixed for FF Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElementTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-28 19:52:59 UTC (rev 9083) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-28 21:41:24 UTC (rev 9084) @@ -343,10 +343,6 @@ GENERATED_157, /** Was originally .isFirefox(). */ - @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME) }) - GENERATED_158, - - /** Was originally .isFirefox(). */ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME), @WebBrowser(value = IE, minVersion = 11) }) GENERATED_164, Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElement.java 2014-01-28 19:52:59 UTC (rev 9083) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElement.java 2014-01-28 21:41:24 UTC (rev 9084) @@ -14,19 +14,15 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.html; -import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_158; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_41; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_OUTER_HTML_BODY_HEAD_READONLY; -import java.net.MalformedURLException; import java.util.Locale; import net.sourceforge.htmlunit.corejs.javascript.Context; -import com.gargoylesoftware.htmlunit.html.DomElement; import com.gargoylesoftware.htmlunit.html.HtmlBody; import com.gargoylesoftware.htmlunit.html.HtmlElement; -import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxSetter; @@ -110,18 +106,7 @@ @JsxGetter public String getBackground() { final HtmlElement node = getDomNodeOrDie(); - String background = node.getAttribute("background"); - if (background != DomElement.ATTRIBUTE_NOT_DEFINED - && getBrowserVersion().hasFeature(GENERATED_158)) { - try { - final HtmlPage page = (HtmlPage) node.getPage(); - background = page.getFullyQualifiedUrl(background).toExternalForm(); - } - catch (final MalformedURLException e) { - Context.throwAsScriptRuntimeEx(e); - } - } - return background; + return node.getAttribute("background"); } /** Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElementTest.java 2014-01-28 19:52:59 UTC (rev 9083) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLBodyElementTest.java 2014-01-28 21:41:24 UTC (rev 9084) @@ -14,9 +14,6 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.html; -import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF17; -import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF24; - import org.junit.Test; import org.junit.runner.RunWith; import org.openqa.selenium.By; @@ -24,7 +21,6 @@ import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; -import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented; import com.gargoylesoftware.htmlunit.WebDriverTestCase; /** @@ -45,9 +41,9 @@ * @throws Exception if an error occurs */ @Test - @Alerts(FF = {",0px,0px,0px,0px", ",,,,", ",8px,8px,8px,8px", ",,,," }, - IE = {"0px,0px,0px,0px,0px", ",,,,", "15px 10px,10px,10px,15px,15px", ",,,," }, - IE11 = {"0px,0px,0px,0px,0px", ",,,,", "8px,8px,8px,8px,8px", ",,,," }) + @Alerts(DEFAULT = {"0px,0px,0px,0px,0px", ",,,,", "8px,8px,8px,8px,8px", ",,,," }, + FF = {",0px,0px,0px,0px", ",,,,", ",8px,8px,8px,8px", ",,,," }, + IE8 = {"0px,0px,0px,0px,0px", ",,,,", "15px 10px,10px,10px,15px,15px", ",,,," }) public void testDefaultPaddingAndMargins() throws Exception { final String html = "<html>\n" @@ -159,7 +155,6 @@ */ @Test @Alerts({"", "http://www.foo.com/blah.gif", "blah.gif" }) - @NotYetImplemented({ FF17, FF24 }) public void background() throws Exception { final String html = "<html>\n" |
From: <rb...@us...> - 2014-01-29 18:29:53
|
Revision: 9089 http://sourceforge.net/p/htmlunit/code/9089 Author: rbri Date: 2014-01-29 18:29:49 +0000 (Wed, 29 Jan 2014) Log Message: ----------- Load iframe content when iframe is child of a node added by setting innerHTML Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement2Test.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java 2014-01-29 18:25:34 UTC (rev 9088) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java 2014-01-29 18:29:49 UTC (rev 9089) @@ -19,6 +19,7 @@ import java.net.URL; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -392,6 +393,18 @@ /** * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> * + * Marks this frame to load the source when added to page. + */ + public void markLoadSrcWhenAddedToPage() { + final String src = getSrcAttribute(); + if (StringUtils.isNoneEmpty(src) && !WebClient.ABOUT_BLANK.equals(src)) { + loadSrcWhenAddedToPage_ = true; + } + } + + /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * * Marks this frame as created by javascript. This is needed to handle * some special IE behavior. */ 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 2014-01-29 18:25:34 UTC (rev 9088) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-01-29 18:29:49 UTC (rev 9089) @@ -76,6 +76,7 @@ import com.gargoylesoftware.htmlunit.ScriptResult; import com.gargoylesoftware.htmlunit.SgmlPage; import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.BaseFrameElement; import com.gargoylesoftware.htmlunit.html.DomAttr; import com.gargoylesoftware.htmlunit.html.DomCharacterData; import com.gargoylesoftware.htmlunit.html.DomComment; @@ -960,6 +961,12 @@ final String valueAsString = Context.toString(value); parseHtmlSnippet(domNode, true, valueAsString); + for (final DomNode node : domNode.getDescendants()) { + if (node instanceof BaseFrameElement) { + ((BaseFrameElement) node).markLoadSrcWhenAddedToPage(); + } + } + final boolean createFragment = getBrowserVersion().hasFeature(JS_INNER_HTML_CREATES_DOC_FRAGMENT_AS_PARENT); // if the parentNode has null parentNode in IE, // create a DocumentFragment to be the parentNode's parentNode. Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement2Test.java 2014-01-29 18:25:34 UTC (rev 9088) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLIFrameElement2Test.java 2014-01-29 18:29:49 UTC (rev 9089) @@ -265,7 +265,6 @@ */ @Test @Alerts({ "createIFrame", "loaded" }) - @NotYetImplemented public void documentCreateElement_iFrameInsideDiv() throws Exception { final String html = "<html>\n" |
From: <asa...@us...> - 2014-01-31 05:28:14
|
Revision: 9093 http://sourceforge.net/p/htmlunit/code/9093 Author: asashour Date: 2014-01-31 05:28:09 +0000 (Fri, 31 Jan 2014) Log Message: ----------- HTMLObjectElement: classid could be affected by webClient.setActiveXObjectMap(). 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/html/HTMLObjectElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-31 04:43:06 UTC (rev 9092) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-31 05:28:09 UTC (rev 9093) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="asashour"> + HTMLObjectElement: classid could be affected by webClient.setActiveXObjectMap(). + </action> <action type="fix" dev="rbri" issue="1544"> Load iframe content when iframe is child of a node added by setting innerHTML. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-31 04:43:06 UTC (rev 9092) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-31 05:28:09 UTC (rev 9093) @@ -412,10 +412,6 @@ /** Was originally .isIE(). */ @BrowserFeature(@WebBrowser(IE)) - GENERATED_86, - - /** Was originally .isIE(). */ - @BrowserFeature(@WebBrowser(IE)) GENERATED_88, /** Was originally .isIE(). */ @@ -642,6 +638,10 @@ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) HTML_COMMENT_ELEMENT, + /** Supports <object> classid attribute. */ + @BrowserFeature(@WebBrowser(IE)) + HTML_OBJECT_CLASSID, + /** Indicates that "host" HTTP header should be the first. */ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME) }) HTTP_HEADER_HOST_FIRST, Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElement.java 2014-01-31 04:43:06 UTC (rev 9092) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElement.java 2014-01-31 05:28:09 UTC (rev 9093) @@ -14,11 +14,15 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.html; -import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_86; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTML_OBJECT_CLASSID; import static com.gargoylesoftware.htmlunit.javascript.configuration.BrowserName.IE; + +import java.util.Map; + import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; +import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlObject; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter; @@ -94,15 +98,41 @@ @JsxSetter(@WebBrowser(IE)) public void setClassid(final String classid) { getDomNodeOrDie().setAttribute("classid", classid); - if (classid.indexOf(':') != -1 && getBrowserVersion().hasFeature(GENERATED_86) - && getWindow().getWebWindow().getWebClient().getOptions().isActiveXNative() - && System.getProperty("os.name").contains("Windows")) { - try { - wrappedActiveX_ = new ActiveXObjectImpl(classid); - wrappedActiveX_.setParentScope(getParentScope()); + if (classid.indexOf(':') != -1 && getBrowserVersion().hasFeature(HTML_OBJECT_CLASSID)) { + final WebClient webClient = getWindow().getWebWindow().getWebClient(); + final Map<String, String> map = webClient.getActiveXObjectMap(); + if (map != null) { + final String xClassString = map.get(classid); + if (xClassString != null) { + try { + final Class<?> xClass = Class.forName(xClassString); + final Object object = xClass.newInstance(); + boolean contextCreated = false; + if (Context.getCurrentContext() == null) { + Context.enter(); + contextCreated = true; + } + wrappedActiveX_ = Context.toObject(object, getParentScope()); + if (contextCreated) { + Context.exit(); + } + } + catch (final Exception e) { + throw Context.reportRuntimeError("ActiveXObject Error: failed instantiating class " + + xClassString + " because " + e.getMessage() + "."); + } + return; + } } - catch (final Exception e) { - Context.throwAsScriptRuntimeEx(e); + if (webClient.getOptions().isActiveXNative() + && System.getProperty("os.name").contains("Windows")) { + try { + wrappedActiveX_ = new ActiveXObjectImpl(classid); + wrappedActiveX_.setParentScope(getParentScope()); + } + catch (final Exception e) { + Context.throwAsScriptRuntimeEx(e); + } } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java 2014-01-31 04:43:06 UTC (rev 9092) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java 2014-01-31 05:28:09 UTC (rev 9093) @@ -14,18 +14,27 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.html; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.junit.Test; import org.junit.runner.RunWith; import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; +import com.gargoylesoftware.htmlunit.CollectingAlertHandler; +import com.gargoylesoftware.htmlunit.MockWebConnection; import com.gargoylesoftware.htmlunit.SimpleWebTestCase; +import com.gargoylesoftware.htmlunit.WebClient; /** * Unit tests for {@link HTMLObjectElement}. * * @version $Revision$ * @author Daniel Gredler + * @author Ahmed Ashour */ @RunWith(BrowserRunner.class) public class HTMLObjectElementTest extends SimpleWebTestCase { @@ -44,4 +53,37 @@ loadPageWithAlerts(html); } + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "undefined", IE = "ActiveX is working!") + public void classid() throws Exception { + final String clsid = "clsid:TESTING-CLASS-ID"; + final String html = "<html><head>\n" + + "<object id='id1' classid='" + clsid + "'></object>\n" + + "<script>\n" + + " function test() {\n" + + " alert(document.all.id1.MESSAGE);\n" + + " }\n" + + "</script>\n" + + "</head><body onload='test()'>\n" + + "</body></html>"; + + final WebClient client = getWebClient(); + final Map<String, String> activeXObjectMap = new HashMap<String, String>(); + activeXObjectMap.put(clsid, + "com.gargoylesoftware.htmlunit.javascript.MockActiveXObject"); + client.setActiveXObjectMap(activeXObjectMap); + + final List<String> collectedAlerts = new ArrayList<String>(); + client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); + + final MockWebConnection webConnection = new MockWebConnection(); + webConnection.setResponse(getDefaultUrl(), html); + client.setWebConnection(webConnection); + + client.getPage(getDefaultUrl()); + assertEquals(getExpectedAlerts(), collectedAlerts); + } } |
From: <asa...@us...> - 2014-01-31 15:07:44
|
Revision: 9094 http://sourceforge.net/p/htmlunit/code/9094 Author: asashour Date: 2014-01-31 15:07:40 +0000 (Fri, 31 Jan 2014) Log Message: ----------- HtmlFileInput: ability to upload multiple files using setValueAttribute(String []). Issue 215 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlFileInput.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest.java Added Paths: ----------- trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_one.txt trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_two.txt Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-31 05:28:09 UTC (rev 9093) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-31 15:07:40 UTC (rev 9094) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="add" dev="asashour" issue="215" system="features"> + HtmlFileInput: ability to upload multiple files using setValueAttribute(String []). + </action> <action type="fix" dev="asashour"> HTMLObjectElement: classid could be affected by webClient.setActiveXObjectMap(). </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlFileInput.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlFileInput.java 2014-01-31 05:28:09 UTC (rev 9093) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlFileInput.java 2014-01-31 15:07:40 UTC (rev 9094) @@ -19,11 +19,14 @@ import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; +import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.SgmlPage; import com.gargoylesoftware.htmlunit.util.KeyDataPair; import com.gargoylesoftware.htmlunit.util.NameValuePair; @@ -52,7 +55,7 @@ * @param attributes the initial attributes */ HtmlFileInput(final String qualifiedName, final SgmlPage page, - final Map<String, DomAttr> attributes) { + final Map<String, DomAttr> attributes) { super(qualifiedName, page, addValueIfNeeded(page, attributes)); if (hasFeature(FILEINPUT_EMPTY_DEFAULT_VALUE)) { @@ -110,44 +113,48 @@ */ @Override public NameValuePair[] getSubmitKeyValuePairs() { - String value = getValueAttribute(); + final String valueAttribute = getValueAttribute(); - if (StringUtils.isEmpty(value)) { + if (StringUtils.isEmpty(valueAttribute)) { return new NameValuePair[] {new KeyDataPair(getNameAttribute(), new File(""), null, null)}; } - File file = null; - // to tolerate file:// - if (value.startsWith("file:/")) { - if (value.startsWith("file://") && !value.startsWith("file:///")) { - value = "file:///" + value.substring(7); + final List<NameValuePair> list = new ArrayList<NameValuePair>(); + for (String value : valueAttribute.split("§")) { + File file = null; + // to tolerate file:// + if (value.startsWith("file:/")) { + if (value.startsWith("file://") && !value.startsWith("file:///")) { + value = "file:///" + value.substring(7); + } + try { + file = new File(new URI(value)); + } + catch (final URISyntaxException e) { + // nothing here + } } - try { - file = new File(new URI(value)); + + if (file == null) { + file = new File(value); } - catch (final URISyntaxException e) { - // nothing here + + // contentType and charset are determined from browser and page + // perhaps it could be interesting to have setters for it in this class + // to give finer control to user + final String contentType; + if (contentType_ == null) { + contentType = getPage().getWebClient().guessContentType(file); } + else { + contentType = contentType_; + } + final String charset = getPage().getPageEncoding(); + final KeyDataPair keyDataPair = new KeyDataPair(getNameAttribute(), file, contentType, charset); + keyDataPair.setData(data_); + list.add(keyDataPair); } - - if (file == null) { - file = new File(value); - } - - // contentType and charset are determined from browser and page - // perhaps it could be interesting to have setters for it in this class - // to give finer control to user - final String contentType; - if (contentType_ == null) { - contentType = getPage().getWebClient().guessContentType(file); - } - else { - contentType = contentType_; - } - final String charset = getPage().getPageEncoding(); - final KeyDataPair keyDataPair = new KeyDataPair(getNameAttribute(), file, contentType, charset); - keyDataPair.setData(data_); - return new NameValuePair[] {keyDataPair}; + return list.toArray(new NameValuePair[list.size()]); } /** @@ -186,4 +193,28 @@ public String getContentType() { return contentType_; } + + /** + * Used to specify <code>multiple</code> paths to upload. + * + * The current implementation splits the value based on '§'. + * We may follow WebDriver solution, once made, + * see https://code.google.com/p/selenium/issues/detail?id=2239 + * @param paths the list of paths of the files to upload + * @return the page contained by this element's window after the value is set + */ + public Page setValueAttribute(final String[] paths) { + if (getAttribute("multiple") == ATTRIBUTE_NOT_DEFINED) { + throw new IllegalStateException("HtmlFileInput is not 'multiple'."); + } + final StringBuilder builder = new StringBuilder(); + for (final String p : paths) { + if (builder.length() != 0) { + builder.append('§'); + } + builder.append(p); + } + return super.setValueAttribute(builder.toString()); + } + } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest.java 2014-01-31 05:28:09 UTC (rev 9093) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest.java 2014-01-31 15:07:40 UTC (rev 9094) @@ -493,4 +493,63 @@ writer.close(); } } + + /** + * @throws Exception if the test fails + */ + @Test + public void mutiple() throws Exception { + final Map<String, Class<? extends Servlet>> servlets = new HashMap<String, Class<? extends Servlet>>(); + servlets.put("/upload1", Multiple1Servlet.class); + servlets.put("/upload2", HtmlFileInput2Test.PrintRequestServlet.class); + startWebServer("./", null, servlets); + + final String filename1 = "HtmlFileInputTest_one.txt"; + final String path1 = getClass().getResource(filename1).toExternalForm(); + final File file1 = new File(new URI(path1)); + assertTrue(file1.exists()); + + final String filename2 = "HtmlFileInputTest_two.txt"; + final String path2 = getClass().getResource(filename2).toExternalForm(); + final File file2 = new File(new URI(path2)); + assertTrue(file2.exists()); + + final WebClient client = getWebClient(); + final HtmlPage firstPage = client.getPage("http://localhost:" + PORT + "/upload1"); + + final HtmlForm form = firstPage.getForms().get(0); + final HtmlFileInput fileInput = form.getInputByName("myInput"); + fileInput.setValueAttribute(new String[] {path1, path2}); + + final HtmlSubmitInput submitInput = form.getInputByValue("Upload"); + final HtmlPage secondPage = submitInput.click(); + + final String response = secondPage.getWebResponse().getContentAsString(); + + assertTrue(response.contains("HtmlFileInputTest_one.txt")); + assertTrue(response.contains("First")); + assertTrue(response.contains("HtmlFileInputTest_two.txt")); + assertTrue(response.contains("Second")); + } + + /** + * Servlet for '/upload1'. + */ + public static class Multiple1Servlet extends HttpServlet { + + /** + * {@inheritDoc} + */ + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) + throws ServletException, IOException { + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/html"); + response.getWriter().write("<html>" + + "<body><form action='upload2' method='post' enctype='multipart/form-data'>\n" + + "Name: <input name='myInput' type='file' multiple><br>\n" + + "<input type='submit' value='Upload' id='mySubmit'>\n" + + "</form></body></html>\n"); + } + } } Added: trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_one.txt =================================================================== --- trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_one.txt (rev 0) +++ trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_one.txt 2014-01-31 15:07:40 UTC (rev 9094) @@ -0,0 +1 @@ +First \ No newline at end of file Property changes on: trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_one.txt ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_two.txt =================================================================== --- trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_two.txt (rev 0) +++ trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_two.txt 2014-01-31 15:07:40 UTC (rev 9094) @@ -0,0 +1 @@ +Second \ No newline at end of file Property changes on: trunk/htmlunit/src/test/resources/com/gargoylesoftware/htmlunit/html/HtmlFileInputTest_two.txt ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property |
From: <rb...@us...> - 2014-01-31 21:55:19
|
Revision: 9095 http://sourceforge.net/p/htmlunit/code/9095 Author: rbri Date: 2014-01-31 21:55:16 +0000 (Fri, 31 Jan 2014) Log Message: ----------- HtmlParser fixed for pages with scripts outside the html tag Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HTMLParser.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/MalformedHtmlTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-31 15:07:40 UTC (rev 9094) +++ trunk/htmlunit/src/changes/changes.xml 2014-01-31 21:55:16 UTC (rev 9095) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="rbri"> + HtmlParser fixed for pages with scripts outside the html tag. + </action> <action type="add" dev="asashour" issue="215" system="features"> HtmlFileInput: ability to upload multiple files using setValueAttribute(String []). </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HTMLParser.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HTMLParser.java 2014-01-31 15:07:40 UTC (rev 9094) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HTMLParser.java 2014-01-31 21:55:16 UTC (rev 9095) @@ -382,6 +382,9 @@ */ static final class HtmlUnitDOMBuilder extends AbstractSAXParser implements ContentHandler, LexicalHandler, HTMLTagBalancingListener { + + private enum HeadParsed { YES, SYNTESIZED, NO }; + private final HtmlPage page_; private Locator locator_; @@ -389,7 +392,7 @@ private DomNode currentNode_; private StringBuilder characters_; - private boolean headParsed_ = false; + private HeadParsed headParsed_ = HeadParsed.NO; private boolean parsingInnerHead_ = false; private HtmlElement head_; private HtmlElement body_; @@ -498,6 +501,15 @@ public void startDocument() throws SAXException { } + /** {@inheritDoc} */ + @Override + public void startElement(final QName element, final XMLAttributes attributes, final Augmentations augs) + throws XNIException { + // just to have local access to the augmentations. A better way? + augmentations_ = augs; + super.startElement(element, attributes, augs); + } + /** {@inheritDoc ContentHandler#startElement(String,String,String,Attributes)} */ public void startElement( String namespaceURI, final String localName, @@ -519,18 +531,19 @@ namespaceURI = namespaceURI.trim(); } if ("head".equals(tagLower)) { - if (headParsed_ || page_.isParsingHtmlSnippet()) { + if (headParsed_ == HeadParsed.YES || page_.isParsingHtmlSnippet()) { parsingInnerHead_ = true; return; } - headParsed_ = true; + + headParsed_ = isSynthesized(augmentations_) ? HeadParsed.SYNTESIZED : HeadParsed.YES; } // add a head if none was there - else if (!headParsed_ && ("body".equals(tagLower) || "frameset".equals(tagLower))) { + else if (headParsed_ == HeadParsed.NO && ("body".equals(tagLower) || "frameset".equals(tagLower))) { final ElementFactory factory = getElementFactory(page_, namespaceURI, "head"); final DomElement newElement = factory.createElement(page_, "head", null); currentNode_.appendChild(newElement); - headParsed_ = true; + headParsed_ = HeadParsed.SYNTESIZED; } // If we're adding a body element, keep track of any temporary synthetic ones @@ -898,7 +911,7 @@ } } - if (headParsed_ && "head".equalsIgnoreCase(elem.localpart)) { + if (headParsed_ == HeadParsed.YES && "head".equalsIgnoreCase(elem.localpart)) { parsingInnerHead_ = true; } } @@ -917,6 +930,12 @@ page_.setBuilder(oldBuilder); } } + + private boolean isSynthesized(final Augmentations augs) { + final HTMLEventInfo info = (augs == null) ? null + : (HTMLEventInfo) augs.getItem(FEATURE_AUGMENTATIONS); + return info != null ? info.isSynthesized() : false; + } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java 2014-01-31 15:07:40 UTC (rev 9094) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HTMLParser4Test.java 2014-01-31 21:55:16 UTC (rev 9095) @@ -17,6 +17,7 @@ import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.CHROME; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.IE11; +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.IE8; import org.junit.Test; import org.junit.runner.RunWith; @@ -90,6 +91,97 @@ } /** + * @throws Exception failure + */ + @Test + @Alerts(DEFAULT = { "4", "[object HTMLScriptElement]", "[object Text]", + "[object HTMLTitleElement]", "[object Text]" }, + IE8 = { "2", "[object HTMLTitleElement]", "[object HTMLScriptElement]", "undefined", "undefined" }) + @NotYetImplemented(IE8) + public void badlyFormedHTML_scriptBeforeHead() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<script>var i=7;</script>\n" + + "<html>\n" + + " <head>\n" + + " <title>first</title>\n" + + " </head>\n" + + " <body>\n" + + " <script>\n" + + " var headchilds = document.getElementsByTagName('head')[0].childNodes;\n" + + " alert(headchilds.length);\n" + + " alert(headchilds[0]);\n" + + " alert(headchilds[1]);\n" + + " alert(headchilds[2]);\n" + + " alert(headchilds[3]);\n" + + " </script>\n" + + " </body>\n" + + "</html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception failure + */ + @Test + @Alerts(DEFAULT = { "4", "[object HTMLScriptElement]", "[object Text]", + "[object HTMLTitleElement]", "[object Text]" }, + IE8 = { "3", "[object]", "[object]", "[object]", "undefined" }) + @NotYetImplemented(IE8) + public void badlyFormedHTML_scriptBeforeDoctype() throws Exception { + final String html = "<script>var i=7;</script>\n" + + HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html>\n" + + " <head>\n" + + " <title>first</title>\n" + + " </head>\n" + + " <body>\n" + + " <script>\n" + + " var headchilds = document.getElementsByTagName('head')[0].childNodes;\n" + + " alert(headchilds.length);\n" + + " alert(headchilds[0]);\n" + + " alert(headchilds[1]);\n" + + " alert(headchilds[2]);\n" + + " alert(headchilds[3]);\n" + + " </script>\n" + + " </body>\n" + + "</html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception failure + */ + @Test + @Alerts(DEFAULT = { "4", "[object HTMLParagraphElement]", "[object Text]", + "[object HTMLScriptElement]", "[object Text]" }, + IE8 = { "3", "[object]", "[object]", "[object]", "undefined" }) + @NotYetImplemented + public void badlyFormedHTML_scriptAfterHtml() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "<html>\n" + + " <head>\n" + + " <title>first</title>\n" + + " <script>\n" + + " function test(){\n" + + " var headchilds = document.getElementsByTagName('body')[0].childNodes;\n" + + " alert(headchilds.length);\n" + + " alert(headchilds[0]);\n" + + " alert(headchilds[1]);\n" + + " alert(headchilds[2]);\n" + + " alert(headchilds[3]);\n" + + " }\n" + + " </script>\n" + + " </head>\n" + + " <body onload='test()'><p>HtmlUnit</p></body>\n" + + "</html>" + + "<script>var i=7;</script>\n"; + + loadPageWithAlerts2(html); + } + + /** * Test when an illegal tag is found in head as some websites do. * @throws Exception failure */ Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/MalformedHtmlTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/MalformedHtmlTest.java 2014-01-31 15:07:40 UTC (rev 9094) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/MalformedHtmlTest.java 2014-01-31 21:55:16 UTC (rev 9095) @@ -162,8 +162,6 @@ */ @Test @Alerts("12345") - @NotYetImplemented(IE8) - // Our HTML fixed done during parsing create an HTML different from the IE8 one public void testWrongHtml_TagBeforeHtml() throws Exception { final String html = "<div>\n" + "<html>\n" |
From: <rb...@us...> - 2014-02-01 11:57:42
|
Revision: 9096 http://sourceforge.net/p/htmlunit/code/9096 Author: rbri Date: 2014-02-01 11:57:37 +0000 (Sat, 01 Feb 2014) Log Message: ----------- Dom manipulation fixed provided by Frank Danek. Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlElement.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NodeList.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Window3Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/changes/changes.xml 2014-02-01 11:57:37 UTC (rev 9096) @@ -8,6 +8,11 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: Internal cleanup and some fixes for the innerHTML/outerHTML/insertAdjacentHTML. + Fix appendChild/insertBefore/replaceChild also. + Additionally trigger the correct notifications to inform about dom changes. + </action> <action type="fix" dev="rbri"> HtmlParser fixed for pages with scripts outside the html tag. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/BaseFrameElement.java 2014-02-01 11:57:37 UTC (rev 9096) @@ -19,9 +19,9 @@ import java.net.URL; import java.util.Map; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Attr; import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; import com.gargoylesoftware.htmlunit.Page; @@ -69,6 +69,15 @@ super(qualifiedName, page, attributes); init(); + + if (page instanceof HtmlPage && ((HtmlPage) page).isParsingHtmlSnippet()) { + // if created by the HTMLParser the src attribute is not set via setAttribute() or some other method but is + // part of the given attributes already. + final String src = getAttribute("src"); + if (src != ATTRIBUTE_NOT_DEFINED && !WebClient.ABOUT_BLANK.equals(src)) { + loadSrcWhenAddedToPage_ = true; + } + } } private void init() { @@ -357,6 +366,31 @@ } } + /** + * {@inheritDoc} + */ + @Override + public Attr setAttributeNode(final Attr attribute) { + final String qualifiedName = attribute.getName(); + String attributeValue = null; + if ("src".equals(qualifiedName)) { + attributeValue = attribute.getValue().trim(); + } + + final Attr result = super.setAttributeNode(attribute); + + if ("src".equals(qualifiedName) && !WebClient.ABOUT_BLANK.equals(attributeValue)) { + if (isDirectlyAttachedToPage()) { + loadSrc(); + } + else { + loadSrcWhenAddedToPage_ = true; + } + } + + return result; + } + private void loadSrc() { loadSrcWhenAddedToPage_ = false; final String src = getSrcAttribute(); @@ -393,18 +427,6 @@ /** * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> * - * Marks this frame to load the source when added to page. - */ - public void markLoadSrcWhenAddedToPage() { - final String src = getSrcAttribute(); - if (StringUtils.isNoneEmpty(src) && !WebClient.ABOUT_BLANK.equals(src)) { - loadSrcWhenAddedToPage_ = true; - } - } - - /** - * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> - * * Marks this frame as created by javascript. This is needed to handle * some special IE behavior. */ Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java 2014-02-01 11:57:37 UTC (rev 9096) @@ -89,6 +89,7 @@ * @author <a href="mailto:tom...@un...">Tom Anderson</a> * @author Ronald Brill * @author Chuck Dumont + * @author Frank Danek */ public abstract class DomNode implements Cloneable, Serializable, Node { @@ -671,6 +672,13 @@ } /** + * {@inheritDoc} + */ + public NamedNodeMap getAttributes() { + return NamedAttrNodeMapImpl.EMPTY_MAP; + } + + /** * Returns a flag indicating whether or not this node should have any leading and trailing * whitespace removed when {@link #asText()} is called. This method should usually return * <tt>true</tt>, but must return <tt>false</tt> for such things as text formatting tags. @@ -923,7 +931,7 @@ if (domNode != this && domNode.getParentNode() != null) { domNode.detach(); } - // move the node + basicAppend(domNode); fireAddition(domNode); @@ -932,63 +940,9 @@ return domNode; } - private void fireAddition(final DomNode domNode) { - final boolean wasAlreadyAttached = domNode.isDirectlyAttachedToPage(); - domNode.directlyAttachedToPage_ = isDirectlyAttachedToPage(); - - if (isDirectlyAttachedToPage()) { - // trigger events - final Page page = getPage(); - if (page instanceof HtmlPage) { - ((HtmlPage) page).notifyNodeAdded(domNode); - } - - // a node that is already "complete" (ie not being parsed) and not yet attached - if (!domNode.isBodyParsed() && !wasAlreadyAttached) { - for (final DomNode child : domNode.getDescendants()) { - child.directlyAttachedToPage_ = true; - child.onAllChildrenAddedToPage(true); - } - domNode.onAllChildrenAddedToPage(true); - } - } - - if (this instanceof DomDocumentFragment) { - onAddedToDocumentFragment(); - } - - fireNodeAdded(this, domNode); - } - /** - * Indicates if the current node is being parsed. This means that the opening tag has already been - * parsed but not the body and end tag. - */ - private boolean isBodyParsed() { - return getStartLineNumber() != -1 && getEndLineNumber() == -1; - } - - /** - * Quietly removes this node and moves its children to the specified destination. "Quietly" means - * that no node events are fired. This method is not appropriate for most use cases. It should - * only be used in specific cases for HTML parsing hackery. - * - * @param destination the node to which this node's children should be moved before this node is removed - */ - void quietlyRemoveAndMoveChildrenTo(final DomNode destination) { - if (destination.getPage() != getPage()) { - throw new RuntimeException("Cannot perform quiet move on nodes from different pages."); - } - for (final DomNode child : getChildren()) { - child.basicRemove(); - destination.basicAppend(child); - } - basicRemove(); - } - - /** * Appends the specified node to the end of this node's children, assuming the specified - * node is clean (doesn't have preexisting relationships to other nodes. + * node is clean (doesn't have preexisting relationships to other nodes). * * @param node the node to append to this node's children */ @@ -1009,51 +963,31 @@ } /** - * Check for insertion errors for a new child node. This is overridden by derived - * classes to enforce which types of children are allowed. - * - * @param newChild the new child node that is being inserted below this node - * @throws DOMException HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does - * not allow children of the type of the newChild node, or if the node to insert is one of - * this node's ancestors or this node itself, or if this node is of type Document and the - * DOM application attempts to insert a second DocumentType or Element node. - * WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the - * one that created this node. - */ - protected void checkChildHierarchy(final Node newChild) throws DOMException { - Node parentNode = this; - while (parentNode != null) { - if (parentNode == newChild) { - throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, "Child node is already a parent."); - } - parentNode = parentNode.getParentNode(); - } - final Document thisDocument = getOwnerDocument(); - final Document childDocument = newChild.getOwnerDocument(); - if (childDocument != thisDocument && childDocument != null) { - throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, "Child node " + newChild.getNodeName() - + " is not in the same Document as this " + getNodeName() + "."); - } - } - - /** * {@inheritDoc} */ public Node insertBefore(final Node newChild, final Node refChild) { - if (refChild == null) { - appendChild(newChild); + if (newChild instanceof DomDocumentFragment) { + final DomDocumentFragment fragment = (DomDocumentFragment) newChild; + for (final DomNode child : fragment.getChildren()) { + insertBefore(child, refChild); + } } else { - if (refChild.getParentNode() != this) { - throw new DOMException(DOMException.NOT_FOUND_ERR, "Reference node is not a child of this node."); + if (refChild == null) { + appendChild(newChild); } - ((DomNode) refChild).insertBefore((DomNode) newChild); + else { + if (refChild.getParentNode() != this) { + throw new DOMException(DOMException.NOT_FOUND_ERR, "Reference node is not a child of this node."); + } + ((DomNode) refChild).insertBefore((DomNode) newChild); + } } - return null; + return newChild; } /** - * Inserts a new child node before this node into the child relationship this node is a + * Inserts the specified node as a new child node before this node into the child relationship this node is a * part of. If the specified node is this node, this method is a no-op. * * @param newNode the new node to insert @@ -1068,31 +1002,73 @@ return; } - //clean up the new node, in case it is being moved - final DomNode exParent = newNode.getParentNode(); - newNode.basicRemove(); + // clean up the new node, in case it is being moved + if (newNode.getParentNode() != null) { + newNode.detach(); + } + basicInsertBefore(newNode); + + fireAddition(newNode); + } + + /** + * Inserts the specified node into this node's parent's children right before this node, assuming the specified + * node is clean (doesn't have preexisting relationships to other nodes). + * + * @param node the node to insert before this node + */ + private void basicInsertBefore(final DomNode node) { + node.setPage(page_); if (parent_.firstChild_ == this) { - parent_.firstChild_ = newNode; + parent_.firstChild_ = node; } else { - previousSibling_.nextSibling_ = newNode; + previousSibling_.nextSibling_ = node; } - newNode.previousSibling_ = previousSibling_; - newNode.nextSibling_ = this; - previousSibling_ = newNode; - newNode.parent_ = parent_; - newNode.setPage(page_); + node.previousSibling_ = previousSibling_; + node.nextSibling_ = this; + previousSibling_ = node; + node.parent_ = parent_; + } - fireAddition(newNode); + private void fireAddition(final DomNode domNode) { + final boolean wasAlreadyAttached = domNode.isDirectlyAttachedToPage(); + domNode.directlyAttachedToPage_ = isDirectlyAttachedToPage(); - if (exParent != null) { - fireNodeDeleted(exParent, newNode); - exParent.fireNodeDeleted(exParent, this); + if (isDirectlyAttachedToPage()) { + // trigger events + final Page page = getPage(); + if (page instanceof HtmlPage) { + ((HtmlPage) page).notifyNodeAdded(domNode); + } + + // a node that is already "complete" (ie not being parsed) and not yet attached + if (!domNode.isBodyParsed() && !wasAlreadyAttached) { + for (final DomNode child : domNode.getDescendants()) { + child.directlyAttachedToPage_ = true; + child.onAllChildrenAddedToPage(true); + } + domNode.onAllChildrenAddedToPage(true); + } } + + if (this instanceof DomDocumentFragment) { + onAddedToDocumentFragment(); + } + + fireNodeAdded(this, domNode); } /** + * Indicates if the current node is being parsed. This means that the opening tag has already been + * parsed but not the body and end tag. + */ + private boolean isBodyParsed() { + return getStartLineNumber() != -1 && getEndLineNumber() == -1; + } + + /** * Recursively sets the new page on the node and its children * @param newPage the new owning page */ @@ -1110,13 +1086,6 @@ /** * {@inheritDoc} */ - public NamedNodeMap getAttributes() { - return NamedAttrNodeMapImpl.EMPTY_MAP; - } - - /** - * {@inheritDoc} - */ public Node removeChild(final Node child) { if (child.getParentNode() != this) { throw new DOMException(DOMException.NOT_FOUND_ERR, "Node is not a child of this node."); @@ -1126,25 +1095,12 @@ } /** - * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> - * - * Detach this node from all relationships with other nodes. - * This is the first step of an move. + * Removes all of this node's children. */ - protected void detach() { - final DomNode exParent = parent_; - basicRemove(); - - final HtmlPage htmlPage = getHtmlPageOrNull(); - if (htmlPage != null) { - htmlPage.notifyNodeRemoved(this); + public void removeAllChildren() { + while (getFirstChild() != null) { + getFirstChild().remove(); } - - if (exParent != null) { - fireNodeDeleted(exParent, this); - //ask ex-parent to fire event (because we don't have parent now) - exParent.fireNodeDeleted(exParent, this); - } } /** @@ -1156,6 +1112,20 @@ } /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * Detach this node from all relationships with other nodes. + * This is the first step of an move. + */ + protected void detach() { + final DomNode exParent = parent_; + + basicRemove(); + + fireRemoval(exParent); + } + + /** * Cuts off all relationships this node has with siblings and parents. */ private void basicRemove() { @@ -1177,6 +1147,23 @@ parent_ = null; } + private void fireRemoval(final DomNode exParent) { + final HtmlPage htmlPage = getHtmlPageOrNull(); + if (htmlPage != null) { + // some of the actions executed on removal need an intact parent relationship (e.g. for the + // DocumentPositionComparator) so we have to restore it temporarily + parent_ = exParent; + htmlPage.notifyNodeRemoved(this); + parent_ = null; + } + + if (exParent != null) { + fireNodeDeleted(exParent, this); + // ask ex-parent to fire event (because we don't have parent now) + exParent.fireNodeDeleted(exParent, this); + } + } + /** * {@inheritDoc} */ @@ -1196,13 +1183,62 @@ */ public void replace(final DomNode newNode) throws IllegalStateException { if (newNode != this) { - newNode.remove(); - insertBefore(newNode); + final DomNode exParent = parent_; + final DomNode exNextSibling = nextSibling_; + remove(); + + exParent.insertBefore(newNode, exNextSibling); } } /** + * Quietly removes this node and moves its children to the specified destination. "Quietly" means + * that no node events are fired. This method is not appropriate for most use cases. It should + * only be used in specific cases for HTML parsing hackery. + * + * @param destination the node to which this node's children should be moved before this node is removed + */ + void quietlyRemoveAndMoveChildrenTo(final DomNode destination) { + if (destination.getPage() != getPage()) { + throw new RuntimeException("Cannot perform quiet move on nodes from different pages."); + } + for (final DomNode child : getChildren()) { + child.basicRemove(); + destination.basicAppend(child); + } + basicRemove(); + } + + /** + * Check for insertion errors for a new child node. This is overridden by derived + * classes to enforce which types of children are allowed. + * + * @param newChild the new child node that is being inserted below this node + * @throws DOMException HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does + * not allow children of the type of the newChild node, or if the node to insert is one of + * this node's ancestors or this node itself, or if this node is of type Document and the + * DOM application attempts to insert a second DocumentType or Element node. + * WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the + * one that created this node. + */ + protected void checkChildHierarchy(final Node newChild) throws DOMException { + Node parentNode = this; + while (parentNode != null) { + if (parentNode == newChild) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, "Child node is already a parent."); + } + parentNode = parentNode.getParentNode(); + } + final Document thisDocument = getOwnerDocument(); + final Document childDocument = newChild.getOwnerDocument(); + if (childDocument != thisDocument && childDocument != null) { + throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, "Child node " + newChild.getNodeName() + + " is not in the same Document as this " + getNodeName() + "."); + } + } + + /** * Lifecycle method invoked whenever a node is added to a page. Intended to * be overridden by nodes which need to perform custom logic when they are * added to a page. This method is recursive, so if you override it, please @@ -1435,15 +1471,6 @@ } /** - * Removes all of this node's children. - */ - public void removeAllChildren() { - while (getFirstChild() != null) { - getFirstChild().remove(); - } - } - - /** * Parses the SelectionNamespaces property into a map of prefix/namespace pairs. * The default namespace (specified by xmlns=) is placed in the map using the * empty string ("") key. Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlElement.java 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlElement.java 2014-02-01 11:57:37 UTC (rev 9096) @@ -37,6 +37,7 @@ import org.apache.commons.lang3.ClassUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.Comment; import org.w3c.dom.DOMException; @@ -216,6 +217,52 @@ } /** + * Sets the specified attribute. This method may be overridden by subclasses + * which are interested in specific attribute value changes, but such methods <b>must</b> + * invoke <tt>super.setAttributeNode()</tt>, and <b>should</b> consider the value of the + * <tt>cloning</tt> parameter when deciding whether or not to execute custom logic. + * + * @param attribute the attribute to set + * @return {@inheritDoc} + */ + @Override + public Attr setAttributeNode(final Attr attribute) { + final String qualifiedName = attribute.getName(); + final String oldAttributeValue = getAttribute(qualifiedName); + final HtmlPage htmlPage = (HtmlPage) getPage(); + final boolean mappedElement = isDirectlyAttachedToPage() + && HtmlPage.isMappedElement(htmlPage, qualifiedName); + if (mappedElement) { + // cast is save here because isMappedElement checks for HtmlPage + htmlPage.removeMappedElement(this); + } + + final Attr result = super.setAttributeNode(attribute); + + if (mappedElement) { + htmlPage.addMappedElement(this); + } + + final HtmlAttributeChangeEvent htmlEvent; + if (oldAttributeValue == ATTRIBUTE_NOT_DEFINED) { + htmlEvent = new HtmlAttributeChangeEvent(this, qualifiedName, attribute.getValue()); + fireHtmlAttributeAdded(htmlEvent); + htmlPage.fireHtmlAttributeAdded(htmlEvent); + } + else { + htmlEvent = new HtmlAttributeChangeEvent(this, qualifiedName, oldAttributeValue); + fireHtmlAttributeReplaced(htmlEvent); + htmlPage.fireHtmlAttributeReplaced(htmlEvent); + } + + if (hasFeature(EVENT_PROPERTY_CHANGE)) { + fireEvent(Event.createPropertyChangeEvent(this, qualifiedName)); + } + + return result; + } + + /** * Returns the HTML elements that are descendants of this element and that have one of the specified tag names. * @param tagNames the tag names to match (case-insensitive) * @return the HTML elements that are descendants of this element and that have one of the specified tag name Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2014-02-01 11:57:37 UTC (rev 9096) @@ -46,6 +46,7 @@ import net.sourceforge.htmlunit.corejs.javascript.Function; import net.sourceforge.htmlunit.corejs.javascript.Script; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; +import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -376,35 +377,8 @@ /** * {@inheritDoc} - */ - public DomNodeList<DomElement> getElementsByTagName(final String tagName) { - return new XPathDomNodeList<DomElement>(this, "//*[local-name()='" + tagName + "']"); - } - - /** - * {@inheritDoc} * Not yet implemented. */ - public DomNodeList<DomElement> getElementsByTagNameNS(final String namespaceURI, final String localName) { - throw new UnsupportedOperationException("HtmlPage.getElementsByTagNameNS is not yet implemented."); - } - - /** - * {@inheritDoc} - */ - public DomElement getElementById(final String elementId) { - try { - return getElementById(elementId, true); - } - catch (final ElementNotFoundException e) { - return null; - } - } - - /** - * {@inheritDoc} - * Not yet implemented. - */ public String getInputEncoding() { throw new UnsupportedOperationException("HtmlPage.getInputEncoding is not yet implemented."); } @@ -519,6 +493,14 @@ /** * {@inheritDoc} + * Not yet implemented. + */ + public DOMImplementation getImplementation() { + throw new UnsupportedOperationException("HtmlPage.getImplementation is not yet implemented."); + } + + /** + * {@inheritDoc} * @param tagName the tag name, preferably in lowercase */ @Override @@ -578,27 +560,46 @@ * {@inheritDoc} * Not yet implemented. */ - public DOMImplementation getImplementation() { - throw new UnsupportedOperationException("HtmlPage.getImplementation is not yet implemented."); + public EntityReference createEntityReference(final String id) { + throw new UnsupportedOperationException("HtmlPage.createEntityReference is not yet implemented."); } /** * {@inheritDoc} * Not yet implemented. */ - public EntityReference createEntityReference(final String id) { - throw new UnsupportedOperationException("HtmlPage.createEntityReference is not yet implemented."); + public ProcessingInstruction createProcessingInstruction(final String namespaceURI, final String qualifiedName) { + throw new UnsupportedOperationException("HtmlPage.createProcessingInstruction is not yet implemented."); } /** * {@inheritDoc} + */ + public DomNodeList<DomElement> getElementsByTagName(final String tagName) { + return new XPathDomNodeList<DomElement>(this, "//*[local-name()='" + tagName + "']"); + } + + /** + * {@inheritDoc} * Not yet implemented. */ - public ProcessingInstruction createProcessingInstruction(final String namespaceURI, final String qualifiedName) { - throw new UnsupportedOperationException("HtmlPage.createProcessingInstruction is not yet implemented."); + public DomNodeList<DomElement> getElementsByTagNameNS(final String namespaceURI, final String localName) { + throw new UnsupportedOperationException("HtmlPage.getElementsByTagNameNS is not yet implemented."); } /** + * {@inheritDoc} + */ + public DomElement getElementById(final String elementId) { + try { + return getElementById(elementId, true); + } + catch (final ElementNotFoundException e) { + return null; + } + } + + /** * Returns the {@link HtmlAnchor} with the specified name. * * @param name the name to search by @@ -1333,6 +1334,15 @@ return true; } + /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * @return true if the OnbeforeunloadHandler has accepted to change the page + */ + public boolean isOnbeforeunloadAccepted() { + return executeEventHandlersIfNeeded(Event.TYPE_BEFORE_UNLOAD); + } + private boolean isOnbeforeunloadAccepted(final HtmlPage page, final Event event) { if (event.getType().equals(Event.TYPE_BEFORE_UNLOAD) && event.getReturnValue() != null) { final OnbeforeunloadHandler handler = getWebClient().getOnbeforeunloadHandler(); @@ -1767,6 +1777,55 @@ } /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * @param node the node that has just been added to the document + */ + void notifyNodeAdded(final DomNode node) { + if (node instanceof DomElement) { + addMappedElement((DomElement) node, true); + + if (node instanceof BaseFrameElement) { + frameElements_.add((BaseFrameElement) node); + } + for (final HtmlElement child : node.getHtmlElementDescendants()) { + if (child instanceof BaseFrameElement) { + frameElements_.add((BaseFrameElement) child); + } + } + + if ("base".equals(node.getNodeName())) { + calculateBase(); + } + } + node.onAddedToPage(); + } + + /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * @param node the node that has just been removed from the tree + */ + void notifyNodeRemoved(final DomNode node) { + if (node instanceof HtmlElement) { + removeMappedElement((HtmlElement) node, true, true); + + if (node instanceof BaseFrameElement) { + frameElements_.remove(node); + } + for (final HtmlElement child : node.getHtmlElementDescendants()) { + if (child instanceof BaseFrameElement) { + frameElements_.remove(child); + } + } + + if ("base".equals(node.getNodeName())) { + calculateBase(); + } + } + } + + /** * Adds an element to the ID and name maps, if necessary. * @param element the element to be added to the ID and name maps */ @@ -1788,7 +1847,23 @@ private void addElement(final Map<String, SortedSet<DomElement>> map, final DomElement element, final String attribute, final boolean recurse) { - final String value = element.getAttribute(attribute); + // first try real attributes + String value = element.getAttribute(attribute); + + if (DomElement.ATTRIBUTE_NOT_DEFINED == value && !(element instanceof HtmlApplet)) { + // second try are JavaScript attributes + // ...but applets are a bit special so ignore them + final ScriptableObject scriptObject = element.getScriptObject(); + // we have to make sure the scriptObject has a slot for the given attribute. + // just using get() may use e.g. getWithPreemption(). + if (scriptObject.has(attribute, scriptObject)) { + final Object jsValue = scriptObject.get(attribute, scriptObject); + if (jsValue != null && jsValue != Scriptable.NOT_FOUND && jsValue instanceof String) { + value = (String) jsValue; + } + } + } + if (DomElement.ATTRIBUTE_NOT_DEFINED != value) { SortedSet<DomElement> elements = map.get(value); if (elements == null) { @@ -1829,8 +1904,24 @@ } private void removeElement(final Map<String, SortedSet<DomElement>> map, final DomElement element, - final String att, final boolean recurse) { - final String value = element.getAttribute(att); + final String attribute, final boolean recurse) { + // first try real attributes + String value = element.getAttribute(attribute); + + if (DomElement.ATTRIBUTE_NOT_DEFINED == value && !(element instanceof HtmlApplet)) { + // second try are JavaScript attributes + // ...but applets are a bit special so ignore them + final ScriptableObject scriptObject = element.getScriptObject(); + // we have to make sure the scriptObject has a slot for the given attribute. + // just using get() may use e.g. getWithPreemption(). + if (scriptObject.has(attribute, scriptObject)) { + final Object jsValue = scriptObject.get(attribute, scriptObject); + if (jsValue != null && jsValue != Scriptable.NOT_FOUND && jsValue instanceof String) { + value = (String) jsValue; + } + } + } + if (!StringUtils.isEmpty(value)) { final SortedSet<DomElement> elements = map.remove(value); if (elements != null && (elements.size() != 1 || !elements.contains(element))) { @@ -1840,29 +1931,20 @@ } if (recurse) { for (final DomElement child : element.getChildElements()) { - removeElement(map, child, att, true); + removeElement(map, child, attribute, true); } } } /** - * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> - * - * @param node the node that has just been added to the document + * Indicates if the attribute name indicates that the owning element is mapped. + * @param document the owning document + * @param attributeName the name of the attribute to consider + * @return <code>true</code> if the owning element should be mapped in its owning page */ - void notifyNodeAdded(final DomNode node) { - if (node instanceof DomElement) { - addMappedElement((DomElement) node, true); - - if (node instanceof BaseFrameElement) { - frameElements_.add((BaseFrameElement) node); - } - - if ("base".equals(node.getNodeName())) { - calculateBase(); - } - } - node.onAddedToPage(); + static boolean isMappedElement(final Document document, final String attributeName) { + return (document instanceof HtmlPage) + && ("name".equals(attributeName) || "id".equals(attributeName)); } private void calculateBase() { @@ -1883,25 +1965,6 @@ } /** - * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> - * - * @param node the node that has just been removed from the tree - */ - void notifyNodeRemoved(final DomNode node) { - if (node instanceof HtmlElement) { - removeMappedElement((HtmlElement) node, true, true); - - if (node instanceof BaseFrameElement) { - frameElements_.remove(node); - } - - if ("base".equals(node.getNodeName())) { - calculateBase(); - } - } - } - - /** * Loads the content of the contained frames. This is done after the page is completely loaded, to allow script * contained in the frames to reference elements from the page located after the closing </frame> tag. * @throws FailingHttpStatusCodeException if the server returns a failing status code AND the property @@ -2059,9 +2122,17 @@ */ @Override public HtmlPage cloneNode(final boolean deep) { - final HtmlPage result = (HtmlPage) super.cloneNode(deep); + // we need the ScriptObject clone before cloning the kids. + final HtmlPage result = (HtmlPage) super.cloneNode(false); final SimpleScriptable jsObjClone = ((SimpleScriptable) getScriptObject()).clone(); jsObjClone.setDomNode(result); + + // if deep, clone the kids too. + if (deep) { + for (DomNode child = getFirstChild(); child != null; child = child.getNextSibling()) { + result.appendChild(child.cloneNode(true)); + } + } return result; } @@ -2174,15 +2245,6 @@ } /** - * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> - * - * @return true if the OnbeforeunloadHandler has accepted to change the page - */ - public boolean isOnbeforeunloadAccepted() { - return executeEventHandlersIfNeeded(Event.TYPE_BEFORE_UNLOAD); - } - - /** * Returns <tt>true</tt> if an HTML parser is operating on this page, adding content to it. * @return <tt>true</tt> if an HTML parser is operating on this page, adding content to it */ @@ -2208,7 +2270,7 @@ * Returns <tt>true</tt> if an HTML parser is parsing a non-inline HTML snippet to add content * to this page. Non-inline content is content that is parsed for the page, but not in the * same stream as the page itself -- basically anything other than <tt>document.write()</tt> - * or <tt>document.writeln()</tt>: <tt>innerHTML</tt>, <tt>otherHTML</tt>, + * or <tt>document.writeln()</tt>: <tt>innerHTML</tt>, <tt>outerHTML</tt>, * <tt>document.createElement()</tt>, etc. * * @return <tt>true</tt> if an HTML parser is parsing a non-inline HTML snippet to add content @@ -2230,11 +2292,6 @@ */ void registerSnippetParsingEnd() { snippetParserCount_--; - - // maybe the stream has added a iframe tag - if (0 == snippetParserCount_) { - loadFrames(); - } } /** @@ -2367,17 +2424,6 @@ } /** - * Indicates if the attribute name indicates that the owning element is mapped. - * @param document the owning document - * @param attributeName the name of the attribute to consider - * @return <code>true</code> if the owning element should be mapped in its owning page - */ - static boolean isMappedElement(final Document document, final String attributeName) { - return (document instanceof HtmlPage) - && ("name".equals(attributeName) || "id".equals(attributeName)); - } - - /** * Returns whether the current page mode is in quirks mode or in standards mode. * @return true for quirks mode, false for standards mode */ Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java 2014-02-01 11:57:37 UTC (rev 9096) @@ -217,15 +217,26 @@ // is the node allowed here? if (!isNodeInsertable(childNode)) { - // IE silently ignores it if (getBrowserVersion().hasFeature(JS_APPEND_CHILD_THROWS_NO_EXCEPTION_FOR_WRONG_NODE)) { - return childObject; + return childNode; } - throw asJavaScriptException( new DOMException("Node cannot be inserted at the specified point in the hierarchy", DOMException.HIERARCHY_REQUEST_ERR)); } + if (childObject instanceof DomDocumentFragment) { + final DomDocumentFragment fragment = (DomDocumentFragment) childObject; + for (final DomNode child : fragment.getChildren()) { + if (!isNodeInsertable((Node) child.getScriptObject())) { + if (getBrowserVersion().hasFeature(JS_APPEND_CHILD_THROWS_NO_EXCEPTION_FOR_WRONG_NODE)) { + return childNode; + } + throw asJavaScriptException( + new DOMException("Node cannot be inserted at the specified point in the hierarchy", + DOMException.HIERARCHY_REQUEST_ERR)); + } + } + } // Get XML node for the DOM node passed in final DomNode childDomNode = childNode.getDomNodeOrDie(); @@ -248,7 +259,7 @@ } initInlineFrameIfNeeded(childDomNode); - for (final DomNode domNode : childDomNode.getChildren()) { + for (final DomNode domNode : childDomNode.getDescendants()) { initInlineFrameIfNeeded(domNode); } } @@ -302,50 +313,6 @@ } /** - * Indicates if the node can be inserted. - * @param childObject the node - * @return <code>false</code> if it is not allowed here - */ - private boolean isNodeInsertable(final Node childObject) { - return !(childObject instanceof HTMLHtmlElement); - } - - /** - * Clones this node. - * @param deep if <tt>true</tt>, recursively clones all descendants - * @return the newly cloned node - */ - @JsxFunction - public Object cloneNode(final boolean deep) { - final DomNode domNode = getDomNodeOrDie(); - final DomNode clonedNode = domNode.cloneNode(deep); - - final Node jsClonedNode = getJavaScriptNode(clonedNode); - if (getBrowserVersion().hasFeature(JS_CLONE_NODE_COPIES_EVENT_LISTENERS)) { - // need to copy the event listener when they exist - copyEventListenersWhenNeeded(domNode, clonedNode); - } - return jsClonedNode; - } - - private void copyEventListenersWhenNeeded(final DomNode domNode, final DomNode clonedNode) { - final Node jsNode = (Node) domNode.getScriptObject(); - if (jsNode != null) { - final Node jsClonedNode = getJavaScriptNode(clonedNode); - jsClonedNode.getEventListenersContainer().copyFrom(jsNode.getEventListenersContainer()); - } - - // look through the children - DomNode child = domNode.getFirstChild(); - DomNode clonedChild = clonedNode.getFirstChild(); - while (child != null && clonedChild != null) { - copyEventListenersWhenNeeded(child, clonedChild); - child = child.getNextSibling(); - clonedChild = clonedChild.getNextSibling(); - } - } - - /** * Add a DOM node as a child to this node before the referenced node. * If the referenced node is null, append to the end. * @param context the JavaScript context @@ -375,7 +342,7 @@ else { refChildObject = Undefined.instance; } - Object appendedChild = null; + Object insertedChild = null; if (newChildObject instanceof Node) { final Node newChild = (Node) newChildObject; @@ -383,22 +350,29 @@ // is the node allowed here? if (!isNodeInsertable(newChild)) { - // IE silently ignores it if (getBrowserVersion().hasFeature(JS_APPEND_CHILD_THROWS_NO_EXCEPTION_FOR_WRONG_NODE)) { - return newChildNode; + return newChild; } - throw Context.reportRuntimeError("Node cannot be inserted at the specified point in the hierarchy"); + throw asJavaScriptException( + new DOMException("Node cannot be inserted at the specified point in the hierarchy", + DOMException.HIERARCHY_REQUEST_ERR)); } - if (newChildNode instanceof DomDocumentFragment) { final DomDocumentFragment fragment = (DomDocumentFragment) newChildNode; for (final DomNode child : fragment.getChildren()) { - insertBeforeImpl(new Object[] {child.getScriptObject(), refChildObject}); + if (!isNodeInsertable((Node) child.getScriptObject())) { + if (getBrowserVersion().hasFeature(JS_APPEND_CHILD_THROWS_NO_EXCEPTION_FOR_WRONG_NODE)) { + return newChild; + } + throw asJavaScriptException( + new DOMException("Node cannot be inserted at the specified point in the hierarchy", + DOMException.HIERARCHY_REQUEST_ERR)); + } } - return newChildObject; } + + // extract refChild final DomNode refChildNode; - // IE accepts non standard calls with only one argument if (refChildObject == Undefined.instance) { if (getBrowserVersion().hasFeature(JS_NODE_INSERT_BEFORE_THROW_EXCEPTION_FOR_EXTRA_ARGUMENT)) { if (args.length > 1) { @@ -423,40 +397,27 @@ } final DomNode domNode = getDomNodeOrDie(); - // Append the child to the parent node - if (refChildNode != null) { - refChildNode.insertBefore(newChildNode); - appendedChild = newChildObject; - } - else { - domNode.appendChild(newChildNode); - appendedChild = newChildObject; - } - // if parentNode is null in IE, create a DocumentFragment to be the parentNode + domNode.insertBefore(newChildNode, refChildNode); + insertedChild = newChild; + + // if parentNode is null, create a DocumentFragment to be the parentNode if (domNode.getParentNode() == null && getBrowserVersion() .hasFeature(JS_APPEND_CHILD_CREATE_DOCUMENT_FRAGMENT_PARENT)) { final DomDocumentFragment fragment = domNode.getPage().createDomDocumentFragment(); fragment.appendChild(domNode); } } - return appendedChild; + return insertedChild; } /** - * This method provides a way to determine whether two Node references returned by - * the implementation reference the same object. - * When two Node references are references to the same object, even if through a proxy, - * the references may be used completely interchangeably, such that all attributes - * have the same values and calling the same DOM method on either reference always has exactly the same effect. - * - * @param other the node to test against - * - * @return whether this node is the same node as the given one + * Indicates if the node can be inserted. + * @param childObject the node + * @return <code>false</code> if it is not allowed here */ - @JsxFunction({ @WebBrowser(CHROME), @WebBrowser(value = IE, minVersion = 9) }) - public boolean isSameNode(final Object other) { - return other == this; + private boolean isNodeInsertable(final Node childObject) { + return !(childObject instanceof HTMLHtmlElement); } /** @@ -480,6 +441,105 @@ } /** + * Replaces a child DOM node with another DOM node. + * @param newChildObject the node to add as a child of this node + * @param oldChildObject the node to remove as a child of this node + * @return the removed child node + */ + @JsxFunction + public Object replaceChild(final Object newChildObject, final Object oldChildObject) { + Object removedChild = null; + + if (newChildObject instanceof DocumentFragment) { + final DocumentFragment fragment = (DocumentFragment) newChildObject; + Node firstNode = null; + final Node refChildObject = ((Node) oldChildObject).getNextSibling(); + for (final DomNode node : fragment.getDomNodeOrDie().getChildren()) { + if (firstNode == null) { + replaceChild(node.getScriptObject(), oldChildObject); + firstNode = (Node) node.getScriptObject(); + } + else { + insertBeforeImpl(new Object[] {node.getScriptObject(), refChildObject}); + } + } + if (firstNode == null) { + removeChild(oldChildObject); + } + removedChild = oldChildObject; + } + else if (newChildObject instanceof Node && oldChildObject instanceof Node) { + final Node newChild = (Node) newChildObject; + + // is the node allowed here? + if (!isNodeInsertable(newChild)) { + throw Context.reportRuntimeError("Node cannot be inserted at the specified point in the hierarchy"); + } + + // Get XML nodes for the DOM nodes passed in + final DomNode newChildNode = newChild.getDomNodeOrDie(); + final DomNode oldChildNode = ((Node) oldChildObject).getDomNodeOrDie(); + + // Replace the old child with the new child. + oldChildNode.replace(newChildNode); + removedChild = oldChildObject; + } + + return removedChild; + } + + /** + * Clones this node. + * @param deep if <tt>true</tt>, recursively clones all descendants + * @return the newly cloned node + */ + @JsxFunction + public Object cloneNode(final boolean deep) { + final DomNode domNode = getDomNodeOrDie(); + final DomNode clonedNode = domNode.cloneNode(deep); + + final Node jsClonedNode = getJavaScriptNode(clonedNode); + if (getBrowserVersion().hasFeature(JS_CLONE_NODE_COPIES_EVENT_LISTENERS)) { + // need to copy the event listener when they exist + copyEventListenersWhenNeeded(domNode, clonedNode); + } + return jsClonedNode; + } + + private void copyEventListenersWhenNeeded(final DomNode domNode, final DomNode clonedNode) { + final Node jsNode = (Node) domNode.getScriptObject(); + if (jsNode != null) { + final Node jsClonedNode = getJavaScriptNode(clonedNode); + jsClonedNode.getEventListenersContainer().copyFrom(jsNode.getEventListenersContainer()); + } + + // look through the children + DomNode child = domNode.getFirstChild(); + DomNode clonedChild = clonedNode.getFirstChild(); + while (child != null && clonedChild != null) { + copyEventListenersWhenNeeded(child, clonedChild); + child = child.getNextSibling(); + clonedChild = clonedChild.getNextSibling(); + } + } + + /** + * This method provides a way to determine whether two Node references returned by + * the implementation reference the same object. + * When two Node references are references to the same object, even if through a proxy, + * the references may be used completely interchangeably, such that all attributes + * have the same values and calling the same DOM method on either reference always has exactly the same effect. + * + * @param other the node to test against + * + * @return whether this node is the same node as the given one + */ + @JsxFunction({ @WebBrowser(CHROME), @WebBrowser(value = IE, minVersion = 9) }) + public boolean isSameNode(final Object other) { + return other == this; + } + + /** * Returns whether this node has any children. * @return boolean true if this node has any children, false otherwise */ @@ -543,54 +603,6 @@ } /** - * Replaces a child DOM node with another DOM node. - * @param newChildObject the node to add as a child of this node - * @param oldChildObject the node to remove as a child of this node - * @return the removed child node - */ - @JsxFunction - public Object replaceChild(final Object newChildObject, final Object oldChildObject) { - Object removedChild = null; - - if (newChildObject instanceof DocumentFragment) { - final DocumentFragment fragment = (DocumentFragment) newChildObject; - Node firstNode = null; - final Node refChildObject = ((Node) oldChildObject).getNextSibling(); - for (final DomNode node : fragment.getDomNodeOrDie().getChildren()) { - if (firstNode == null) { - replaceChild(node.getScriptObject(), oldChildObject); - firstNode = (Node) node.getScriptObject(); - } - else { - insertBeforeImpl(new Object[] {node.getScriptObject(), refChildObject}); - } - } - if (firstNode == null) { - removeChild(oldChildObject); - } - removedChild = oldChildObject; - } - else if (newChildObject instanceof Node && oldChildObject instanceof Node) { - final Node newChild = (Node) newChildObject; - - // is the node allowed here? - if (!isNodeInsertable(newChild)) { - throw Context.reportRuntimeError("Node cannot be inserted at the specified point in the hierarchy"); - } - - // Get XML nodes for the DOM nodes passed in - final DomNode newChildNode = newChild.getDomNodeOrDie(); - final DomNode oldChildNode = ((Node) oldChildObject).getDomNodeOrDie(); - - // Replace the old child with the new child. - oldChildNode.replace(newChildNode); - removedChild = oldChildObject; - } - - return removedChild; - } - - /** * Returns this node's parent node. * @return this node's parent node */ Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NodeList.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NodeList.java 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NodeList.java 2014-02-01 11:57:37 UTC (rev 9096) @@ -39,6 +39,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlAttributeChangeEvent; import com.gargoylesoftware.htmlunit.html.HtmlAttributeChangeListener; import com.gargoylesoftware.htmlunit.html.HtmlElement; +import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; import com.gargoylesoftware.htmlunit.javascript.configuration.JavaScriptConfiguration; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; @@ -220,8 +221,13 @@ final DomNode domNode = getDomNodeOrNull(); if (domNode != null) { domNode.addDomChangeListener(listener); - if (attributeChangeSensitive_ && domNode instanceof HtmlElement) { - ((HtmlElement) domNode).addHtmlAttributeChangeListener(listener); + if (attributeChangeSensitive_) { + if (domNode instanceof HtmlElement) { + ((HtmlElement) domNode).addHtmlAttributeChangeListener(listener); + } + else if (domNode instanceof HtmlPage) { + ((HtmlPage) domNode).addHtmlAttributeChangeListener(listener); + } } } listenerRegistered_ = true; 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 2014-01-31 21:55:16 UTC (rev 9095) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-02-01 11:57:37 UTC (rev 9096) @@ -76,7 +76,6 @@ import com.gargoylesoftware.htmlunit.ScriptResult; import com.gargoylesoftware.htmlunit.SgmlPage; import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.BaseFrameElement; import com.gargoylesoftware.htmlunit.html.DomAttr; import com.gargoylesoftware.htmlunit.html.DomCharacterData; import com.gargoylesoftware.htmlunit.html.DomComment; @@ -713,6 +712,22 @@ } /** + * Gets the attributes of the element in the form of a {@link org.xml.sax.Attributes}. + * @param element the element to read the attributes from + * @return the attributes + */ + protected AttributesImpl readAttributes(final HtmlElement element) { + final AttributesImpl attributes = new AttributesImpl(); + for (final DomAttr entry : element.getAttributesMap().values()) { + final String name = entry.getName(); + final String value = entry.getValue(); + attributes.addAttribute(null, name, name, null, value); + } + + return attributes; + } + + /** * Removes this object from the document hierarchy. * @param removeChildren whether to remove children or no * @return a reference to the object that is removed @@ -943,8 +958,8 @@ } /** - * Replace all children elements of this element with the supplied value. - * @param value the new value for the contents of this node + * Replaces all child elements of this element with the supplied value. + * @param value the new value for the contents of this element */ @JsxSetter public void setInnerHTML(final Object value) { @@ -952,21 +967,12 @@ domNode.removeAllChildren(); - // null && IE -> add child - // null && non-IE -> Don't add - // '' -> Don't add final boolean addChildForNull = getBrowserVersion().hasFeature(JS_INNER_HTML_ADD_CHILD_FOR_NULL_VALUE); if ((value == null && addChildForNull) || (value != null && !"".equals(value))) { final String valueAsString = Context.toString(value); - parseHtmlSnippet(domNode, true, valueAsString); + parseHtmlSnippet(domNode, valueAsString); - for (final DomNode node : domNode.getDescendants()) { - if (node instanceof BaseFrameElement) { - ((BaseFrameElement) node).markLoadSrcWhenAddedToPage(); - } - } - final boolean createFragment = getBrowserVersion().hasFeature(JS_INNER_HTML_CREATES_DOC_FRAGMENT_AS_PARENT); // if the parentNode has null parentNode in IE, // create a DocumentFragment to be the parentNode's parentNode. @@ -978,8 +984,8 @@ } /** - * Replace all children elements of this element with the supplied value. - * @param value the new value for the contents of this node + * Replaces all child elements of this element with the supplied text value. + * @param value the new value for the contents of this element */ @JsxSetter({ @WebBrowser(IE), @WebBrowser(CHROME) }) public void setInnerText(final String value) { @@ -1009,8 +1015,8 @@ } /** - * Replace all children elements of this element with the supplied value. - * @param value the new value for the contents of this node + * Replaces all child elements of this element with the supplied text value. + * @param value the new value for the contents of this element */ @Override public void setTextContent(final Object value) { @@ -1018,52 +1024,57 @@ } /** - * Replace all children elements of this element with the supplied value. - * Sets the outerHTML of the node. - * @param value the new value for replacing this node - * @see <a href="http://msdn.microsoft.com/en-us/library/ms534310.aspx">MSDN documentation</a> + * Replaces this element (including all child elements) with the supplied value. + * @param value the new value for replacing this element */ @JsxSetter public void setOuterHTML(final String value) { final DomNode domNode = getDomNodeOrDie(); + final DomNode parent = do... [truncated message content] |
From: <asa...@us...> - 2014-02-02 10:23:37
|
Revision: 9099 http://sourceforge.net/p/htmlunit/code/9099 Author: asashour Date: 2014-02-02 10:23:34 +0000 (Sun, 02 Feb 2014) Log Message: ----------- JavaScript: handle 'arguments' as a parameter. Issue 1452 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/ArgumentsTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-02-01 13:20:06 UTC (rev 9098) +++ trunk/htmlunit/src/changes/changes.xml 2014-02-02 10:23:34 UTC (rev 9099) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="asashour" issue="1572"> + JavaScript: handle 'arguments' as a parameter. + </action> <action type="fix" dev="rbri" due-to="Frank Danek"> JavaScript: Internal cleanup and some fixes for the innerHTML/outerHTML/insertAdjacentHTML. Fix appendChild/insertBefore/replaceChild also. Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/ArgumentsTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/ArgumentsTest.java 2014-02-01 13:20:06 UTC (rev 9098) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/ArgumentsTest.java 2014-02-02 10:23:34 UTC (rev 9099) @@ -154,4 +154,20 @@ loadPageWithAlerts2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("hi") + public void argumentsAsParameter() throws Exception { + final String html = "<html><body><script>\n" + + "function test1(arguments) {\n" + + " alert(arguments);\n" + + "}\n" + + "test1('hi');\n" + + "</script></body></html>"; + + loadPageWithAlerts2(html); + } } |
From: <rb...@us...> - 2014-02-02 14:29:04
|
Revision: 9101 http://sourceforge.net/p/htmlunit/code/9101 Author: rbri Date: 2014-02-02 14:29:00 +0000 (Sun, 02 Feb 2014) Log Message: ----------- Fix encoding of innerHTML result for script content 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/javascript/host/html/HTMLScriptElementTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-02-02 10:34:29 UTC (rev 9100) +++ trunk/htmlunit/src/changes/changes.xml 2014-02-02 14:29:00 UTC (rev 9101) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="rbri" issue="1509"> + JavaScript: Fix encoding of innerHTML result for script content. + </action> <action type="fix" dev="asashour" issue="1572"> JavaScript: handle 'arguments' as a parameter. </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 2014-02-02 10:34:29 UTC (rev 9100) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLElement.java 2014-02-02 14:29:00 UTC (rev 9101) @@ -941,7 +941,10 @@ } buffer.append(">"); // Add the children. - printChildren(buffer, node, html); + final boolean isHtml = html + && !(scriptObject instanceof HTMLScriptElement) + && !(scriptObject instanceof HTMLStyleElement); + printChildren(buffer, node, isHtml); if (null == htmlElement || !htmlElement.isEndTagForbidden()) { buffer.append("</").append(tag).append(">"); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLScriptElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLScriptElementTest.java 2014-02-02 10:34:29 UTC (rev 9100) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLScriptElementTest.java 2014-02-02 14:29:00 UTC (rev 9101) @@ -909,4 +909,35 @@ loadPageWithAlerts2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = { "\n <script id=\"testScript\">function foo() { return a > b}</script>\n " }, + IE8 = { "" }) + @NotYetImplemented(IE8) + public void innerHTMLGetSet() throws Exception { + final String html + = "<html>\n" + + "<head></head>\n" + + "<body>\n" + + + " <div id='tester'>\n" + + " <script id='testScript'>function foo() { return a > b}</script>\n" + + " </div>\n" + + + " <script type='text/javascript'>\n" + + " var div = document.getElementById('tester');\n" + + " try {\n" + + " div.innerHTML = div.innerHTML;\n" + + " } catch (e) { alert('exception'); }\n" + + " alert(div.innerHTML);\n" + + " </script>\n" + + + "</body>\n" + + "</html>\n"; + + loadPageWithAlerts2(html); + } } |
From: <rb...@us...> - 2014-02-04 16:51:32
|
Revision: 9108 http://sourceforge.net/p/htmlunit/code/9108 Author: rbri Date: 2014-02-04 16:51:29 +0000 (Tue, 04 Feb 2014) Log Message: ----------- test assert fix; window.createPopup is not available in IE11 Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Popup.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Popup2Test.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Popup.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Popup.java 2014-02-04 08:28:49 UTC (rev 9107) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Popup.java 2014-02-04 16:51:29 UTC (rev 9108) @@ -40,9 +40,10 @@ * @author Marc Guillemot * @author David K. Taylor * @author Ahmed Ashour + * @author Ronald Brill * @see <a href="http://msdn.microsoft.com/en-us/library/ms535882.aspx">MSDN documentation</a> */ -@JsxClass(browsers = @WebBrowser(IE)) +@JsxClass(browsers = @WebBrowser(value = IE, maxVersion = 10)) public class Popup extends SimpleScriptable { private boolean opened_; Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java 2014-02-04 08:28:49 UTC (rev 9107) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java 2014-02-04 16:51:29 UTC (rev 9108) @@ -403,7 +403,7 @@ * @see <a href="http://msdn.microsoft.com/en-us/library/ms536392.aspx">MSDN documentation</a> * @return the created popup */ - @JsxFunction(@WebBrowser(IE)) + @JsxFunction(@WebBrowser(value = IE, maxVersion = 10)) public Popup createPopup() { final Popup popup = new Popup(); popup.setParentScope(this); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Popup2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Popup2Test.java 2014-02-04 08:28:49 UTC (rev 9107) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Popup2Test.java 2014-02-04 16:51:29 UTC (rev 9108) @@ -36,21 +36,21 @@ * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = "exception", IE = "done") + @Alerts(DEFAULT = "exception", IE8 = "done") public void testPopup() throws Exception { final String html = "<html><head><title>First</title><body>\n" + "<script>\n" - + "try {\n" - + "var oPopup = window.createPopup();\n" - + "var oPopupBody = oPopup.document.body;\n" - + "oPopupBody.innerHTML = 'bla bla';\n" - + "oPopup.show(100, 100, 200, 50, document.body);\n" - + "alert('done');\n" - + "} catch(e) { alert('exception'); }\n" + + " try {\n" + + " var oPopup = window.createPopup();\n" + + " var oPopupBody = oPopup.document.body;\n" + + " oPopupBody.innerHTML = 'bla bla';\n" + + " oPopup.show(100, 100, 200, 50, document.body);\n" + + " alert('done');\n" + + " } catch(e) { alert('exception'); }\n" + "</script>\n" + "</body></html>"; - loadPage2(html); + loadPageWithAlerts2(html); } /** @@ -59,19 +59,19 @@ * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = "exception", IE = "done") + @Alerts(DEFAULT = "exception", IE8 = "done") public void testPopupBodyStyle() throws Exception { final String html = "<html><head><title>First</title><body>\n" + "<script language='javascript'>\n" - + "try {\n" - + " popup = window.createPopup();\n" - + " popupBody = popup.document.body;\n" - + " popupBody.style.backgroundColor = '#7f7fff';\n" - + " alert('done');\n" - + "} catch(e) { alert('exception'); }\n" + + " try {\n" + + " popup = window.createPopup();\n" + + " popupBody = popup.document.body;\n" + + " popupBody.style.backgroundColor = '#7f7fff';\n" + + " alert('done');\n" + + " } catch(e) { alert('exception'); }\n" + "</script>\n" + "</body></html>"; - loadPage2(html); + loadPageWithAlerts2(html); } } |
From: <asa...@us...> - 2014-02-05 00:32:32
|
Revision: 9109 http://sourceforge.net/p/htmlunit/code/9109 Author: asashour Date: 2014-02-05 00:32:28 +0000 (Wed, 05 Feb 2014) Log Message: ----------- Fix for HTMLObjectElement: classid could be affected by webClient.setActiveXObjectMap(). Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElement.java 2014-02-04 16:51:29 UTC (rev 9108) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElement.java 2014-02-05 00:32:28 UTC (rev 9109) @@ -21,9 +21,11 @@ import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; +import net.sourceforge.htmlunit.corejs.javascript.Wrapper; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlObject; +import com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxSetter; @@ -39,7 +41,7 @@ * @author Ronald Brill */ @JsxClass(domClass = HtmlObject.class) -public class HTMLObjectElement extends FormChild { +public class HTMLObjectElement extends FormChild implements Wrapper { private Scriptable wrappedActiveX_; @@ -109,7 +111,7 @@ final Object object = xClass.newInstance(); boolean contextCreated = false; if (Context.getCurrentContext() == null) { - Context.enter(); + new HtmlUnitContextFactory(webClient).enterContext(); contextCreated = true; } wrappedActiveX_ = Context.toObject(object, getParentScope()); @@ -160,4 +162,15 @@ super.put(name, start, value); } } + + /** + * {@inheritDoc} + */ + @Override + public Object unwrap() { + if (wrappedActiveX_ instanceof Wrapper) { + return ((Wrapper) wrappedActiveX_).unwrap(); + } + return wrappedActiveX_; + } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java 2014-02-04 16:51:29 UTC (rev 9108) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLObjectElementTest.java 2014-02-05 00:32:28 UTC (rev 9109) @@ -57,14 +57,18 @@ * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = "undefined", IE = "ActiveX is working!") + @Alerts(DEFAULT = "undefined", IE = { "ActiveX is working!", "Javascript called this method!" }) public void classid() throws Exception { final String clsid = "clsid:TESTING-CLASS-ID"; final String html = "<html><head>\n" + "<object id='id1' classid='" + clsid + "'></object>\n" + "<script>\n" + " function test() {\n" - + " alert(document.all.id1.MESSAGE);\n" + + " var obj = document.all.id1;" + + " alert(obj.MESSAGE);\n" + + " if (obj.GetMessage) {\n" + + " alert(obj.GetMessage());\n" + + " }\n" + " }\n" + "</script>\n" + "</head><body onload='test()'>\n" |
From: <rb...@us...> - 2014-02-07 13:59:39
|
Revision: 9112 http://sourceforge.net/p/htmlunit/code/9112 Author: rbri Date: 2014-02-07 13:59:36 +0000 (Fri, 07 Feb 2014) Log Message: ----------- GAEJavaScriptExecutor is public again but marked as part of the internal api. Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/GAEJavaScriptExecutor.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2014-02-07 12:09:20 UTC (rev 9111) +++ trunk/htmlunit/src/changes/changes.xml 2014-02-07 13:59:36 UTC (rev 9112) @@ -8,6 +8,9 @@ <body> <release version="2.14" date="???" description="FF24, Bugfixes, initial work on IE11"> + <action type="fix" dev="rbri" issue="1503"> + GAEJavaScriptExecutor is public again but marked as part of the internal api. + </action> <action type="fix" dev="rbri" issue="1509"> JavaScript: Fix encoding of innerHTML result for script content. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/GAEJavaScriptExecutor.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/GAEJavaScriptExecutor.java 2014-02-07 12:09:20 UTC (rev 9111) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/GAEJavaScriptExecutor.java 2014-02-07 13:59:36 UTC (rev 9112) @@ -17,6 +17,8 @@ import com.gargoylesoftware.htmlunit.WebClient; /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * * Google App Engine specific subclass to facilitate execution of JS jobs. * * @version $Revision$ @@ -24,7 +26,7 @@ * @author Kostadin Chikov * @author Ronald Brill */ -class GAEJavaScriptExecutor extends DefaultJavaScriptExecutor { +public class GAEJavaScriptExecutor extends DefaultJavaScriptExecutor { private static final long serialVersionUID = 6730370472962866668L; /** Creates an EventLoop for the webClient. |
From: <rb...@us...> - 2014-02-08 18:21:25
|
Revision: 9116 http://sourceforge.net/p/htmlunit/code/9116 Author: rbri Date: 2014-02-08 18:21:20 +0000 (Sat, 08 Feb 2014) Log Message: ----------- correct the order of frame element initialization; revalidated with reals browsers Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFrame2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-02-08 13:02:26 UTC (rev 9115) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-02-08 18:21:20 UTC (rev 9116) @@ -226,10 +226,6 @@ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME), @WebBrowser(value = IE, minVersion = 11) }) EVENT_ONLOAD_EXTERNAL_JAVASCRIPT, - /** Triggers "onload" event of the frameset before the one from the frames. */ - @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) - EVENT_ONLOAD_FRAMESET_FIRST, - /** Triggers "onload" event if an iframe was created by javascript and added to the page. */ @BrowserFeature({ @WebBrowser(FF), @WebBrowser(CHROME), @WebBrowser(value = IE, minVersion = 11) }) EVENT_ONLOAD_IFRAME_CREATED_BY_JAVASCRIPT, Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2014-02-08 13:02:26 UTC (rev 9115) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2014-02-08 18:21:20 UTC (rev 9116) @@ -16,7 +16,6 @@ import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.EVENT_DOM_CONTENT_LOADED; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.EVENT_ONBEFOREUNLOAD_USES_EVENT; -import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.EVENT_ONLOAD_FRAMESET_FIRST; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.EVENT_ONLOAD_IFRAME_CREATED_BY_JAVASCRIPT; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.FOCUS_BODY_ELEMENT_AT_START; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.FOCUS_HTML_ELEMENT_AT_START; @@ -254,7 +253,6 @@ setReadyStateOnDeferredScriptsIfNeeded(); // frame initialization has a different order - final boolean framesetFirst = browserVersion.hasFeature(EVENT_ONLOAD_FRAMESET_FIRST); boolean isFrameWindow = enclosingWindow instanceof FrameWindow; boolean isFirstPageInFrameWindow = false; if (isFrameWindow) { @@ -262,7 +260,7 @@ isFirstPageInFrameWindow = enclosingWindow.getHistory().getLength() <= 2; // first is always about:blank } - if ((framesetFirst && !isFrameWindow) || (isFrameWindow && !isFirstPageInFrameWindow)) { + if (isFrameWindow && !isFirstPageInFrameWindow) { executeEventHandlersIfNeeded(Event.TYPE_LOAD); } @@ -275,7 +273,7 @@ } } - if (!framesetFirst && !isFrameWindow) { + if (!isFrameWindow) { executeEventHandlersIfNeeded(Event.TYPE_LOAD); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFrame2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFrame2Test.java 2014-02-08 13:02:26 UTC (rev 9115) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlFrame2Test.java 2014-02-08 18:21:20 UTC (rev 9116) @@ -96,29 +96,28 @@ /** * Regression test for for bug - * <a href="http://sf.net/support/tracker.php?aid=2873802">2873802</a>. + * <a href="http://sourceforge.net/p/htmlunit/bugs/925/">925</a>. * @throws Exception if an error occurs */ @Test - @Alerts(FF = { "second [object HTMLFormElement]", "third [object HTMLFormElement]", + @Alerts(DEFAULT = { "second [object HTMLFormElement]", "third [object HTMLFormElement]", "parent [object HTMLFormElement]" }, - IE = { "parent [object]", "second [object]", "third [object]" }, - IE11 = { }) + IE8 = { "second [object]", "third [object]", "parent [object]" }) // real FF sometimes alerts 'third' before 'second' - // real IE11 does not know frames.XXX.document anymore public void postponeLoading() throws Exception { - final String html = "<FRAMESET onload=\"alert('parent ' + window.parent.frames.third.document.frm)\">\n" - + " <FRAME name=second frameborder=0 src='second.html'>\n" - + " <FRAME name=third frameborder=0 src='third.html'>\n" + final String html = "<FRAMESET rows='50%,*' " + + "onload=\"alert('parent ' + window.parent.frames['third'].document.frm)\">\n" + + " <FRAME name='second' frameborder='0' src='second.html'>\n" + + " <FRAME name='third' frameborder='0' src='third.html'>\n" + "</FRAMESET>"; final String secondHtml = "<html>\n" - + "<body onload=\"alert('second ' + window.parent.frames.third.document.frm)\">\n" + + "<body onload=\"alert('second ' + window.parent.frames['third'].document.frm)\">\n" + " <h1>second</h1>\n" + "</body></html>"; final String thirdHtml = "<html>\n" - + "<body onload=\"alert('third ' + window.parent.frames.third.document.frm)\">\n" + + "<body onload=\"alert('third ' + window.parent.frames['third'].document.frm)\">\n" + " <form name='frm' id='frm'>\n" + " <input type='text' id='one' name='one' value='something'>\n" + " </form>\n" @@ -133,6 +132,7 @@ * @throws Exception if an error occurs */ @Test + @Alerts({ "second", "third", "first" }) public void frameOnload() throws Exception { final String html = "<FRAMESET rows='50%,50%' onload=\"alert('first')\">\n" + " <FRAME name='second' src='second.html'>\n" @@ -152,22 +152,7 @@ getMockWebConnection().setResponse(new URL(getDefaultUrl(), "second.html"), secondHtml); getMockWebConnection().setResponse(new URL(getDefaultUrl(), "third.html"), thirdHtml); - final WebDriver driver = loadPage2(html); - final List<String> actualAlerts = getCollectedAlerts(driver); - - // tested with real ff17 and ie6; running in selenium returns different results - Assert.assertEquals(3, actualAlerts.size()); - - // ignore order of frame windows - if (getBrowserVersion().isIE() && BrowserVersion.INTERNET_EXPLORER_11 != getBrowserVersion()) { - // returns 'first' 'third' 'second' - Assert.assertEquals("first", actualAlerts.get(0)); - } - else { - // IE11 returns 'second' 'third' 'first' - // DEFAULT returns 'third' 'second' 'first' - Assert.assertEquals("first", actualAlerts.get(2)); - } + loadPageWithAlerts2(html); } /** Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java 2014-02-08 13:02:26 UTC (rev 9115) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java 2014-02-08 18:21:20 UTC (rev 9116) @@ -14,6 +14,7 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.html; +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF17; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF24; import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.IE8; @@ -382,6 +383,60 @@ * @throws Exception if the test fails */ @Test + @Alerts({ "head", "bottom", "frameset" }) + public void onloadOrderRows() throws Exception { + final String html = "<html><head><title>OnloadTest</title></head>\n" + + "<frameset rows='50%,*' onLoad='alert(\"frameset\")'>\n" + + " <frame name='head' src='head.html'>\n" + + " <frame name='bottom' src='bottom.html'>\n" + + "</frameset>\n" + + "</html>"; + + final String top = "<html><head><title>Head</title></head>\n" + + "<body onload='alert(\"head\")'>head</body>\n" + + "</html>"; + final String bottom = "<html><head><title>Bottom</title></head>\n" + + "<body onload='alert(\"bottom\")'>bottom</body>\n" + + "</html>"; + + getMockWebConnection().setResponse(new URL(URL_FIRST, "head.html"), top); + getMockWebConnection().setResponse(new URL(URL_FIRST, "bottom.html"), bottom); + + loadPageWithAlerts2(html); + assertEquals(3, getMockWebConnection().getRequestCount()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({ "left", "right", "frameset" }) + public void onloadOrderCols() throws Exception { + final String html = "<html><head><title>OnloadTest</title></head>\n" + + "<frameset cols='50%,*' onLoad='alert(\"frameset\")'>\n" + + " <frame name='left' src='left.html'>\n" + + " <frame name='right' src='right.html'>\n" + + "</frameset>\n" + + "</html>"; + + final String left = "<html><head><title>Left</title></head>\n" + + "<body onload='alert(\"left\")'>left</body>\n" + + "</html>"; + final String right = "<html><head><title>Right</title></head>\n" + + "<body onload='alert(\"right\")'>right</body>\n" + + "</html>"; + + getMockWebConnection().setResponse(new URL(URL_FIRST, "left.html"), left); + getMockWebConnection().setResponse(new URL(URL_FIRST, "right.html"), right); + + loadPageWithAlerts2(html); + assertEquals(3, getMockWebConnection().getRequestCount()); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts({ "OnloadTest", "header -> content -> frameSet", "content\nClick for new frame content with onload", "header -> content -> frameSet -> onloadFrame", @@ -390,9 +445,9 @@ public void windowLocationReplaceOnload() throws Exception { final String html = "<html><head><title>OnloadTest</title></head>\n" + "<frameset rows=\"50,*\" onLoad=\"top.header.addToFrameOrder('frameSet');\">\n" - + " <frame name=\"header\" src=\"header.html\"></frame>\n" + + " <frame name=\"header\" src=\"header.html\">\n" + " <frame name=\"content\" id=\"content\" " - + "src=\"javascript:window.location.replace('content.html')\"></frame>\n" + + "src=\"javascript:window.location.replace('content.html')\">\n" + "</frameset>\n" + "</html>"; @@ -406,23 +461,23 @@ + " }\n" + "</script>\n" + "<body onload=\"addToFrameOrder('header');\">\n" - + "<div id=\"frameOrder\"></div>\n" + + " <div id=\"frameOrder\"></div>\n" + "</body></html>"; final String contentFrame = "<html><head><title>contentFrame</title></head>\n" + "<body onload=\"top.header.addToFrameOrder('content');\">\n" - + "<h3>content</h3>\n" - + "<a name=\"onloadFrameAnchor\" href=\"onload.html\" " + + " <h3>content</h3>\n" + + " <a name=\"onloadFrameAnchor\" href=\"onload.html\" " + "target=\"content\">Click for new frame content with onload</a>\n" + "</body></html>"; final String onloadFrame = "<html><head><title>onloadFrame</title></head>\n" + "<body onload=\"alert('Onload alert.');top.header.addToFrameOrder('onloadFrame');\">\n" - + "<script type=\"text/javascript\">\n" - + " alert('Body alert.');\n" - + "</script>\n" - + "<h3>onloadFrame</h3>\n" - + "<p id=\"newContent\">New content loaded...</p>\n" + + " <script type=\"text/javascript\">\n" + + " alert('Body alert.');\n" + + " </script>\n" + + " <h3>onloadFrame</h3>\n" + + " <p id=\"newContent\">New content loaded...</p>\n" + "</body></html>"; getMockWebConnection().setResponse(URL_FIRST, html); @@ -463,13 +518,13 @@ "header -> content -> frameSet -> onloadFrame", "onloadFrame\nNew content loaded..." }, FF = { "OnloadTest", "header -> frameSet", "" }) - @NotYetImplemented + @NotYetImplemented(FF) public void windowLocationAssignOnload() throws Exception { final String html = "<html><head><title>OnloadTest</title></head>\n" + "<frameset rows=\"50,*\" onLoad=\"top.header.addToFrameOrder('frameSet');\">\n" - + " <frame name=\"header\" src=\"header.html\"></frame>\n" + + " <frame name=\"header\" src=\"header.html\">\n" + " <frame name=\"content\" id=\"content\" " - + "src=\"javascript:window.location.assign('content.html')\"></frame>\n" + + "src=\"javascript:window.location.assign('content.html')\">\n" + "</frameset>\n" + "</html>"; @@ -483,23 +538,23 @@ + " }\n" + "</script>\n" + "<body onload=\"addToFrameOrder('header');\">\n" - + "<div id=\"frameOrder\"></div>\n" + + " <div id=\"frameOrder\"></div>\n" + "</body></html>"; final String contentFrame = "<html><head><title>contentFrame</title></head>\n" + "<body onload=\"top.header.addToFrameOrder('content');\">\n" - + "<h3>content</h3>\n" - + "<a name=\"onloadFrameAnchor\" href=\"onload.html\" " + + " <h3>content</h3>\n" + + " <a name=\"onloadFrameAnchor\" href=\"onload.html\" " + "target=\"content\">Click for new frame content with onload</a>\n" + "</body></html>"; final String onloadFrame = "<html><head><title>onloadFrame</title></head>\n" + "<body onload=\"alert('Onload alert.');top.header.addToFrameOrder('onloadFrame');\">\n" - + "<script type=\"text/javascript\">\n" - + " alert('Body alert.');\n" - + "</script>\n" - + "<h3>onloadFrame</h3>\n" - + "<p id=\"newContent\">New content loaded...</p>\n" + + " <script type=\"text/javascript\">\n" + + " alert('Body alert.');\n" + + " </script>\n" + + " <h3>onloadFrame</h3>\n" + + " <p id=\"newContent\">New content loaded...</p>\n" + "</body></html>"; getMockWebConnection().setResponse(URL_FIRST, html); @@ -545,9 +600,9 @@ public void windowLocationSetOnload() throws Exception { final String html = "<html><head><title>OnloadTest</title></head>\n" + "<frameset rows=\"50,*\" onLoad=\"top.header.addToFrameOrder('frameSet');\">\n" - + " <frame name=\"header\" src=\"header.html\"></frame>\n" + + " <frame name=\"header\" src=\"header.html\">\n" + " <frame name=\"content\" id=\"content\" " - + "src=\"javascript:window.location='content.html'\"></frame>\n" + + "src=\"javascript:window.location='content.html'\">\n" + "</frameset>\n" + "</html>"; @@ -561,23 +616,23 @@ + " }\n" + "</script>\n" + "<body onload=\"addToFrameOrder('header');\">\n" - + "<div id=\"frameOrder\"></div>\n" + + " <div id=\"frameOrder\"></div>\n" + "</body></html>"; final String contentFrame = "<html><head><title>contentFrame</title></head>\n" + "<body onload=\"top.header.addToFrameOrder('content');\">\n" - + "<h3>content</h3>\n" - + "<a name=\"onloadFrameAnchor\" href=\"onload.html\" " + + " <h3>content</h3>\n" + + " <a name=\"onloadFrameAnchor\" href=\"onload.html\" " + "target=\"content\">Click for new frame content with onload</a>\n" + "</body></html>"; final String onloadFrame = "<html><head><title>onloadFrame</title></head>\n" + "<body onload=\"alert('Onload alert.');top.header.addToFrameOrder('onloadFrame');\">\n" - + "<script type=\"text/javascript\">\n" - + " alert('Body alert.');\n" - + "</script>\n" - + "<h3>onloadFrame</h3>\n" - + "<p id=\"newContent\">New content loaded...</p>\n" + + " <script type=\"text/javascript\">\n" + + " alert('Body alert.');\n" + + " </script>\n" + + " <h3>onloadFrame</h3>\n" + + " <p id=\"newContent\">New content loaded...</p>\n" + "</body></html>"; getMockWebConnection().setResponse(URL_FIRST, html); |
From: <rb...@us...> - 2014-02-09 19:01:14
|
Revision: 9118 http://sourceforge.net/p/htmlunit/code/9118 Author: rbri Date: 2014-02-09 19:01:11 +0000 (Sun, 09 Feb 2014) Log Message: ----------- a first fix for Issue #1505 (wip) Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2014-02-08 18:27:10 UTC (rev 9117) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2014-02-09 19:01:11 UTC (rev 9118) @@ -70,6 +70,7 @@ import com.gargoylesoftware.htmlunit.Cache; import com.gargoylesoftware.htmlunit.ElementNotFoundException; import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.History; import com.gargoylesoftware.htmlunit.OnbeforeunloadHandler; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.ScriptResult; @@ -257,7 +258,14 @@ boolean isFirstPageInFrameWindow = false; if (isFrameWindow) { isFrameWindow = ((FrameWindow) enclosingWindow).getFrameElement() instanceof HtmlFrame; - isFirstPageInFrameWindow = enclosingWindow.getHistory().getLength() <= 2; // first is always about:blank + + final History hist = enclosingWindow.getHistory(); + if (hist.getLength() > 0 && WebClient.URL_ABOUT_BLANK == hist.getUrl(0)) { + isFirstPageInFrameWindow = hist.getLength() <= 2; + } + else { + isFirstPageInFrameWindow = enclosingWindow.getHistory().getLength() < 2; + } } if (isFrameWindow && !isFirstPageInFrameWindow) { Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java 2014-02-08 18:27:10 UTC (rev 9117) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLFrameElement2Test.java 2014-02-09 19:01:11 UTC (rev 9118) @@ -441,7 +441,6 @@ "content\nClick for new frame content with onload", "header -> content -> frameSet -> onloadFrame", "onloadFrame\nNew content loaded..." }) - @NotYetImplemented public void windowLocationReplaceOnload() throws Exception { final String html = "<html><head><title>OnloadTest</title></head>\n" + "<frameset rows='50,*' onLoad=\"top.header.addToFrameOrder('frameSet');\">\n" |