From: <rb...@us...> - 2013-12-04 18:41:07
|
Revision: 8815 http://sourceforge.net/p/htmlunit/code/8815 Author: rbri Date: 2013-12-04 18:41:03 +0000 (Wed, 04 Dec 2013) Log Message: ----------- DomCharacterData.deleteData() fixed 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/html/DomCharacterData.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/CharacterDataImplTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2013-12-01 21:00:59 UTC (rev 8814) +++ trunk/htmlunit/src/changes/changes.xml 2013-12-04 18:41:03 UTC (rev 8815) @@ -8,6 +8,11 @@ <body> <release version="2.14" date="???" description="Bugfixes"> + DomCharacterData-deleteData + <action type="fix" dev="rbri" due-to="Frank Danek"> + JavaScript: DomCharacterData.deleteData no longer wipes the string when called with an invalid + offset. Also the error handling is fixed. + </action> <action type="fix" dev="rbri" issue="1245"> Use the same accept headers as browsers do. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2013-12-01 21:00:59 UTC (rev 8814) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2013-12-04 18:41:03 UTC (rev 8815) @@ -850,6 +850,11 @@ @BrowserFeature(@WebBrowser(FF)) JS_DOMIMPLEMENTATION_FEATURE_XPATH_3, + /** Javascript property function delete thows an exception if the + * given count is negative. */ + @BrowserFeature(@WebBrowser(IE)) + JS_DOM_CDATA_DELETE_THROWS_NEGATIVE_COUNT, + /** Don't enumerate functions, see {@link net.sourceforge.htmlunit.corejs.javascript.ScriptableObject#DONTENUM}. */ @BrowserFeature(@WebBrowser(IE)) JS_DONT_ENUM_FUNCTIONS, Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomCharacterData.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomCharacterData.java 2013-12-01 21:00:59 UTC (rev 8814) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomCharacterData.java 2013-12-04 18:41:03 UTC (rev 8815) @@ -26,6 +26,8 @@ * @author <a href="mailto:cs...@dy...">Christian Sell</a> * @author Ahmed Ashour * @author Philip Graf + * @author Ronald Brill + * @author Frank Danek */ public abstract class DomCharacterData extends DomNode implements CharacterData { @@ -94,21 +96,25 @@ /** * Deletes characters from character data. - * @param offset the position of the first character to be deleted - * @param count the number of characters to be deleted + * @param offset the position of the first character to be deleted (can't be + * less than zero) + * @param count the number of characters to be deleted, if less than zero + * leaves the first offset chars */ public void deleteData(final int offset, final int count) { - if (offset < 0 || count < 0) { - throw new IllegalArgumentException("offset: " + offset + " count: " + count); + if (offset < 0) { + throw new IllegalArgumentException("Provided offset: " + offset + "is less than zero."); } - final int tailLength = Math.max(data_.length() - count - offset, 0); - if (tailLength > 0) { - data_ = data_.substring(0, offset) + data_.substring(offset + count, offset + count + tailLength); + final String data = data_.substring(0, offset); + if (count >= 0) { + final int fromLeft = offset + count; + if (fromLeft < data_.length()) { + data_ = data + data_.substring(fromLeft, data_.length()); + return; + } } - else { - data_ = ""; - } + data_ = data; } /** Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/CharacterDataImplTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/CharacterDataImplTest.java 2013-12-01 21:00:59 UTC (rev 8814) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/CharacterDataImplTest.java 2013-12-04 18:41:03 UTC (rev 8815) @@ -129,15 +129,38 @@ * @throws Exception if the test fails */ @Test - @Alerts("Some Text") + @Alerts({ "Some Text", "Some", "Some", "me", "" }) public void characterDataImpl_deleteData() throws Exception { final String html = "<html><head><title>First</title><script>\n" + "function doTest() {\n" + " var div1=document.getElementById('div1');\n" + " var text1=div1.firstChild;\n" - + " text1.deleteData(5, 11);\n" - + " alert(text1.data);\n" + + + " try {\n" + + " text1.deleteData(5, 11);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(4, 5);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(1, 0);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(0, 2);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(0, 2);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + "}\n" + "</script></head><body onload='doTest()'>\n" + "<div id='div1'>Some Not So New Text</div></body></html>"; @@ -147,6 +170,120 @@ } /** + * Regression test for deleteData of a text node. + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = { "", "", "", "" }, + IE = { "", "", "", "exception" }) + public void characterDataImpl_deleteDataEmptyImput() throws Exception { + final String html + = "<html><head><title>First</title><script>\n" + + "function doTest() {\n" + + " var div1=document.getElementById('div1');\n" + + " var text1=div1.firstChild;\n" + + + " try {\n" + + " text1.deleteData(0, 1);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(0, 0);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(0, 1);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(0, -1);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + "}\n" + + "</script></head><body onload='doTest()'>\n" + + "<div id='div1'>-</div></body></html>"; + + final WebDriver driver = loadPageWithAlerts2(html); + assertEquals("First", driver.getTitle()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = { "exception", "exception", "exception", "exception" }, + IE = { "exception", "exception", "abcde", "exception" }) + public void characterDataImpl_deleteDataInvalidStart() throws Exception { + final String html + = "<html><head><title>First</title><script>\n" + + "function doTest() {\n" + + " var div1=document.getElementById('div1');\n" + + " var text1=div1.firstChild;\n" + + " try {\n" + + " text1.deleteData(-1, 4);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(20, 4);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(20, 0);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(20, -18);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + "}\n" + + "</script></head><body onload='doTest()'>\n" + + "<div id='div1'>abcde</div></body></html>"; + + final WebDriver driver = loadPageWithAlerts2(html); + assertEquals("First", driver.getTitle()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = { "Some Not So New Te", "Some ", "So" }, + IE = { "exception", "exception", "exception" }) + public void characterDataImpl_deleteDataNegativeCount() throws Exception { + final String html + = "<html><head><title>First</title><script>\n" + + "function doTest() {\n" + + " var div1=document.getElementById('div1');\n" + + " var text1=div1.firstChild;\n" + + " try {\n" + + " text1.deleteData(18, -15);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(5, -4);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + + " try {\n" + + " text1.deleteData(2, -4);\n" + + " alert(text1.data);\n" + + " } catch (e) { alert('exception') }\n" + + "}\n" + + "</script></head><body onload='doTest()'>\n" + + "<div id='div1'>Some Not So New Text</div></body></html>"; + + final WebDriver driver = loadPageWithAlerts2(html); + assertEquals("First", driver.getTitle()); + } + + /** * Regression test for insertData of a text node. * @throws Exception if the test fails */ |