| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <title>Range.surroundContents() crash</title> | 4 <title>Range.surroundContents() crash</title> |
| 5 <script src="../../../resources/js-test.js"></script> | 5 <script src="../../../resources/js-test.js"></script> |
| 6 </head> | 6 </head> |
| 7 <body> | 7 <body> |
| 8 <script> | 8 <script> |
| 9 description('Range::didSplitTextNode() should not yield an invalid Range object
nor cause a crash inside surroundContents().'); | 9 description('DOM mutation events should not be dispatched during DOM mutations i
n surroundContents().'); |
| 10 | 10 |
| 11 window.jsTestIsAsync = true; | 11 window.jsTestIsAsync = true; |
| 12 | 12 |
| 13 var range; | 13 var range; |
| 14 var textContainer; | 14 var textContainer; |
| 15 var textToBeSplit; | 15 var textToBeSplit; |
| 16 var newTextNode; | 16 var newTextNode; |
| 17 | 17 |
| 18 function run() | 18 function run() |
| 19 { | 19 { |
| 20 textContainer = document.createElement('div'); | 20 textContainer = document.createElement('div'); |
| 21 textToBeSplit = document.createTextNode('SPLITME'); | 21 textToBeSplit = document.createTextNode('SPLITME'); |
| 22 textContainer.appendChild(textToBeSplit); | 22 textContainer.appendChild(textToBeSplit); |
| 23 document.body.appendChild(textContainer); | 23 document.body.appendChild(textContainer); |
| 24 | 24 |
| 25 var surroundParent = document.createElement('div'); | 25 var surroundParent = document.createElement('div'); |
| 26 var textToBeRemoved = document.createTextNode('I will be removed.'); | 26 var textToBeRemoved = document.createTextNode('I will be removed.'); |
| 27 surroundParent.appendChild(textToBeRemoved); | 27 surroundParent.appendChild(textToBeRemoved); |
| 28 document.body.appendChild(surroundParent); | 28 document.body.appendChild(surroundParent); |
| 29 | 29 |
| 30 // Range.surroundContents(newParent) removes newParent's children during its
preprocess phase, thus | 30 // Range.surroundContents(newParent) removes newParent's children during its |
| 31 // the following event handler is called in the middle of surroundContents()
method. | 31 // preprocess phase, however the following event handler is called after |
| 32 // finishing all DOM mutation in surroundContents() method. |
| 32 textToBeRemoved.addEventListener('DOMNodeRemoved', function (event) { | 33 textToBeRemoved.addEventListener('DOMNodeRemoved', function (event) { |
| 33 shouldEvaluateTo('textContainer.childNodes.length', 1); | 34 // |surroundParent| is moved into |textContainer|, and is selected. |
| 34 shouldBeTrue('range.startContainer === textToBeSplit'); | 35 shouldEvaluateTo('textContainer.childNodes.length', 2); |
| 35 shouldEvaluateTo('range.startOffset', textToBeSplit.length); | 36 shouldBeTrue('range.startContainer === textContainer'); |
| 37 shouldEvaluateTo('range.startOffset', 1); |
| 36 shouldBeTrue('range.endContainer === textContainer'); | 38 shouldBeTrue('range.endContainer === textContainer'); |
| 37 shouldEvaluateTo('range.endOffset', 1); | 39 shouldEvaluateTo('range.endOffset', 2); |
| 38 | |
| 39 // A bug in Range::didSplitTextNode() yielded an invalid Range object (m
_start is located *after* m_end). | |
| 40 // This leads to a crash if this happens within surroundContents(). | |
| 41 textToBeSplit.splitText(textToBeSplit.length - 1); | |
| 42 newTextNode = textToBeSplit.nextSibling; | |
| 43 | |
| 44 // To reproduce a crash, there must be something in between split text n
odes. | |
| 45 textContainer.insertBefore(document.createElement('span'), newTextNode); | |
| 46 | |
| 47 shouldEvaluateTo('textContainer.childNodes.length', 3); | |
| 48 shouldBeTrue('range.startContainer === newTextNode'); | |
| 49 shouldEvaluateTo('range.startOffset', newTextNode.length); | |
| 50 shouldBeTrue('range.endContainer === textContainer'); | |
| 51 shouldEvaluateTo('range.endOffset', 3); | |
| 52 }); | 40 }); |
| 53 | 41 |
| 54 range = new Range(); | 42 range = new Range(); |
| 55 range.setStart(textToBeSplit, textToBeSplit.length); | 43 range.setStart(textToBeSplit, textToBeSplit.length); |
| 56 range.setEnd(textContainer, 1); | 44 range.setEnd(textContainer, 1); |
| 57 range.surroundContents(surroundParent); | 45 range.surroundContents(surroundParent); |
| 58 | 46 |
| 59 testPassed('Did not crash.'); | 47 testPassed('Did not crash.'); |
| 60 | 48 |
| 61 // Cleanup. | 49 // Cleanup. |
| 62 document.body.removeChild(textContainer); | 50 document.body.removeChild(textContainer); |
| 63 | 51 |
| 64 window.finishJSTest(); | 52 window.finishJSTest(); |
| 65 } | 53 } |
| 66 | 54 |
| 67 window.setTimeout(run, 0); | 55 window.setTimeout(run, 0); |
| 68 </script> | 56 </script> |
| 69 </body> | 57 </body> |
| 70 </html> | 58 </html> |
| OLD | NEW |