test_content_iterator_post_order.html (48719B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Test for post-order content iterator</title> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <link rel="stylesheet" href="/tests/SimpleTest/test.css"> 8 <script> 9 var Cc = SpecialPowers.Cc; 10 var Ci = SpecialPowers.Ci; 11 function finish() { 12 // The SimpleTest may require usual elements in the template, but they shouldn't be during test. 13 // So, let's create them at end of the test. 14 document.body.innerHTML = '<div id="display"></div><div id="content"></div><pre id="test"></pre>'; 15 SimpleTest.finish(); 16 } 17 18 function createContentIterator() { 19 return Cc["@mozilla.org/scriptable-content-iterator;1"] 20 .createInstance(Ci.nsIScriptableContentIterator); 21 } 22 23 function getNodeDescription(aNode) { 24 if (aNode === undefined) { 25 return "undefine"; 26 } 27 if (aNode === null) { 28 return "null"; 29 } 30 function getElementDescription(aElement) { 31 if (aElement.tagName === "BR") { 32 if (aElement.previousSibling) { 33 return `<br> element after ${getNodeDescription(aElement.previousSibling)}`; 34 } 35 return `<br> element in ${getElementDescription(aElement.parentElement)}`; 36 } 37 let hasHint = aElement == document.body; 38 let tag = `<${aElement.tagName.toLowerCase()}`; 39 if (aElement.getAttribute("id")) { 40 tag += ` id="${aElement.getAttribute("id")}"`; 41 hasHint = true; 42 } 43 if (aElement.getAttribute("class")) { 44 tag += ` class="${aElement.getAttribute("class")}"`; 45 hasHint = true; 46 } 47 if (aElement.getAttribute("type")) { 48 tag += ` type="${aElement.getAttribute("type")}"`; 49 } 50 if (aElement.getAttribute("name")) { 51 tag += ` name="${aElement.getAttribute("name")}"`; 52 } 53 if (aElement.getAttribute("value")) { 54 tag += ` value="${aElement.getAttribute("value")}"`; 55 hasHint = true; 56 } 57 if (aElement.getAttribute("style")) { 58 tag += ` style="${aElement.getAttribute("style")}"`; 59 hasHint = true; 60 } 61 if (hasHint) { 62 return tag + ">"; 63 } 64 return `${tag}> in ${getElementDescription(aElement.parentElement)}`; 65 } 66 switch (aNode.nodeType) { 67 case aNode.TEXT_NODE: 68 return `text node, "${aNode.wholeText.replace(/\n/g, '\\n')}"`; 69 case aNode.COMMENT_NODE: 70 return `comment node, "${aNode.data.replace(/\n/g, '\\n')}"`; 71 case aNode.ELEMENT_NODE: 72 return getElementDescription(SpecialPowers.unwrap(aNode)); 73 default: 74 return "unknown node"; 75 } 76 } 77 78 SimpleTest.waitForExplicitFinish(); 79 SimpleTest.waitForFocus(function () { 80 let iter = createContentIterator(); 81 82 /** 83 * Basic behavior tests of first(), last(), prev() and next() after initialized with an empty element. 84 */ 85 document.body.innerHTML = "<div></div>"; 86 let description = "Initialized with empty <div> as root node:"; 87 iter.initWithRootNode(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, document.body.firstChild); 88 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 89 `${description} currentNode should be the <div> immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 90 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 91 92 iter.first(); 93 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 94 `${description} currentNode should be the <div> after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 95 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`); 96 97 iter.last(); 98 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 99 `${description} currentNode should be the <div> after calling last() (got: ${getNodeDescription(iter.currentNode)})`); 100 ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`); 101 102 iter.prev(); 103 is(SpecialPowers.unwrap(iter.currentNode), null, 104 `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`); 105 ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected? 106 107 iter.first(); 108 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 109 `${description} currentNode should be the <div> after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`); 110 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`); 111 112 iter.next(); 113 is(SpecialPowers.unwrap(iter.currentNode), null, 114 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 115 ok(iter.isDone, `${description} isDone should be true after calling next()`); 116 117 /** 118 * Basic behavior tests of first(), last(), prev() and next() after initialized with a range which selects empty element. 119 */ 120 let range = document.createRange(); 121 range.selectNode(document.body.firstChild); 122 description = "Initialized with range including only empty <div>:"; 123 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 124 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 125 `${description} currentNode should be the <div> immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 126 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 127 128 iter.first(); 129 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 130 `${description} currentNode should be the <div> after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 131 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`); 132 133 iter.last(); 134 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 135 `${description} currentNode should be the <div> after calling last() (got: ${getNodeDescription(iter.currentNode)})`); 136 ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`); 137 138 iter.prev(); 139 is(SpecialPowers.unwrap(iter.currentNode), null, 140 `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`); 141 ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected? 142 143 iter.first(); 144 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 145 `${description} currentNode should be the <div> after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`); 146 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`); 147 148 iter.next(); 149 is(SpecialPowers.unwrap(iter.currentNode), null, 150 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 151 ok(iter.isDone, `${description} isDone should be true after calling next()`); 152 153 /** 154 * Basic behavior tests of first(), last(), prev() and next() after initialized with positions which select empty element. 155 */ 156 range.selectNode(document.body.firstChild); 157 description = "Initialized with positions including only empty <div>:"; 158 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 159 range.startContainer, range.startOffset, 160 range.endContainer, range.endOffset); 161 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 162 `${description} currentNode should be the <div> immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 163 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 164 165 iter.first(); 166 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 167 `${description} currentNode should be the <div> after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 168 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`); 169 170 iter.last(); 171 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 172 `${description} currentNode should be the <div> after calling last() (got: ${getNodeDescription(iter.currentNode)})`); 173 ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`); 174 175 iter.prev(); 176 is(SpecialPowers.unwrap(iter.currentNode), null, 177 `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`); 178 ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected? 179 180 iter.first(); 181 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 182 `${description} currentNode should be the <div> after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`); 183 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`); 184 185 iter.next(); 186 is(SpecialPowers.unwrap(iter.currentNode), null, 187 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 188 ok(iter.isDone, `${description} isDone should be true after calling next()`); 189 190 /** 191 * Tests to initializing with collapsed range in an empty element. 192 */ 193 range = document.createRange(); 194 range.collapse(document.body.firstChild, 0); 195 description = "Initialized with range collapsed in empty <div>:"; 196 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 197 is(SpecialPowers.unwrap(iter.currentNode), null, 198 `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 199 ok(iter.isDone, `${description} isDone should be true immediately after initialization`); 200 201 iter.first(); 202 is(SpecialPowers.unwrap(iter.currentNode), null, 203 `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 204 ok(iter.isDone, `${description} isDone should be true even after calling first()`); 205 206 /** 207 * Tests to initializing with collapsed range in an empty element. 208 */ 209 description = "Initialized with a position in empty <div>:"; 210 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 211 document.body.firstChild, 0, document.body.firstChild, 0); 212 is(SpecialPowers.unwrap(iter.currentNode), null, 213 `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 214 ok(iter.isDone, `${description} isDone should be true immediately after initialization`); 215 216 iter.first(); 217 is(SpecialPowers.unwrap(iter.currentNode), null, 218 `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 219 ok(iter.isDone, `${description} isDone should be true even after calling first()`); 220 221 /** 222 * Basic behavior tests of first(), last(), prev() and next() after initialized with the text element. 223 */ 224 document.body.innerHTML = "<div>some text.</div>"; 225 description = "Initialized with a text node as root node:"; 226 iter.initWithRootNode(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, document.body.firstChild.firstChild); 227 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 228 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 229 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 230 231 iter.first(); 232 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 233 `${description} currentNode should be the text node after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 234 ok(!iter.isDone, `${description} isDone shouldn't be the text node after calling first()`); 235 236 iter.last(); 237 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 238 `${description} currentNode should be the text node after calling last() (got: ${getNodeDescription(iter.currentNode)})`); 239 ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`); 240 241 iter.prev(); 242 is(SpecialPowers.unwrap(iter.currentNode), null, 243 `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`); 244 ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected? 245 246 iter.first(); 247 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 248 `${description} currentNode should be the text node after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`); 249 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`); 250 251 iter.next(); 252 is(SpecialPowers.unwrap(iter.currentNode), null, 253 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 254 ok(iter.isDone, `${description} isDone should be true after calling next()`); 255 256 /** 257 * Basic behavior tests of first(), last(), prev() and next() after initialized with a range which selects the text node. 258 */ 259 range = document.createRange(); 260 range.selectNode(document.body.firstChild.firstChild); 261 description = "Initialized with range including only text node:"; 262 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 263 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 264 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 265 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 266 267 iter.first(); 268 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 269 `${description} currentNode should be the text node after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 270 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`); 271 272 iter.last(); 273 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 274 `${description} currentNode should be the text node after calling last() (got: ${getNodeDescription(iter.currentNode)})`); 275 ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`); 276 277 iter.prev(); 278 is(SpecialPowers.unwrap(iter.currentNode), null, 279 `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`); 280 ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected? 281 282 iter.first(); 283 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 284 `${description} currentNode should be the text node after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`); 285 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`); 286 287 iter.next(); 288 is(SpecialPowers.unwrap(iter.currentNode), null, 289 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 290 ok(iter.isDone, `${description} isDone should be true after calling next()`); 291 292 /** 293 * Basic behavior tests of first() and next() after initialized with positions which select the text node. 294 * XXX In this case, content iterator lists up the parent <div> element. Not sure if this is intentional difference 295 * from initWithRange(). 296 */ 297 range.selectNode(document.body.firstChild); 298 description = "Initialized with positions including only text node:"; 299 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 300 range.startContainer, range.startOffset, 301 range.endContainer, range.endOffset); 302 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 303 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 304 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 305 306 iter.first(); 307 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 308 `${description} currentNode should be the text node after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 309 ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`); 310 311 iter.next(); 312 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 313 `${description} currentNode should be the <div> element after calling next() from first position (got: ${getNodeDescription(iter.currentNode)})`); 314 ok(!iter.isDone, `${description} isDone shouldn't be true after calling next() from first position`); 315 316 iter.next(); 317 is(SpecialPowers.unwrap(iter.currentNode), null, 318 `${description} currentNode should be null after calling next() from second position (got: ${getNodeDescription(iter.currentNode)})`); 319 ok(iter.isDone, `${description} isDone should be true after calling next() from second position`); 320 321 /** 322 * Tests to initializing with collapsed range at start of a text node. 323 */ 324 range = document.createRange(); 325 range.collapse(document.body.firstChild.firstChild, 0); 326 description = "Initialized with range collapsed at start of text node:"; 327 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 328 is(SpecialPowers.unwrap(iter.currentNode), null, 329 `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 330 ok(iter.isDone, `${description} isDone should be true immediately after initialization`); 331 332 iter.first(); 333 is(SpecialPowers.unwrap(iter.currentNode), null, 334 `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 335 ok(iter.isDone, `${description} isDone should be true even after calling first()`); 336 337 /** 338 * Tests to initializing with collapsed range at start of a text node. 339 * XXX In this case, content iterator lists up the text node. Not sure if this is intentional difference 340 * from initWithRange(). 341 */ 342 description = "Initialized with a position at start of text node:"; 343 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 344 document.body.firstChild.firstChild, 0, document.body.firstChild.firstChild, 0); 345 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 346 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 347 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 348 349 iter.next(); 350 is(SpecialPowers.unwrap(iter.currentNode), null, 351 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 352 ok(iter.isDone, `${description} isDone should be true after calling next()`); 353 354 /** 355 * Tests to initializing with collapsed range at end of a text node. 356 */ 357 range = document.createRange(); 358 range.collapse(document.body.firstChild.firstChild, document.body.firstChild.firstChild.length); 359 description = "Initialized with range collapsed at end of text node:"; 360 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 361 is(SpecialPowers.unwrap(iter.currentNode), null, 362 `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 363 ok(iter.isDone, `${description} isDone should be true immediately after initialization`); 364 365 iter.first(); 366 is(SpecialPowers.unwrap(iter.currentNode), null, 367 `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 368 ok(iter.isDone, `${description} isDone should be true even after calling first()`); 369 370 /** 371 * Tests to initializing with collapsed range at end of a text node. 372 * XXX In this case, content iterator lists up the text node. Not sure if this is intentional difference 373 * from initWithRange(). 374 */ 375 description = "Initialized with a position at end of text node:"; 376 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 377 document.body.firstChild.firstChild, document.body.firstChild.firstChild.length, 378 document.body.firstChild.firstChild, document.body.firstChild.firstChild.length); 379 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 380 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 381 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 382 383 iter.next(); 384 is(SpecialPowers.unwrap(iter.currentNode), null, 385 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 386 ok(iter.isDone, `${description} isDone should be true after calling next()`); 387 388 /** 389 * Tests to initializing with collapsed range at middle of a text node. 390 */ 391 range = document.createRange(); 392 range.collapse(document.body.firstChild.firstChild, document.body.firstChild.firstChild.length / 2); 393 description = "Initialized with range collapsed at end of text node:"; 394 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 395 is(SpecialPowers.unwrap(iter.currentNode), null, 396 `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 397 ok(iter.isDone, `${description} isDone should be true immediately after initialization`); 398 399 iter.first(); 400 is(SpecialPowers.unwrap(iter.currentNode), null, 401 `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`); 402 ok(iter.isDone, `${description} isDone should be true even after calling first()`); 403 404 /** 405 * Tests to initializing with collapsed range at middle of a text node. 406 * XXX In this case, content iterator lists up the text node. Not sure if this is intentional difference 407 * from initWithRange(). 408 */ 409 description = "Initialized with a position at end of text node:"; 410 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 411 document.body.firstChild.firstChild, document.body.firstChild.firstChild.length / 2, 412 document.body.firstChild.firstChild, document.body.firstChild.firstChild.length / 2); 413 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 414 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 415 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 416 417 iter.next(); 418 is(SpecialPowers.unwrap(iter.currentNode), null, 419 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 420 ok(iter.isDone, `${description} isDone should be true after calling next()`); 421 422 /** 423 * Tests to initializing with a range selecting all text in a text node. 424 */ 425 range = document.createRange(); 426 range.setStart(document.body.firstChild.firstChild, 0); 427 range.setEnd(document.body.firstChild.firstChild, document.body.firstChild.firstChild.length); 428 description = "Initialized with range selecting all text in text node:"; 429 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 430 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 431 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 432 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 433 434 iter.next(); 435 is(SpecialPowers.unwrap(iter.currentNode), null, 436 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 437 ok(iter.isDone, `${description} isDone should be true after calling next()`); 438 439 /** 440 * Tests to initializing with positions selecting all text in a text node. 441 */ 442 description = "Initialized with positions selecting all text in text node:"; 443 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 444 document.body.firstChild.firstChild, 0, 445 document.body.firstChild.firstChild, document.body.firstChild.firstChild.length); 446 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild, 447 `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`); 448 ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`); 449 450 iter.next(); 451 is(SpecialPowers.unwrap(iter.currentNode), null, 452 `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`); 453 ok(iter.isDone, `${description} isDone should be true after calling next()`); 454 455 /** 456 * Basic tests with complicated tree. 457 */ 458 function check(aIter, aExpectedResult, aDescription) { 459 if (aExpectedResult.length) { 460 is(SpecialPowers.unwrap(aIter.currentNode), aExpectedResult[0], 461 `${aDescription}: currentNode should be the text node immediately after initialization (got: ${getNodeDescription(aIter.currentNode)}, expected: ${getNodeDescription(aExpectedResult[0])})`); 462 ok(!aIter.isDone, `${aDescription}: isDone shouldn't be true immediately after initialization`); 463 464 aIter.first(); 465 is(SpecialPowers.unwrap(aIter.currentNode), aExpectedResult[0], 466 `${aDescription}: currentNode should be the text node after calling first() (got: ${getNodeDescription(aIter.currentNode)}, expected: ${getNodeDescription(aExpectedResult[0])})`); 467 ok(!aIter.isDone, `${aDescription}: isDone shouldn't be true after calling first()`); 468 469 for (let expected of aExpectedResult) { 470 is(SpecialPowers.unwrap(aIter.currentNode), expected, 471 `${aDescription}: currentNode should be the node (got: ${getNodeDescription(aIter.currentNode)}, expected: ${getNodeDescription(expected)})`); 472 ok(!aIter.isDone, `${aDescription}: isDone shouldn't be true when ${getNodeDescription(expected)} is expected`); 473 aIter.next(); 474 } 475 476 is(SpecialPowers.unwrap(aIter.currentNode), null, 477 `${aDescription}: currentNode should be null after calling next() finally (got: ${getNodeDescription(aIter.currentNode)}`); 478 ok(aIter.isDone, `${aDescription}: isDone should be true after calling next() finally`); 479 } else { 480 is(SpecialPowers.unwrap(aIter.currentNode), null, 481 `${aDescription}: currentNode should be null immediately after initialization (got: ${getNodeDescription(aIter.currentNode)})`); 482 ok(aIter.isDone, `${aDescription}: isDone should be true immediately after initialization`); 483 484 aIter.first(); 485 is(SpecialPowers.unwrap(aIter.currentNode), null, 486 `${aDescription}: currentNode should be null after calling first() (got: ${getNodeDescription(aIter.currentNode)})`); 487 ok(aIter.isDone, `${aDescription}: isDone should be true after calling first()`); 488 } 489 } 490 491 document.body.innerHTML = "<p>" + 492 "Here is <b>bold</b> and <i><u>underlined and </u>italic </i><span>or no style text.</span><br>" + 493 "</p>" + 494 "<p>" + 495 "Here is an <input> element: <input type=\"text\" value=\"default value\"><br>\n" + 496 "and a <textarea> element: <textarea>text area's text node</textarea><br><br>\n" + 497 "<!-- and here is comment node -->" + 498 "</p>"; 499 500 let expectedResult = 501 [document.body.firstChild.firstChild, // the first text node 502 document.body.firstChild.firstChild.nextSibling.firstChild, // text in <b> 503 document.body.firstChild.firstChild.nextSibling, // <b> 504 document.body.firstChild.firstChild.nextSibling.nextSibling, // text next to <b> 505 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild.firstChild, // text in <u> 506 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild, // <u> 507 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild.nextSibling, // text next to <u> 508 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling, // <i> 509 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.firstChild, // text in <span> 510 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.nextSibling, // <span> 511 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // <br> next to <span> 512 document.body.firstChild, // first <p> 513 document.body.firstChild.nextSibling.firstChild, // the first text node in second <p> 514 document.body.firstChild.nextSibling.firstChild.nextSibling, // <input> 515 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling, // <br> next to <input> 516 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling, // text next to <input> 517 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.firstChild, // text in <textarea> 518 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling, // <textarea> 519 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // <br> next to <textarea> 520 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // <br> next to <br> 521 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // text next to <br> 522 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // comment 523 document.body.firstChild.nextSibling, // second <p> 524 document.body]; // <body> 525 526 iter.initWithRootNode(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, document.body); 527 check(iter, expectedResult, "Initialized with the <body> as root element:"); 528 529 /** 530 * Selects the <body> with a range. 531 */ 532 range = document.createRange(); 533 range.selectNode(document.body); 534 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 535 check(iter, expectedResult, "Initialized with range selecting the <body>"); 536 537 /** 538 * Selects the <body> with positions. 539 */ 540 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 541 range.startContainer, range.startOffset, range.endContainer, range.endOffset); 542 check(iter, expectedResult, "Initialized with positions selecting the <body>"); 543 544 /** 545 * Selects all children in the <body> with a range. 546 */ 547 expectedResult.pop(); // <body> shouldn't be listed up. 548 range = document.createRange(); 549 range.selectNodeContents(document.body); 550 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 551 check(iter, expectedResult, "Initialized with range selecting all children in the <body>"); 552 553 /** 554 * Selects all children in the <body> with positions. 555 */ 556 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 557 range.startContainer, range.startOffset, range.endContainer, range.endOffset); 558 check(iter, expectedResult, "Initialized with positions selecting all children in the <body>"); 559 560 /** 561 * range/positions around elements. 562 */ 563 document.body.innerHTML = "abc<b>def</b><i>ghi</i>jkl"; 564 range = document.createRange(); 565 566 range.setStart(document.body.firstChild, 0); 567 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 568 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 569 check(iter, 570 [document.body.firstChild, // text before <b> 571 document.body.firstChild.nextSibling.firstChild], // text in <b> 572 "Initialized with range selecting '[abc<b>de]f'"); 573 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 574 range.startContainer, range.startOffset, 575 range.endContainer, range.endOffset); 576 check(iter, 577 [document.body.firstChild, // text before <b> 578 document.body.firstChild.nextSibling.firstChild], // text in <b> 579 "Initialized with positions selecting '[abc<b>de]f'"); 580 581 range.setStart(document.body.firstChild, 2); 582 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 583 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 584 check(iter, 585 [document.body.firstChild, // text before <b> 586 document.body.firstChild.nextSibling.firstChild], // text in <b> 587 "Initialized with range selecting 'ab[c<b>de]f'"); 588 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 589 range.startContainer, range.startOffset, 590 range.endContainer, range.endOffset); 591 check(iter, 592 [document.body.firstChild, // text before <b> 593 document.body.firstChild.nextSibling.firstChild], // text in <b> 594 "Initialized with positions selecting 'ab[c<b>de]f'"); 595 596 range.setStart(document.body.firstChild, 3); 597 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 598 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 599 check(iter, 600 [document.body.firstChild, // text before <b> 601 document.body.firstChild.nextSibling.firstChild], // text in <b> 602 "Initialized with range selecting 'abc[<b>de]f'"); 603 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 604 range.startContainer, range.startOffset, 605 range.endContainer, range.endOffset); 606 check(iter, 607 [document.body.firstChild, // text before <b> 608 document.body.firstChild.nextSibling.firstChild], // text in <b> 609 "Initialized with positions selecting 'abc[<b>de]f'"); 610 611 range.setStart(document.body, 1); 612 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 613 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 614 check(iter, 615 [document.body.firstChild.nextSibling.firstChild], // text in <b> 616 "Initialized with range selecting 'abc{<b>de]f'"); 617 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 618 range.startContainer, range.startOffset, 619 range.endContainer, range.endOffset); 620 check(iter, 621 [document.body.firstChild.nextSibling.firstChild], // text in <b> 622 "Initialized with positions selecting 'abc{<b>de]f'"); 623 624 range.setStart(document.body.firstChild.nextSibling, 0); 625 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 626 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 627 check(iter, 628 [document.body.firstChild.nextSibling.firstChild], // text in <b> 629 "Initialized with range selecting '<b>{de]f'"); 630 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 631 range.startContainer, range.startOffset, 632 range.endContainer, range.endOffset); 633 check(iter, 634 [document.body.firstChild.nextSibling.firstChild], // text in <b> 635 "Initialized with positions selecting '<b>{de]f'"); 636 637 range.setStart(document.body.firstChild.nextSibling, 0); 638 range.setEnd(document.body.firstChild.nextSibling.firstChild, 3); 639 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 640 check(iter, 641 [document.body.firstChild.nextSibling.firstChild], // text in <b> 642 "Initialized with range selecting '<b>{def]</b>'"); 643 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 644 range.startContainer, range.startOffset, 645 range.endContainer, range.endOffset); 646 check(iter, 647 [document.body.firstChild.nextSibling.firstChild], // text in <b> 648 "Initialized with positions selecting '<b>{def]</b>'"); 649 650 range.setStart(document.body.firstChild.nextSibling, 0); 651 range.setEnd(document.body.firstChild.nextSibling, 1); 652 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 653 check(iter, 654 [document.body.firstChild.nextSibling.firstChild], // text in <b> 655 "Initialized with range selecting '<b>{def}</b>'"); 656 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 657 range.startContainer, range.startOffset, 658 range.endContainer, range.endOffset); 659 check(iter, 660 [document.body.firstChild.nextSibling.firstChild], // text in <b> 661 "Initialized with positions selecting '<b>{def}</b>'"); 662 663 range.setStart(document.body.firstChild.nextSibling, 0); 664 range.setEnd(document.body, 2); 665 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 666 check(iter, 667 [document.body.firstChild.nextSibling.firstChild, // text in <b> 668 document.body.firstChild.nextSibling], // <b> 669 "Initialized with range selecting '<b>{def</b>}<i>ghi'"); 670 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 671 range.startContainer, range.startOffset, 672 range.endContainer, range.endOffset); 673 check(iter, 674 [document.body.firstChild.nextSibling.firstChild, // text in <b> 675 document.body.firstChild.nextSibling], // <b> 676 "Initialized with positions selecting '<b>{def</b>}<i>ghi'"); 677 678 range.setStart(document.body.firstChild.nextSibling.firstChild, 3); 679 range.setEnd(document.body, 2); 680 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 681 check(iter, 682 [document.body.firstChild.nextSibling.firstChild, // text in <b> 683 document.body.firstChild.nextSibling], // <b> 684 "Initialized with range selecting '<b>def[</b>}<i>ghi'"); 685 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 686 range.startContainer, range.startOffset, 687 range.endContainer, range.endOffset); 688 check(iter, 689 [document.body.firstChild.nextSibling.firstChild, // text in <b> 690 document.body.firstChild.nextSibling], // <b> 691 "Initialized with positions selecting '<b>def[</b>}<i>ghi'"); 692 693 range.setStart(document.body.firstChild.nextSibling, 1); 694 range.setEnd(document.body, 2); 695 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 696 check(iter, 697 [document.body.firstChild.nextSibling], // <b> 698 "Initialized with range selecting '<b>def{</b>}<i>ghi'"); 699 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 700 range.startContainer, range.startOffset, 701 range.endContainer, range.endOffset); 702 check(iter, 703 [document.body.firstChild.nextSibling], // <b> 704 "Initialized with positions selecting '<b>def{</b>}<i>ghi'"); 705 706 range.setStart(document.body.firstChild.nextSibling, 1); 707 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 708 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 709 check(iter, 710 [document.body.firstChild.nextSibling], // <b> 711 "Initialized with range selecting '<b>def{</b><i>}ghi'"); 712 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 713 range.startContainer, range.startOffset, 714 range.endContainer, range.endOffset); 715 check(iter, 716 [document.body.firstChild.nextSibling], // <b> 717 "Initialized with positions selecting '<b>def{</b><i>}ghi'"); 718 719 range.setStart(document.body.firstChild.nextSibling, 1); 720 range.setEnd(document.body.firstChild.nextSibling.nextSibling.firstChild, 0); 721 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 722 check(iter, 723 [document.body.firstChild.nextSibling, // <b> 724 document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i> 725 "Initialized with range selecting '<b>def{</b><i>]ghi'"); 726 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 727 range.startContainer, range.startOffset, 728 range.endContainer, range.endOffset); 729 check(iter, 730 [document.body.firstChild.nextSibling, // <b> 731 document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i> 732 "Initialized with positions selecting '<b>def{</b><i>]ghi'"); 733 734 range.setStart(document.body.firstChild.nextSibling.nextSibling, 0); 735 range.setEnd(document.body, 3); 736 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 737 check(iter, 738 [document.body.firstChild.nextSibling.nextSibling.firstChild, // text in <i> 739 document.body.firstChild.nextSibling.nextSibling], // <i> 740 "Initialized with range selecting '<i>{ghi</i>}jkl'"); 741 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 742 range.startContainer, range.startOffset, 743 range.endContainer, range.endOffset); 744 check(iter, 745 [document.body.firstChild.nextSibling.nextSibling.firstChild, // text in <i> 746 document.body.firstChild.nextSibling.nextSibling], // <i> 747 "Initialized with positions selecting '<i>{ghi</i>}jkl'"); 748 749 range.setStart(document.body.firstChild.nextSibling.nextSibling.firstChild, 3); 750 range.setEnd(document.body, 3); 751 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 752 check(iter, 753 [document.body.firstChild.nextSibling.nextSibling.firstChild, // text in <i> 754 document.body.firstChild.nextSibling.nextSibling], // <i> 755 "Initialized with range selecting '<i>ghi[</i>}jkl'"); 756 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 757 range.startContainer, range.startOffset, 758 range.endContainer, range.endOffset); 759 check(iter, 760 [document.body.firstChild.nextSibling.nextSibling.firstChild, // text in <i> 761 document.body.firstChild.nextSibling.nextSibling], // <i> 762 "Initialized with positions selecting '<i>ghi[</i>}jkl'"); 763 764 range.setStart(document.body.firstChild.nextSibling.nextSibling, 1); 765 range.setEnd(document.body, 3); 766 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 767 check(iter, 768 [document.body.firstChild.nextSibling.nextSibling], // <i> 769 "Initialized with range selecting '<i>ghi{</i>}jkl'"); 770 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 771 range.startContainer, range.startOffset, 772 range.endContainer, range.endOffset); 773 check(iter, 774 [document.body.firstChild.nextSibling.nextSibling], // <i> 775 "Initialized with positions selecting '<i>ghi{</i>}jkl'"); 776 777 range.setStart(document.body.firstChild.nextSibling.nextSibling, 1); 778 range.setEnd(document.body.firstChild.nextSibling.nextSibling.nextSibling, 0); 779 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 780 check(iter, 781 [document.body.firstChild.nextSibling.nextSibling, // <i> 782 document.body.firstChild.nextSibling.nextSibling.nextSibling], // text after <i> 783 "Initialized with range selecting '<i>ghi{</i>]jkl'"); 784 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 785 range.startContainer, range.startOffset, 786 range.endContainer, range.endOffset); 787 check(iter, 788 [document.body.firstChild.nextSibling.nextSibling, // <i> 789 document.body.firstChild.nextSibling.nextSibling.nextSibling], // text after <i> 790 "Initialized with positions selecting '<i>ghi{</i>]jkl'"); 791 792 /** 793 * range/positions around <br> elements. 794 */ 795 document.body.innerHTML = "abc<br>def"; 796 range = document.createRange(); 797 range.setStart(document.body.firstChild, 3); 798 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 799 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 800 check(iter, 801 [document.body.firstChild, // text before <br> 802 document.body.firstChild.nextSibling, // <br> 803 document.body.firstChild.nextSibling.nextSibling], // text after <br> 804 "Initialized with range selecting 'abc[<br>]def'"); 805 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 806 range.startContainer, range.startOffset, 807 range.endContainer, range.endOffset); 808 check(iter, 809 [document.body.firstChild, // text before <br> 810 document.body.firstChild.nextSibling, // <br> 811 document.body.firstChild.nextSibling.nextSibling], // text after <br> 812 "Initialized with positions selecting 'abc[<br>]def'"); 813 814 range.setStart(document.body, 1); 815 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 816 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 817 check(iter, 818 [document.body.firstChild.nextSibling, // <br> 819 document.body.firstChild.nextSibling.nextSibling], // text after <br> 820 "Initialized with range selecting 'abc{<br>]def'"); 821 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 822 range.startContainer, range.startOffset, 823 range.endContainer, range.endOffset); 824 check(iter, 825 [document.body.firstChild.nextSibling, // <br> 826 document.body.firstChild.nextSibling.nextSibling], // text after <br> 827 "Initialized with positions selecting 'abc{<br>]def'"); 828 829 range.setStart(document.body.firstChild.nextSibling, 0); 830 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 831 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 832 check(iter, 833 [document.body.firstChild.nextSibling, // <br> 834 document.body.firstChild.nextSibling.nextSibling], // text after <br> 835 "Initialized with range selecting 'abc{<br>]def' (starting in <br>)"); 836 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 837 range.startContainer, range.startOffset, 838 range.endContainer, range.endOffset); 839 check(iter, 840 [document.body.firstChild.nextSibling, // <br> 841 document.body.firstChild.nextSibling.nextSibling], // text after <br> 842 "Initialized with positions selecting 'abc{<br>]def' (starting in <br>)"); 843 844 range.setStart(document.body, 1); 845 range.setEnd(document.body, 2); 846 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 847 check(iter, 848 [document.body.firstChild.nextSibling], // <br> 849 "Initialized with range selecting 'abc{<br>}def'"); 850 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 851 range.startContainer, range.startOffset, 852 range.endContainer, range.endOffset); 853 check(iter, 854 [document.body.firstChild.nextSibling], // <br> 855 "Initialized with positions selecting 'abc{<br>}def'"); 856 857 range.setStart(document.body.firstChild, 3); 858 range.setEnd(document.body.firstChild.nextSibling, 0); 859 iter.initWithRange(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, range); 860 check(iter, 861 [document.body.firstChild], // text before <br> 862 "Initialized with range selecting 'abc[}<br>def' (ending in <br>)"); 863 iter.initWithPositions(Ci.nsIScriptableContentIterator.POST_ORDER_ITERATOR, 864 range.startContainer, range.startOffset, 865 range.endContainer, range.endOffset); 866 check(iter, 867 [document.body.firstChild], // text before <br> 868 "Initialized with positions selecting 'abc[}<br>def' (ending in <br>)"); 869 870 finish(); 871 }); 872 </script> 873 </head> 874 <body></body> 875 </html>