test_content_iterator_pre_order.html (48288B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Test for pre-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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_ORDER_ITERATOR, 300 range.startContainer, range.startOffset, 301 range.endContainer, range.endOffset); 302 is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild, 303 `${description} currentNode should be the <div> element 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, 308 `${description} currentNode should be the <div> element 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.firstChild, 313 `${description} currentNode should be the text node 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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_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.PRE_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, // <body> 502 document.body.firstChild, // first <p> 503 document.body.firstChild.firstChild, // the first text node 504 document.body.firstChild.firstChild.nextSibling, // <b> 505 document.body.firstChild.firstChild.nextSibling.firstChild, // text in <b> 506 document.body.firstChild.firstChild.nextSibling.nextSibling, // text next to <b> 507 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling, // <i> 508 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild, // <u> 509 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild.firstChild, // text in <u> 510 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild.nextSibling, // text next to <u> 511 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.nextSibling, // <span> 512 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.firstChild, // text in <span> 513 document.body.firstChild.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // <br> next to <span> 514 document.body.firstChild.nextSibling, // second <p> 515 document.body.firstChild.nextSibling.firstChild, // the first text node in second <p> 516 document.body.firstChild.nextSibling.firstChild.nextSibling, // <input> 517 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling, // <br> next to <input> 518 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling, // text next to <input> 519 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling, // <textarea> 520 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.firstChild, // text in <textarea> 521 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // <br> next to <textarea> 522 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // <br> next to <br> 523 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, // text next to <br> 524 document.body.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling] // comment 525 526 iter.initWithRootNode(Ci.nsIScriptableContentIterator.PRE_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.PRE_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.PRE_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.shift(); // <body> shouldn't be listed up. 548 range = document.createRange(); 549 range.selectNodeContents(document.body); 550 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_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.PRE_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.PRE_ORDER_ITERATOR, range); 569 check(iter, 570 [document.body.firstChild, // text before <b> 571 document.body.firstChild.nextSibling, // <b> 572 document.body.firstChild.nextSibling.firstChild], // text in <b> 573 "Initialized with range selecting '[abc<b>de]f'"); 574 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 575 range.startContainer, range.startOffset, 576 range.endContainer, range.endOffset); 577 check(iter, 578 [document.body.firstChild, // text before <b> 579 document.body.firstChild.nextSibling, // <b> 580 document.body.firstChild.nextSibling.firstChild], // text in <b> 581 "Initialized with positions selecting '[abc<b>de]f'"); 582 583 range.setStart(document.body.firstChild, 2); 584 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 585 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 586 check(iter, 587 [document.body.firstChild, // text before <b> 588 document.body.firstChild.nextSibling, // <b> 589 document.body.firstChild.nextSibling.firstChild], // text in <b> 590 "Initialized with range selecting 'ab[c<b>de]f'"); 591 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 592 range.startContainer, range.startOffset, 593 range.endContainer, range.endOffset); 594 check(iter, 595 [document.body.firstChild, // text before <b> 596 document.body.firstChild.nextSibling, // <b> 597 document.body.firstChild.nextSibling.firstChild], // text in <b> 598 "Initialized with positions selecting 'ab[c<b>de]f'"); 599 600 range.setStart(document.body.firstChild, 3); 601 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 602 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 603 check(iter, 604 [document.body.firstChild, // text before <b> 605 document.body.firstChild.nextSibling, // <b> 606 document.body.firstChild.nextSibling.firstChild], // text in <b> 607 "Initialized with range selecting 'abc[<b>de]f'"); 608 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 609 range.startContainer, range.startOffset, 610 range.endContainer, range.endOffset); 611 check(iter, 612 [document.body.firstChild, // text before <b> 613 document.body.firstChild.nextSibling, // <b> 614 document.body.firstChild.nextSibling.firstChild], // text in <b> 615 "Initialized with positions selecting 'abc[<b>de]f'"); 616 617 range.setStart(document.body, 1); 618 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 619 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 620 check(iter, 621 [document.body.firstChild.nextSibling, // <b> 622 document.body.firstChild.nextSibling.firstChild], // text in <b> 623 "Initialized with range selecting 'abc{<b>de]f'"); 624 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 625 range.startContainer, range.startOffset, 626 range.endContainer, range.endOffset); 627 check(iter, 628 [document.body.firstChild.nextSibling, // <b> 629 document.body.firstChild.nextSibling.firstChild], // text in <b> 630 "Initialized with positions selecting 'abc{<b>de]f'"); 631 632 range.setStart(document.body.firstChild.nextSibling, 0); 633 range.setEnd(document.body.firstChild.nextSibling.firstChild, 2); 634 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 635 check(iter, 636 [document.body.firstChild.nextSibling.firstChild], // text in <b> 637 "Initialized with range selecting '<b>{de]f'"); 638 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 639 range.startContainer, range.startOffset, 640 range.endContainer, range.endOffset); 641 check(iter, 642 [document.body.firstChild.nextSibling.firstChild], // text in <b> 643 "Initialized with positions selecting '<b>{de]f'"); 644 645 range.setStart(document.body.firstChild.nextSibling, 0); 646 range.setEnd(document.body.firstChild.nextSibling.firstChild, 3); 647 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 648 check(iter, 649 [document.body.firstChild.nextSibling.firstChild], // text in <b> 650 "Initialized with range selecting '<b>{def]</b>'"); 651 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 652 range.startContainer, range.startOffset, 653 range.endContainer, range.endOffset); 654 check(iter, 655 [document.body.firstChild.nextSibling.firstChild], // text in <b> 656 "Initialized with positions selecting '<b>{def]</b>'"); 657 658 range.setStart(document.body.firstChild.nextSibling, 0); 659 range.setEnd(document.body.firstChild.nextSibling, 1); 660 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 661 check(iter, 662 [document.body.firstChild.nextSibling.firstChild], // text in <b> 663 "Initialized with range selecting '<b>{def}</b>'"); 664 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 665 range.startContainer, range.startOffset, 666 range.endContainer, range.endOffset); 667 check(iter, 668 [document.body.firstChild.nextSibling.firstChild], // text in <b> 669 "Initialized with positions selecting '<b>{def}</b>'"); 670 671 range.setStart(document.body.firstChild.nextSibling, 0); 672 range.setEnd(document.body, 2); 673 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 674 check(iter, 675 [document.body.firstChild.nextSibling.firstChild], // text in <b> 676 "Initialized with range selecting '<b>{def</b>}<i>ghi'"); 677 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 678 range.startContainer, range.startOffset, 679 range.endContainer, range.endOffset); 680 check(iter, 681 [document.body.firstChild.nextSibling.firstChild], // text in <b> 682 "Initialized with positions selecting '<b>{def</b>}<i>ghi'"); 683 684 range.setStart(document.body.firstChild.nextSibling.firstChild, 3); 685 range.setEnd(document.body, 2); 686 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 687 check(iter, 688 [document.body.firstChild.nextSibling.firstChild], // text in <b> 689 "Initialized with range selecting '<b>def[</b>}<i>ghi'"); 690 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 691 range.startContainer, range.startOffset, 692 range.endContainer, range.endOffset); 693 check(iter, 694 [document.body.firstChild.nextSibling.firstChild], // text in <b> 695 "Initialized with positions selecting '<b>def[</b>}<i>ghi'"); 696 697 range.setStart(document.body.firstChild.nextSibling, 1); 698 range.setEnd(document.body, 2); 699 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 700 check(iter, [], 701 "Initialized with range selecting '<b>def{</b>}<i>ghi'"); 702 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 703 range.startContainer, range.startOffset, 704 range.endContainer, range.endOffset); 705 check(iter, [], 706 "Initialized with positions selecting '<b>def{</b>}<i>ghi'"); 707 708 range.setStart(document.body.firstChild.nextSibling, 1); 709 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 710 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 711 check(iter, 712 [document.body.firstChild.nextSibling.nextSibling], // <i> 713 "Initialized with range selecting '<b>def{</b><i>}ghi'"); 714 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 715 range.startContainer, range.startOffset, 716 range.endContainer, range.endOffset); 717 check(iter, 718 [document.body.firstChild.nextSibling.nextSibling], // <i> 719 "Initialized with positions selecting '<b>def{</b><i>}ghi'"); 720 721 range.setStart(document.body.firstChild.nextSibling, 1); 722 range.setEnd(document.body.firstChild.nextSibling.nextSibling.firstChild, 0); 723 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 724 check(iter, 725 [document.body.firstChild.nextSibling.nextSibling, // <i> 726 document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i> 727 "Initialized with range selecting '<b>def{</b><i>]ghi'"); 728 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 729 range.startContainer, range.startOffset, 730 range.endContainer, range.endOffset); 731 check(iter, 732 [document.body.firstChild.nextSibling.nextSibling, // <i> 733 document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i> 734 "Initialized with positions selecting '<b>def{</b><i>]ghi'"); 735 736 range.setStart(document.body.firstChild.nextSibling.nextSibling, 0); 737 range.setEnd(document.body, 3); 738 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 739 check(iter, 740 [document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i> 741 "Initialized with range selecting '<i>{ghi</i>}jkl'"); 742 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 743 range.startContainer, range.startOffset, 744 range.endContainer, range.endOffset); 745 check(iter, 746 [document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <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.PRE_ORDER_ITERATOR, range); 752 check(iter, 753 [document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i> 754 "Initialized with range selecting '<i>ghi[</i>}jkl'"); 755 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 756 range.startContainer, range.startOffset, 757 range.endContainer, range.endOffset); 758 check(iter, 759 [document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i> 760 "Initialized with positions selecting '<i>ghi[</i>}jkl'"); 761 762 range.setStart(document.body.firstChild.nextSibling.nextSibling, 1); 763 range.setEnd(document.body, 3); 764 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 765 check(iter, [], 766 "Initialized with range selecting '<i>ghi{</i>}jkl'"); 767 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 768 range.startContainer, range.startOffset, 769 range.endContainer, range.endOffset); 770 check(iter, [], 771 "Initialized with positions selecting '<i>ghi{</i>}jkl'"); 772 773 range.setStart(document.body.firstChild.nextSibling.nextSibling, 1); 774 range.setEnd(document.body.firstChild.nextSibling.nextSibling.nextSibling, 0); 775 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 776 check(iter, 777 [document.body.firstChild.nextSibling.nextSibling.nextSibling], // text after <i> 778 "Initialized with range selecting '<i>ghi{</i>]jkl'"); 779 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 780 range.startContainer, range.startOffset, 781 range.endContainer, range.endOffset); 782 check(iter, 783 [document.body.firstChild.nextSibling.nextSibling.nextSibling], // text after <i> 784 "Initialized with positions selecting '<i>ghi{</i>]jkl'"); 785 786 /** 787 * range/positions around <br> elements. 788 */ 789 document.body.innerHTML = "abc<br>def"; 790 range = document.createRange(); 791 range.setStart(document.body.firstChild, 3); 792 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 793 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 794 check(iter, 795 [document.body.firstChild, // text before <br> 796 document.body.firstChild.nextSibling, // <br> 797 document.body.firstChild.nextSibling.nextSibling], // text after <br> 798 "Initialized with range selecting 'abc[<br>]def'"); 799 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 800 range.startContainer, range.startOffset, 801 range.endContainer, range.endOffset); 802 check(iter, 803 [document.body.firstChild, // text before <br> 804 document.body.firstChild.nextSibling, // <br> 805 document.body.firstChild.nextSibling.nextSibling], // text after <br> 806 "Initialized with positions selecting 'abc[<br>]def'"); 807 808 range.setStart(document.body, 1); 809 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 810 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 811 check(iter, 812 [document.body.firstChild.nextSibling, // <br> 813 document.body.firstChild.nextSibling.nextSibling], // text after <br> 814 "Initialized with range selecting 'abc{<br>]def'"); 815 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 816 range.startContainer, range.startOffset, 817 range.endContainer, range.endOffset); 818 check(iter, 819 [document.body.firstChild.nextSibling, // <br> 820 document.body.firstChild.nextSibling.nextSibling], // text after <br> 821 "Initialized with positions selecting 'abc{<br>]def'"); 822 823 range.setStart(document.body.firstChild.nextSibling, 0); 824 range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0); 825 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 826 check(iter, 827 [document.body.firstChild.nextSibling, // <br> 828 document.body.firstChild.nextSibling.nextSibling], // text after <br> 829 "Initialized with range selecting 'abc{<br>]def' (starting in <br>)"); 830 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 831 range.startContainer, range.startOffset, 832 range.endContainer, range.endOffset); 833 check(iter, 834 [document.body.firstChild.nextSibling, // <br> 835 document.body.firstChild.nextSibling.nextSibling], // text after <br> 836 "Initialized with positions selecting 'abc{<br>]def' (starting in <br>)"); 837 838 range.setStart(document.body, 1); 839 range.setEnd(document.body, 2); 840 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 841 check(iter, 842 [document.body.firstChild.nextSibling], // <br> 843 "Initialized with range selecting 'abc{<br>}def'"); 844 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 845 range.startContainer, range.startOffset, 846 range.endContainer, range.endOffset); 847 check(iter, 848 [document.body.firstChild.nextSibling], // <br> 849 "Initialized with positions selecting 'abc{<br>}def'"); 850 851 range.setStart(document.body.firstChild, 3); 852 range.setEnd(document.body.firstChild.nextSibling, 0); 853 iter.initWithRange(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, range); 854 check(iter, 855 [document.body.firstChild], // text before <br> 856 "Initialized with range selecting 'abc[}<br>def' (ending in <br>)"); 857 iter.initWithPositions(Ci.nsIScriptableContentIterator.PRE_ORDER_ITERATOR, 858 range.startContainer, range.startOffset, 859 range.endContainer, range.endOffset); 860 check(iter, 861 [document.body.firstChild], // text before <br> 862 "Initialized with positions selecting 'abc[}<br>def' (ending in <br>)"); 863 864 finish(); 865 }); 866 </script> 867 </head> 868 <body></body> 869 </html>