Closed Bug 1366 Opened 26 years ago Closed 26 years ago

valid removeChild crashes

Categories

(Core :: DOM: Core & HTML, defect, P1)

x86
Windows NT
defect

Tracking

()

VERIFIED FIXED

People

(Reporter: buster, Assigned: joki)

References

()

Details

the problem seems to be that the remove is getting dispatched twice. It only seems to happen when removing the last child in a container. To see the crash, click on the "delete RG" button. There is a single row group, and it is removed twice. You can verify this by setting a breakpoint in nsGenericHTMLContainerElement::RemoveChild ==================== Test Case ================== <HTML> <HEAD> <SCRIPT> function insertCaption() { var table = document.getElementsByTagName("TABLE")[0]; var caption = document.createElement("CAPTION", null); var text = document.createTextNode("here is the new caption text\n"); caption.appendChild(text); table.appendChild(caption); } function deleteCaption() { var table = document.getElementsByTagName("TABLE")[0]; var caption = document.getElementsByTagName("CAPTION")[0]; table.removeChild(caption); } function changeCaptionStyle() { var caption = document.getElementsByTagName("CAPTION")[0]; caption.align="bottom"; dump("SCRIPT: changed caption align to bottom\n"); } function changeTableStyle() { var table = document.getElementsByTagName("TABLE")[0]; table.width="600"; dump("SCRIPT: changed table width to 600\n"); } function insertColGroup() { var table = document.getElementsByTagName("TABLE")[0]; var refColGroup = document.getElementsByTagName("COLGROUP")[0]; var colGroup = document.createElement("COLGROUP", null); colGroup.width=100; colGroup.span=1; table.insertBefore(colGroup, refColGroup); dump("SCRIPT: inserted COLGROUP with span=1 width=200 as first colgroup in table\n"); } function appendColGroup() { var table = document.getElementsByTagName("TABLE")[0]; var colGroup = document.createElement("COLGROUP", null); colGroup.width=300; colGroup.span=1; table.appendChild(colGroup); dump("SCRIPT: appended COLGROUP with span=1 width=300\n"); } function deleteColGroup() { var table = document.getElementsByTagName("TABLE")[0]; var colGroup = document.getElementsByTagName("COLGROUP")[0]; table.removeChild(colGroup); dump("SCRIPT: deleted first COLGROUP\n"); } function changeColGroupStyle() { var colGroup = document.getElementsByTagName("COLGROUP")[0]; colGroup.width="200"; dump("SCRIPT: changed default width for first COLGROUP to 200\n"); } function insertCol() { var table = document.getElementsByTagName("TABLE")[0]; var refCol = table.getElementsByTagName("COL")[0]; var col = document.createElement("COL", null); col.width=200; col.span=1; table.insertBefore(col, refCol); dump("SCRIPT: inserted COL with span=1 width=200 as first col in first col group\n"); } function appendCol() { var table = document.getElementsByTagName("TABLE")[0]; var col = document.createElement("COL", null); table.appendChild(col); dump("SCRIPT: appended COL with span=1 width=300\n"); } function deleteCol() { var table = document.getElementsByTagName("TABLE")[0]; var col = document.getElementsByTagName("COL")[0]; table.removeChild(col); dump("SCRIPT: deleted first COL in first COLGROUP\n"); } function changeColStyle() { var col = document.getElementsByTagName("COL")[0]; col.width="200"; dump("SCRIPT: changed default width for first COL to 200\n"); } function insertRowGroup() { var table = document.getElementsByTagName("TABLE")[0]; var refRowGroup = document.getElementsByTagName("TBODY")[0]; var rowGroup = document.createElement("TBODY", null); table.insertBefore(rowGroup, refRowGroup); dump("SCRIPT: inserted empty ROWGROUP as first rowgroup in table\n"); } function appendRowGroup() { var table = document.getElementsByTagName("TABLE")[0]; var rowGroup = document.createElement("TBODY", null); table.appendChild(rowGroup); dump("SCRIPT: appended empty ROWGROUP\n"); } function appendRowGroupWithContent() { dump("\nSCRIPT: starting appendRowGroupWithContent\n"); var table = document.getElementsByTagName("TABLE")[0]; var rowGroup = document.createElement("TBODY", null); var row = document.createElement("TR", null); var cell = document.createElement("TD", null); var text = document.createTextNode("here is content in the cell from the script appendRowGroupWithContent\n"); cell.appendChild(text); row.appendChild(cell); rowGroup.appendChild(row); table.appendChild(rowGroup); dump("SCRIPT: appended ROWGROUP with 1 row and 1 cell\n"); } function deleteRowGroup() { var table = document.getElementsByTagName("TABLE")[0]; var rowGroup = document.getElementsByTagName("TBODY")[0]; table.removeChild(rowGroup); dump("SCRIPT: deleted first ROWGROUP\n"); } function changeRowGroupStyle() { var rowGroup = document.getElementsByTagName("TBODY")[0]; rowGroup.align="right"; dump("SCRIPT: changed default align for first ROWGROUP to right\n"); } function insertRow() { var rg = document.getElementsByTagName("TBODY")[0]; var refRow = document.getElementsByTagName("TR")[0]; var row = document.createElement("TR", null); rg.insertBefore(row, refRow); dump("SCRIPT: inserted empty ROW as first row in first rowgroup in table\n"); } function appendRow() { var rg = document.getElementsByTagName("TBODY")[0]; var row = document.createElement("TR", null); rg.appendChild(row); dump("SCRIPT: appended empty ROW in first ROWGROUP\n"); } function appendRowWithContent() { dump("\nSCRIPT: starting appendRowWithContent\n"); var rg = document.getElementsByTagName("TBODY")[0]; var row = document.createElement("TR", null); var cell = document.createElement("TD", null); var text = document.createTextNode("x\n"); cell.appendChild(text); row.appendChild(cell); rg.appendChild(row); dump("SCRIPT: appended ROW with 1 cell in first ROWGROUP\n"); } function deleteRow() { var rg = document.getElementsByTagName("TBODY")[0]; var row = document.getElementsByTagName("TR")[0]; rg.removeChild(row); dump("SCRIPT: deleted first ROW in first ROWGROUP\n"); } function changeRowStyle() { var row = document.getElementsByTagName("TR")[0]; row.vAlign="top"; dump("SCRIPT: changed default align for first ROW to right\n"); } function insertCell() { var row = document.getElementsByTagName("TR")[0]; var refCell = document.getElementsByTagName("TD")[0]; var cell = document.createElement("TD", null); var text = document.createTextNode("inserted Cell"); cell.colSpan=2; cell.appendChild(text); row.insertBefore(cell, refCell); dump("SCRIPT: inserted CELL as first cell in first row\n"); } function appendCell() { var row = document.getElementsByTagName("TR")[0]; var cell = document.createElement("TD", null); var text = document.createTextNode("appended Cell"); cell.appendChild(text); row.appendChild(cell); dump("SCRIPT: appended CELL in first ROW\n"); } function deleteCell() { var row = document.getElementsByTagName("TR")[0]; var cell = document.getElementsByTagName("TD")[0]; row.removeChild(cell); dump("SCRIPT: deleted first CELL in first ROW\n"); } function changeCellStyle() { var cell = document.getElementsByTagName("TD")[0]; cell.width=400; dump("SCRIPT: changed width for first CELL to 400\n"); } function AddALot() { dump("\nSCRIPT: starting AddALot\n"); var table = document.getElementsByTagName("TABLE")[0]; var rowGroup = document.createElement("TBODY", null); var row = document.createElement("TR", null); var row1 = document.createElement("TR", null); var cell1 = document.createElement("TD", null); var cell2 = document.createElement("TD", null); var cell3 = document.createElement("TD", null); var cell4 = document.createElement("TD", null); var text1 = document.createTextNode("cell1\n"); var text2 = document.createTextNode("cell2\n"); var text3 = document.createTextNode("cell3 has the most content, and will be the tallest cell in the row\n"); var text4 = document.createTextNode("cell4\n"); cell1.appendChild(text1); cell2.appendChild(text2); cell3.appendChild(text3); cell4.appendChild(text4); row.appendChild(cell3); row.appendChild(cell4); row.insertBefore(cell2, cell3); row.insertBefore(cell1, cell2); row1.appendChild(cell2); row1.appendChild(cell1); row1.insertBefore(cell3, cell2); row1.insertBefore(cell4, cell3); rowGroup.appendChild(row); rowGroup.appendChild(row); rowGroup.appendChild(row1); rowGroup.appendChild(row1); table.appendChild(rowGroup); dump("SCRIPT: finished adding\n"); } </SCRIPT> </HEAD> <BODY> delete removes the first object of [type]. <table width=150 border> <tbody> <tr> <td>cell content</td> </tr> </tbody> </table> <p> <form> <INPUT TYPE="button" NAME="Ins Caption" VALUE="InsertCaption" onClick="insertCaption()" width=100> <INPUT TYPE="button" NAME="Del Caption" VALUE="DeleteCaption" onClick="deleteCaption()" width=100> <br> <INPUT TYPE="button" NAME="Ins ColGroup" VALUE="InsertCG" onClick="insertColGroup()" width=100> <INPUT TYPE="button" NAME="App ColGroup" VALUE="AppendCG" onClick="appendColGroup()" width=100> <INPUT TYPE="button" NAME="Del ColGroup" VALUE="DeleteCG" onClick="deleteColGroup()" width=100> <br> <INPUT TYPE="button" NAME="Ins Col" VALUE="InsertCol" onClick="insertCol()" width=100> <INPUT TYPE="button" NAME="App Col" VALUE="AppendCol" onClick="appendCol()" width=100> <INPUT TYPE="button" NAME="Del Col" VALUE="DeleteCol" onClick="deleteCol()" width=100> <br> <INPUT TYPE="button" NAME="Ins RowGroup" VALUE="InsertRG" onClick="insertRowGroup()" width=100> <INPUT TYPE="button" NAME="App RowGroup" VALUE="AppendRG" onClick="appendRowGroup()" width=100> <INPUT TYPE="button" NAME="Del RowGroup" VALUE="DeleteRG" onClick="deleteRowGroup()" width=100> <INPUT TYPE="button" NAME="App RowGroup with content" VALUE="AppendRG with content" onClick="appendRowGroupWithContent()" width=100> <br> <INPUT TYPE="button" NAME="Ins Row" VALUE="InsertRow" onClick="insertRow()" width=100> <INPUT TYPE="button" NAME="App Row" VALUE="AppendRow" onClick="appendRow()" width=100> <INPUT TYPE="button" NAME="Del Row" VALUE="DeleteRow" onClick="deleteRow()" width=100> <INPUT TYPE="button" NAME="App Row with content" VALUE="AppendRow with content" onClick="appendRowWithContent()" width=100> <br> <INPUT TYPE="button" NAME="Ins Cell" VALUE="InsertCell" onClick="insertCell()" width=100> <INPUT TYPE="button" NAME="App Cell" VALUE="AppendCell" onClick="appendCell()" width=100> <INPUT TYPE="button" NAME="Del Cell" VALUE="DeleteCell" onClick="deleteCell()" width=100> <br> <INPUT TYPE="button" NAME="Add a lot" VALUE="AddALot" onClick="AddALot()" width=100> <br> <INPUT TYPE="button" NAME="Change Table Style" VALUE="ChangeTableStyle" onClick="changeTableStyle()" width=100> <INPUT TYPE="button" NAME="Change Caption Style" VALUE="ChangeCaptionStyle" onClick="changeCaptionStyle()" width=100> <INPUT TYPE="button" NAME="Change ColGroup Style" VALUE="ChangeColGroupStyle" onClick="changeColGroupStyle()" width=100> <INPUT TYPE="button" NAME="Change Col Style" VALUE="ChangeColStyle" onClick="changeColStyle()" width=100> <INPUT TYPE="button" NAME="Change RowGroup Style" VALUE="ChangeRowGroupStyle" onClick="changeRowGroupStyle()" width=100> <INPUT TYPE="button" NAME="Change Row Style" VALUE="ChangeRowStyle" onClick="changeRowStyle()" width=100> <INPUT TYPE="button" NAME="Change Cell Style" VALUE="ChangeCellStyle" onClick="changeCellStyle()" width=100> </form> </BODY></HTML>
Status: NEW → RESOLVED
Closed: 26 years ago
Resolution: --- → FIXED
Okay. Well I fixed a bug today that dealt with the double firing of the click. But I went back and tried this on the pre-fix code and, though the click fired twice, I didn't crash. So maybe Kipp's removeChild fix caught that and the second click was incidental. Regardless, I'm marking this fixed.
QA Contact: 3829
Steve -- can you verify this? thanks
When I select the DeleteRG button, there is a JavaScript error reported: JavaScript error: deleteRowGroup is not defined URL :(null), LineNo :0 Line text: (null), Error text: (null) used 2/03/99 build on win95 -- it does not crash. Should this be written up as a new bug or is this an acceptable statement?
Sounds like the DOM is more broken then when this bug was submitted. Joki should look into it.
The test works. When you copied the test out of the bug report, some of the lines wrapped incorrectly. Specifically, new lines are statement terminators in JavaScript and some of the strings were split across lines. Fixing this will fix the test. BTW, I caught this by looking at the console window after the document had loaded in. Script processing stopped for the main SCRIPT block after the following error: JavaScript error: unterminated string literal URL :file://C:/TEMP/tabletest.html, LineNo :40 Line text: ' dump("SCRIPT: inserted COLGROUP with span=1 width=200 as first col group in ', Error text: '"SCRIPT: inserted COLGROUP with span=1 width=200 as fir st colgroup in '
Status: RESOLVED → VERIFIED
QA Contact: 3829 → 3849
recopied test, reviewed all line breaks (thanks Vidur), works perfectly, tested on ein95 - 2/8/99 build.
RCS file: /cvsroot/mozilla/testing/mochitest/tests/test_bug1366.html,v done Checking in test_bug1366.html; /cvsroot/mozilla/testing/mochitest/tests/test_bug1366.html,v <-- test_bug1366.html initial revision: 1.1 done
Flags: in-testsuite+
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.