From: <mgu...@us...> - 2013-03-21 11:55:47
|
Revision: 8180 http://sourceforge.net/p/htmlunit/code/8180 Author: mguillem Date: 2013-03-21 11:55:44 +0000 (Thu, 21 Mar 2013) Log Message: ----------- handle weird case where document.write is silently ignored Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlScript.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWrite2Test.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWriteTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlScript.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlScript.java 2013-03-20 15:59:37 UTC (rev 8179) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlScript.java 2013-03-21 11:55:44 UTC (rev 8180) @@ -47,6 +47,7 @@ import com.gargoylesoftware.htmlunit.javascript.host.Event; import com.gargoylesoftware.htmlunit.javascript.host.EventHandler; import com.gargoylesoftware.htmlunit.javascript.host.Window; +import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLDocument; import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLScriptElement; import com.gargoylesoftware.htmlunit.protocol.javascript.JavaScriptURLConnection; import com.gargoylesoftware.htmlunit.xml.XmlPage; @@ -248,22 +249,32 @@ final PostponedAction action = new PostponedAction(getPage()) { @Override public void execute() { - final boolean onReady = hasFeature(JS_SCRIPT_SUPPORTS_ONREADYSTATECHANGE); - if (onReady) { - if (!isDeferred()) { - if (SLASH_SLASH_COLON.equals(getSrcAttribute())) { - setAndExecuteReadyState(READY_STATE_COMPLETE); - executeScriptIfNeeded(); + final HTMLDocument jsDoc = (HTMLDocument) ((Window) getPage().getEnclosingWindow().getScriptObject()) + .getDocument(); + jsDoc.setExecutingDynamicExternalPosponed(getStartLineNumber() == -1 + && getSrcAttribute() != ATTRIBUTE_NOT_DEFINED); + + try { + final boolean onReady = hasFeature(JS_SCRIPT_SUPPORTS_ONREADYSTATECHANGE); + if (onReady) { + if (!isDeferred()) { + if (SLASH_SLASH_COLON.equals(getSrcAttribute())) { + setAndExecuteReadyState(READY_STATE_COMPLETE); + executeScriptIfNeeded(); + } + else { + setAndExecuteReadyState(READY_STATE_LOADING); + executeScriptIfNeeded(); + setAndExecuteReadyState(READY_STATE_LOADED); + } } - else { - setAndExecuteReadyState(READY_STATE_LOADING); - executeScriptIfNeeded(); - setAndExecuteReadyState(READY_STATE_LOADED); - } } + else { + executeScriptIfNeeded(); + } } - else { - executeScriptIfNeeded(); + finally { + jsDoc.setExecutingDynamicExternalPosponed(false); } } }; 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 2013-03-20 15:59:37 UTC (rev 8179) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java 2013-03-21 11:55:44 UTC (rev 8180) @@ -551,7 +551,19 @@ throw Context.reportRuntimeError("Function can't be used detached from document"); } + private boolean executionExternalPostponed_ = false; + /** + * This a hack!!! A cleaner way is welcome. + * Handle a case where document.write is simply ignored. + * See HTMLDocumentWrite2Test.write_fromScriptAddedWithAppendChild_external. + * @param executing indicates if executing or not + */ + public void setExecutingDynamicExternalPosponed(final boolean executing) { + executionExternalPostponed_ = executing; + } + + /** * JavaScript function "write". * * See http://www.whatwg.org/specs/web-apps/current-work/multipage/section-dynamic.html for @@ -560,6 +572,14 @@ * @param content the content to write */ protected void write(final String content) { + // really strange: if called from an external script loaded as postponed action, write is ignored!!! + if (executionExternalPostponed_) { + if (LOG.isDebugEnabled()) { + LOG.debug("skipping write for external posponed: " + content); + } + return; + } + if (LOG.isDebugEnabled()) { LOG.debug("write: " + content); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWrite2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWrite2Test.java 2013-03-20 15:59:37 UTC (rev 8179) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWrite2Test.java 2013-03-21 11:55:44 UTC (rev 8180) @@ -316,4 +316,70 @@ + "</html>"; loadPageWithAlerts2(html); } + + /** + * Regression test for bug 743241. + * @throws Exception if the test fails + */ + @Test + public void write_LoadScript() throws Exception { + final String html + = "<html><head><title>First</title></head><body>\n" + + "<script src='script.js'></script>\n" + + "</form></body></html>"; + + final String script = "document.write(\"<div id='div1'>hello</div>\");\n"; + getMockWebConnection().setDefaultResponse(script, JAVASCRIPT_MIME_TYPE); + + final WebDriver driver = loadPage2(html); + assertEquals("First", driver.getTitle()); + + assertEquals("hello", driver.findElement(By.id("div1")).getText()); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(IE = "exception") + public void write_fromScriptAddedWithAppendChild_inline() throws Exception { + final String html = "<html><head></head><body>\n" + + "<div id='it'><script>\n" + + "try {\n" + + " var s = document.createElement('script');\n" + + " var t = document.createTextNode(\"document.write('in inline script'); document.title = 'done';\");\n" + + " s.appendChild(t);\n" + + " document.body.appendChild(s);\n" + + "} catch (e) { alert('exception'); }\n" + + "</script></div></body></html>"; + final WebDriver driver = loadPageWithAlerts2(html); + + if (getExpectedAlerts().length == 0) { + assertEquals("done", driver.getTitle()); + assertEquals("in inline script", driver.findElement(By.id("it")).getText()); + } + } + + /** + * @throws Exception if an error occurs + */ + @Test + public void write_fromScriptAddedWithAppendChild_external() throws Exception { + final String html = "<html><head></head><body>\n" + + "<div id='it'>here</div><script>\n" + + " var s = document.createElement('script');\n" + + " s.src = 'foo.js'\n" + + " document.body.appendChild(s);\n" + + "</script></body></html>"; + + final String js = "document.write('from external script');\n" + + "document.title = 'done';"; + + getMockWebConnection().setDefaultResponse(js, JAVASCRIPT_MIME_TYPE); + final WebDriver driver = loadPage2(html); + + assertEquals("done", driver.getTitle()); + assertEquals("here", driver.findElement(By.id("it")).getText()); + assertEquals("here", driver.findElement(By.tagName("body")).getText()); + } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWriteTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWriteTest.java 2013-03-20 15:59:37 UTC (rev 8179) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocumentWriteTest.java 2013-03-21 11:55:44 UTC (rev 8180) @@ -15,7 +15,6 @@ package com.gargoylesoftware.htmlunit.javascript.host.html; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; import java.net.URL; import java.util.ArrayList; @@ -27,7 +26,6 @@ import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; import com.gargoylesoftware.htmlunit.CollectingAlertHandler; -import com.gargoylesoftware.htmlunit.ElementNotFoundException; import com.gargoylesoftware.htmlunit.MockWebConnection; import com.gargoylesoftware.htmlunit.SimpleWebTestCase; import com.gargoylesoftware.htmlunit.WebClient; @@ -71,39 +69,6 @@ } /** - * Regression test for bug 743241. - * @throws Exception if the test fails - */ - @Test - public void write_LoadScript() throws Exception { - final WebClient webClient = getWebClient(); - final MockWebConnection webConnection = new MockWebConnection(); - webClient.setWebConnection(webConnection); - - final String html - = "<html><head><title>First</title></head><body>\n" - + "<script src='http://script'></script>\n" - + "</form></body></html>"; - webConnection.setResponse(URL_FIRST, html); - - final String script = "document.write(\"<div id='div1'></div>\");\n"; - webConnection.setResponse(new URL("http://script/"), script, JAVASCRIPT_MIME_TYPE); - - final List<String> collectedAlerts = new ArrayList<String>(); - webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); - - final HtmlPage page = webClient.getPage(URL_FIRST); - assertEquals("First", page.getTitleText()); - - try { - page.getHtmlElementById("div1"); - } - catch (final ElementNotFoundException e) { - fail("Element not written to page as expected"); - } - } - - /** * Regression test for bug 715379. * @throws Exception if the test fails */ |