tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_content_iterator_subtree.html (37125B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <meta charset="utf-8">
      5  <title>Test for content subtree 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   * FYI: ContentSubtreeIterator does not support initWithRootNode() nor positionAt().
     84   */
     85 
     86  /**
     87   * Basic behavior tests of first(), last(), prev() and next() after initialized with a range which selects empty element.
     88   */
     89  document.body.innerHTML = "<div></div>";
     90  let range = document.createRange();
     91  range.selectNode(document.body.firstChild);
     92  let description = "Initialized with range including only empty <div>:";
     93  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
     94  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
     95    `${description} currentNode should be the <div> immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
     96  ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`);
     97 
     98  iter.first();
     99  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    100    `${description} currentNode should be the <div> after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    101  ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`);
    102 
    103  iter.last();
    104  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    105    `${description} currentNode should be the <div> after calling last() (got: ${getNodeDescription(iter.currentNode)})`);
    106  ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`);
    107 
    108  iter.prev();
    109  is(SpecialPowers.unwrap(iter.currentNode), null,
    110    `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`);
    111  ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected?
    112 
    113  iter.first();
    114  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    115    `${description} currentNode should be the <div> after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`);
    116  ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`);
    117 
    118  iter.next();
    119  is(SpecialPowers.unwrap(iter.currentNode), null,
    120    `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`);
    121  ok(iter.isDone, `${description} isDone should be true after calling next()`);
    122 
    123  /**
    124   * Basic behavior tests of first(), last(), prev() and next() after initialized with positions which select empty element.
    125   */
    126  range.selectNode(document.body.firstChild);
    127  description = "Initialized with positions including only empty <div>:";
    128  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    129                         range.startContainer, range.startOffset,
    130                         range.endContainer, range.endOffset);
    131  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    132    `${description} currentNode should be the <div> immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    133  ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`);
    134 
    135  iter.first();
    136  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    137    `${description} currentNode should be the <div> after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    138  ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`);
    139 
    140  iter.last();
    141  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    142    `${description} currentNode should be the <div> after calling last() (got: ${getNodeDescription(iter.currentNode)})`);
    143  ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`);
    144 
    145  iter.prev();
    146  is(SpecialPowers.unwrap(iter.currentNode), null,
    147    `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`);
    148  ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected?
    149 
    150  iter.first();
    151  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    152    `${description} currentNode should be the <div> after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`);
    153  ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`);
    154 
    155  iter.next();
    156  is(SpecialPowers.unwrap(iter.currentNode), null,
    157    `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`);
    158  ok(iter.isDone, `${description} isDone should be true after calling next()`);
    159 
    160  /**
    161   * Tests to initializing with collapsed range in an empty element.
    162   */
    163  range = document.createRange();
    164  range.collapse(document.body.firstChild, 0);
    165  description = "Initialized with range collapsed in empty <div>:";
    166  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    167  is(SpecialPowers.unwrap(iter.currentNode), null,
    168    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    169  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    170 
    171  iter.first();
    172  is(SpecialPowers.unwrap(iter.currentNode), null,
    173    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    174  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    175 
    176  /**
    177   * Tests to initializing with collapsed range in an empty element.
    178   */
    179  description = "Initialized with a position in empty <div>:";
    180  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    181                         document.body.firstChild, 0, document.body.firstChild, 0);
    182  is(SpecialPowers.unwrap(iter.currentNode), null,
    183    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    184  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    185 
    186  iter.first();
    187  is(SpecialPowers.unwrap(iter.currentNode), null,
    188    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    189  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    190 
    191  /**
    192   * Basic behavior tests of first(), last(), prev() and next() after initialized with a range which selects the text node.
    193   */
    194  document.body.innerHTML = "<div>some text.</div>";
    195  range = document.createRange();
    196  range.selectNode(document.body.firstChild.firstChild);
    197  description = "Initialized with range including only text node:";
    198  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    199  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild,
    200    `${description} currentNode should be the text node immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    201  ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`);
    202 
    203  iter.first();
    204  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild,
    205    `${description} currentNode should be the text node after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    206  ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`);
    207 
    208  iter.last();
    209  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild,
    210    `${description} currentNode should be the text node after calling last() (got: ${getNodeDescription(iter.currentNode)})`);
    211  ok(!iter.isDone, `${description} isDone shouldn't be true after calling last()`);
    212 
    213  iter.prev();
    214  is(SpecialPowers.unwrap(iter.currentNode), null,
    215    `${description} currentNode should be null after calling prev() (got: ${getNodeDescription(iter.currentNode)})`);
    216  ok(iter.isDone, `${description} isDone should be true after calling prev()`); // XXX Is this expected?
    217 
    218  iter.first();
    219  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild.firstChild,
    220    `${description} currentNode should be the text node after calling first() even after once done (got: ${getNodeDescription(iter.currentNode)})`);
    221  ok(!iter.isDone, `${description} isDone shouldn't be true after calling first() even after once done`);
    222 
    223  iter.next();
    224  is(SpecialPowers.unwrap(iter.currentNode), null,
    225    `${description} currentNode should be null after calling next() (got: ${getNodeDescription(iter.currentNode)})`);
    226  ok(iter.isDone, `${description} isDone should be true after calling next()`);
    227 
    228  /**
    229   * Basic behavior tests of first() and next() after initialized with positions which select the text node.
    230   * XXX In this case, content iterator lists up the parent <div> element.  Not sure if this is intentional difference
    231   *     from initWithRange().
    232   */
    233  range.selectNode(document.body.firstChild);
    234  description = "Initialized with positions including only text node:";
    235  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    236                         range.startContainer, range.startOffset,
    237                         range.endContainer, range.endOffset);
    238  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    239    `${description} currentNode should be the <div> element immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    240  ok(!iter.isDone, `${description} isDone shouldn't be true immediately after initialization`);
    241 
    242  iter.first();
    243  is(SpecialPowers.unwrap(iter.currentNode), document.body.firstChild,
    244    `${description} currentNode should be the <div> element after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    245  ok(!iter.isDone, `${description} isDone shouldn't be true after calling first()`);
    246 
    247  iter.next();
    248  is(SpecialPowers.unwrap(iter.currentNode), null,
    249    `${description} currentNode should be null after calling next() from first position (got: ${getNodeDescription(iter.currentNode)})`);
    250  ok(iter.isDone, `${description} isDone should be true after calling next() from first position`);
    251 
    252  /**
    253   * Tests to initializing with collapsed range at start of a text node.
    254   */
    255  range = document.createRange();
    256  range.collapse(document.body.firstChild.firstChild, 0);
    257  description = "Initialized with range collapsed at start of text node:";
    258  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    259  is(SpecialPowers.unwrap(iter.currentNode), null,
    260    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    261  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    262 
    263  iter.first();
    264  is(SpecialPowers.unwrap(iter.currentNode), null,
    265    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    266  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    267 
    268  /**
    269   * Tests to initializing with collapsed range at start of a text node.
    270   */
    271  description = "Initialized with a position at start of text node:";
    272  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    273                         document.body.firstChild.firstChild, 0, document.body.firstChild.firstChild, 0);
    274  is(SpecialPowers.unwrap(iter.currentNode), null,
    275    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    276  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    277 
    278  iter.first();
    279  is(SpecialPowers.unwrap(iter.currentNode), null,
    280    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    281  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    282 
    283  /**
    284   * Tests to initializing with collapsed range at end of a text node.
    285   */
    286  range = document.createRange();
    287  range.collapse(document.body.firstChild.firstChild, document.body.firstChild.firstChild.length);
    288  description = "Initialized with range collapsed at end of text node:";
    289  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    290  is(SpecialPowers.unwrap(iter.currentNode), null,
    291    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    292  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    293 
    294  iter.first();
    295  is(SpecialPowers.unwrap(iter.currentNode), null,
    296    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    297  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    298 
    299  /**
    300   * Tests to initializing with collapsed range at end of a text node.
    301   */
    302  description = "Initialized with a position at end of text node:";
    303  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    304                         document.body.firstChild.firstChild, document.body.firstChild.firstChild.length,
    305                         document.body.firstChild.firstChild, document.body.firstChild.firstChild.length);
    306  is(SpecialPowers.unwrap(iter.currentNode), null,
    307    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    308  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    309 
    310  iter.first();
    311  is(SpecialPowers.unwrap(iter.currentNode), null,
    312    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    313  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    314 
    315  /**
    316   * Tests to initializing with collapsed range at middle of a text node.
    317   */
    318  range = document.createRange();
    319  range.collapse(document.body.firstChild.firstChild, document.body.firstChild.firstChild.length / 2);
    320  description = "Initialized with range collapsed at end of text node:";
    321  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    322  is(SpecialPowers.unwrap(iter.currentNode), null,
    323    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    324  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    325 
    326  iter.first();
    327  is(SpecialPowers.unwrap(iter.currentNode), null,
    328    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    329  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    330 
    331  /**
    332   * Tests to initializing with collapsed range at middle of a text node.
    333   */
    334  description = "Initialized with a position at end of text node:";
    335  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    336                         document.body.firstChild.firstChild, document.body.firstChild.firstChild.length / 2,
    337                         document.body.firstChild.firstChild, document.body.firstChild.firstChild.length / 2);
    338  is(SpecialPowers.unwrap(iter.currentNode), null,
    339    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    340  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    341 
    342  iter.first();
    343  is(SpecialPowers.unwrap(iter.currentNode), null,
    344    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    345  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    346 
    347  /**
    348   * Tests to initializing with a range selecting all text in a text node.
    349   */
    350  range = document.createRange();
    351  range.setStart(document.body.firstChild.firstChild, 0);
    352  range.setEnd(document.body.firstChild.firstChild, document.body.firstChild.firstChild.length);
    353  description = "Initialized with range selecting all text in text node:";
    354  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    355  is(SpecialPowers.unwrap(iter.currentNode), null,
    356    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    357  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    358 
    359  iter.first();
    360  is(SpecialPowers.unwrap(iter.currentNode), null,
    361    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    362  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    363 
    364  /**
    365   * Tests to initializing with positions selecting all text in a text node.
    366   */
    367  description = "Initialized with positions selecting all text in text node:";
    368  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    369                         document.body.firstChild.firstChild, 0,
    370                         document.body.firstChild.firstChild, document.body.firstChild.firstChild.length);
    371  is(SpecialPowers.unwrap(iter.currentNode), null,
    372    `${description} currentNode should be null immediately after initialization (got: ${getNodeDescription(iter.currentNode)})`);
    373  ok(iter.isDone, `${description} isDone should be true immediately after initialization`);
    374 
    375  iter.first();
    376  is(SpecialPowers.unwrap(iter.currentNode), null,
    377    `${description} currentNode should be null even after calling first() (got: ${getNodeDescription(iter.currentNode)})`);
    378  ok(iter.isDone, `${description} isDone should be true even after calling first()`);
    379 
    380  /**
    381   * Basic tests with complicated tree.
    382   */
    383  function check(aIter, aExpectedResult, aDescription) {
    384    if (aExpectedResult.length) {
    385      is(SpecialPowers.unwrap(aIter.currentNode), aExpectedResult[0],
    386        `${aDescription}: currentNode should be the text node immediately after initialization (got: ${getNodeDescription(aIter.currentNode)}, expected: ${getNodeDescription(aExpectedResult[0])})`);
    387      ok(!aIter.isDone, `${aDescription}: isDone shouldn't be true immediately after initialization`);
    388 
    389      aIter.first();
    390      is(SpecialPowers.unwrap(aIter.currentNode), aExpectedResult[0],
    391        `${aDescription}: currentNode should be the text node after calling first() (got: ${getNodeDescription(aIter.currentNode)}, expected: ${getNodeDescription(aExpectedResult[0])})`);
    392      ok(!aIter.isDone, `${aDescription}: isDone shouldn't be true after calling first()`);
    393 
    394      for (let expected of aExpectedResult) {
    395        is(SpecialPowers.unwrap(aIter.currentNode), expected,
    396          `${aDescription}: currentNode should be the node (got: ${getNodeDescription(aIter.currentNode)}, expected: ${getNodeDescription(expected)})`);
    397        ok(!aIter.isDone, `${aDescription}: isDone shouldn't be true when ${getNodeDescription(expected)} is expected`);
    398        aIter.next();
    399      }
    400 
    401      is(SpecialPowers.unwrap(aIter.currentNode), null,
    402        `${aDescription}: currentNode should be null after calling next() finally (got: ${getNodeDescription(aIter.currentNode)}`);
    403      ok(aIter.isDone, `${aDescription}: isDone should be true after calling next() finally`);
    404    } else {
    405      is(SpecialPowers.unwrap(aIter.currentNode), null,
    406        `${aDescription}: currentNode should be null immediately after initialization (got: ${getNodeDescription(aIter.currentNode)})`);
    407      ok(aIter.isDone, `${aDescription}: isDone should be true immediately after initialization`);
    408 
    409      aIter.first();
    410      is(SpecialPowers.unwrap(aIter.currentNode), null,
    411        `${aDescription}: currentNode should be null after calling first() (got: ${getNodeDescription(aIter.currentNode)})`);
    412      ok(aIter.isDone, `${aDescription}: isDone should be true after calling first()`);
    413    }
    414  }
    415 
    416  document.body.innerHTML = "<p>" +
    417                              "Here is <b>bold</b> and <i><u>underlined and </u>italic </i><span>or no style text.</span><br>" +
    418                            "</p>" +
    419                            "<p>" +
    420                              "Here is an &lt;input&gt; element: <input type=\"text\" value=\"default value\"><br>\n" +
    421                              "and a &lt;textarea&gt; element: <textarea>text area's text node</textarea><br><br>\n" +
    422                              "<!-- and here is comment node -->" +
    423                            "</p>";
    424 
    425  /**
    426   * Selects the <body> with a range.
    427   */
    428  range = document.createRange();
    429  range.selectNode(document.body);
    430  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    431  check(iter, [document.body], "Initialized with range selecting the <body>");
    432 
    433  /**
    434   * Selects the <body> with positions.
    435   */
    436  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    437                         range.startContainer, range.startOffset, range.endContainer, range.endOffset);
    438  check(iter, [document.body], "Initialized with positions selecting the <body>");
    439 
    440  /**
    441   * Selects all children in the <body> with a range.
    442   */
    443  range = document.createRange();
    444  range.selectNodeContents(document.body);
    445  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    446  check(iter,
    447        [document.body.firstChild, // first <p>
    448         document.body.firstChild.nextSibling], // second <p>
    449        "Initialized with range selecting all children in the <body>");
    450 
    451  /**
    452   * Selects all children in the <body> with positions.
    453   */
    454  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    455                         range.startContainer, range.startOffset, range.endContainer, range.endOffset);
    456  check(iter,
    457        [document.body.firstChild, // first <p>
    458         document.body.firstChild.nextSibling], // second <p>
    459        "Initialized with positions selecting all children in the <body>");
    460 
    461  /**
    462   * range/positions around elements.
    463   */
    464  document.body.innerHTML = "abc<b>def</b><i>ghi</i>jkl";
    465  range = document.createRange();
    466 
    467  range.setStart(document.body.firstChild, 0);
    468  range.setEnd(document.body.firstChild.nextSibling.firstChild, 2);
    469  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    470  check(iter, [], "Initialized with range selecting '[abc<b>de]f'");
    471  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    472                         range.startContainer, range.startOffset,
    473                         range.endContainer, range.endOffset);
    474  check(iter, [], "Initialized with positions selecting '[abc<b>de]f'");
    475 
    476  range.setStart(document.body.firstChild, 2);
    477  range.setEnd(document.body.firstChild.nextSibling.firstChild, 2);
    478  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    479  check(iter,[], "Initialized with range selecting 'ab[c<b>de]f'");
    480  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    481                         range.startContainer, range.startOffset,
    482                         range.endContainer, range.endOffset);
    483  check(iter, [], "Initialized with positions selecting 'ab[c<b>de]f'");
    484 
    485  range.setStart(document.body.firstChild, 3);
    486  range.setEnd(document.body.firstChild.nextSibling.firstChild, 2);
    487  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    488  check(iter, [], "Initialized with range selecting 'abc[<b>de]f'");
    489  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    490                         range.startContainer, range.startOffset,
    491                         range.endContainer, range.endOffset);
    492  check(iter, [], "Initialized with positions selecting 'abc[<b>de]f'");
    493 
    494  range.setStart(document.body, 1);
    495  range.setEnd(document.body.firstChild.nextSibling.firstChild, 2);
    496  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    497  check(iter, [], "Initialized with range selecting 'abc{<b>de]f'");
    498  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    499                         range.startContainer, range.startOffset,
    500                         range.endContainer, range.endOffset);
    501  check(iter, [], "Initialized with positions selecting 'abc{<b>de]f'");
    502 
    503  range.setStart(document.body.firstChild.nextSibling, 0);
    504  range.setEnd(document.body.firstChild.nextSibling.firstChild, 2);
    505  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    506  check(iter, [], "Initialized with range selecting '<b>{de]f'");
    507  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    508                         range.startContainer, range.startOffset,
    509                         range.endContainer, range.endOffset);
    510  check(iter, [], "Initialized with positions selecting '<b>{de]f'");
    511 
    512  range.setStart(document.body.firstChild.nextSibling, 0);
    513  range.setEnd(document.body.firstChild.nextSibling.firstChild, 3);
    514  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    515  check(iter, [], "Initialized with range selecting '<b>{def]</b>'");
    516  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    517                         range.startContainer, range.startOffset,
    518                         range.endContainer, range.endOffset);
    519  check(iter, [], "Initialized with positions selecting '<b>{def]</b>'");
    520 
    521  range.setStart(document.body.firstChild.nextSibling, 0);
    522  range.setEnd(document.body.firstChild.nextSibling, 1);
    523  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    524  check(iter,
    525        [document.body.firstChild.nextSibling.firstChild], // text in <b>
    526        "Initialized with range selecting '<b>{def}</b>'");
    527  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    528                         range.startContainer, range.startOffset,
    529                         range.endContainer, range.endOffset);
    530  check(iter,
    531        [document.body.firstChild.nextSibling.firstChild], // text in <b>
    532        "Initialized with positions selecting '<b>{def}</b>'");
    533 
    534  range.setStart(document.body.firstChild.nextSibling, 0);
    535  range.setEnd(document.body, 2);
    536  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    537  check(iter,
    538        [document.body.firstChild.nextSibling.firstChild], // text in <b>
    539       "Initialized with range selecting '<b>{def</b>}<i>ghi'");
    540  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    541                         range.startContainer, range.startOffset,
    542                         range.endContainer, range.endOffset);
    543  check(iter,
    544        [document.body.firstChild.nextSibling.firstChild], // text in <b>
    545        "Initialized with positions selecting '<b>{def</b>}<i>ghi'");
    546 
    547  range.setStart(document.body.firstChild.nextSibling.firstChild, 3);
    548  range.setEnd(document.body, 2);
    549  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    550  check(iter, [], "Initialized with range selecting '<b>def[</b>}<i>ghi'");
    551  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    552                         range.startContainer, range.startOffset,
    553                         range.endContainer, range.endOffset);
    554  check(iter, [], "Initialized with positions selecting '<b>def[</b>}<i>ghi'");
    555 
    556  range.setStart(document.body.firstChild.nextSibling, 1);
    557  range.setEnd(document.body, 2);
    558  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    559  check(iter, [], "Initialized with range selecting '<b>def{</b>}<i>ghi'");
    560  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    561                         range.startContainer, range.startOffset,
    562                         range.endContainer, range.endOffset);
    563  check(iter, [], "Initialized with positions selecting '<b>def{</b>}<i>ghi'");
    564 
    565  range.setStart(document.body.firstChild.nextSibling, 1);
    566  range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0);
    567  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    568  check(iter, [], "Initialized with range selecting '<b>def{</b><i>}ghi'");
    569  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    570                         range.startContainer, range.startOffset,
    571                         range.endContainer, range.endOffset);
    572  check(iter, [], "Initialized with positions selecting '<b>def{</b><i>}ghi'");
    573 
    574  range.setStart(document.body.firstChild.nextSibling, 1);
    575  range.setEnd(document.body.firstChild.nextSibling.nextSibling.firstChild, 0);
    576  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    577  check(iter, [], "Initialized with range selecting '<b>def{</b><i>]ghi'");
    578  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    579                         range.startContainer, range.startOffset,
    580                         range.endContainer, range.endOffset);
    581  check(iter, [], "Initialized with positions selecting '<b>def{</b><i>]ghi'");
    582 
    583  range.setStart(document.body.firstChild.nextSibling.nextSibling, 0);
    584  range.setEnd(document.body, 3);
    585  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    586  check(iter,
    587        [document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i>
    588        "Initialized with range selecting '<i>{ghi</i>}jkl'");
    589  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    590                         range.startContainer, range.startOffset,
    591                         range.endContainer, range.endOffset);
    592  check(iter,
    593        [document.body.firstChild.nextSibling.nextSibling.firstChild], // text in <i>
    594        "Initialized with positions selecting '<i>{ghi</i>}jkl'");
    595 
    596  range.setStart(document.body.firstChild.nextSibling.nextSibling.firstChild, 3);
    597  range.setEnd(document.body, 3);
    598  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    599  check(iter, [], "Initialized with range selecting '<i>ghi[</i>}jkl'");
    600  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    601                         range.startContainer, range.startOffset,
    602                         range.endContainer, range.endOffset);
    603  check(iter, [], "Initialized with positions selecting '<i>ghi[</i>}jkl'");
    604 
    605  range.setStart(document.body.firstChild.nextSibling.nextSibling, 1);
    606  range.setEnd(document.body, 3);
    607  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    608  check(iter, [], "Initialized with range selecting '<i>ghi{</i>}jkl'");
    609  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    610                         range.startContainer, range.startOffset,
    611                         range.endContainer, range.endOffset);
    612  check(iter, [], "Initialized with positions selecting '<i>ghi{</i>}jkl'");
    613 
    614  range.setStart(document.body.firstChild.nextSibling.nextSibling, 1);
    615  range.setEnd(document.body.firstChild.nextSibling.nextSibling.nextSibling, 0);
    616  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    617  check(iter, [], "Initialized with range selecting '<i>ghi{</i>]jkl'");
    618  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    619                         range.startContainer, range.startOffset,
    620                         range.endContainer, range.endOffset);
    621  check(iter, [], "Initialized with positions selecting '<i>ghi{</i>]jkl'");
    622 
    623  /**
    624   * range/positions around <br> elements.
    625   */
    626  document.body.innerHTML = "abc<br>def";
    627  range = document.createRange();
    628  range.setStart(document.body.firstChild, 3);
    629  range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0);
    630  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    631  check(iter,
    632        [document.body.firstChild.nextSibling], // <br>
    633        "Initialized with range selecting 'abc[<br>]def'");
    634  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    635                         range.startContainer, range.startOffset,
    636                         range.endContainer, range.endOffset);
    637  check(iter,
    638        [document.body.firstChild.nextSibling], // <br>
    639        "Initialized with positions selecting 'abc[<br>]def'");
    640 
    641  range.setStart(document.body, 1);
    642  range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0);
    643  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    644  check(iter,
    645        [document.body.firstChild.nextSibling], // <br>
    646        "Initialized with range selecting 'abc{<br>]def'");
    647  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    648                         range.startContainer, range.startOffset,
    649                         range.endContainer, range.endOffset);
    650  check(iter,
    651        [document.body.firstChild.nextSibling], // <br>
    652        "Initialized with positions selecting 'abc{<br>]def'");
    653 
    654  range.setStart(document.body.firstChild.nextSibling, 0);
    655  range.setEnd(document.body.firstChild.nextSibling.nextSibling, 0);
    656  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    657  check(iter, [], "Initialized with range selecting 'abc{<br>]def' (starting in <br>)");
    658  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    659                         range.startContainer, range.startOffset,
    660                         range.endContainer, range.endOffset);
    661  check(iter, [], "Initialized with positions selecting 'abc{<br>]def' (starting in <br>)");
    662 
    663  range.setStart(document.body, 1);
    664  range.setEnd(document.body, 2);
    665  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    666  check(iter,
    667        [document.body.firstChild.nextSibling], // <br>
    668        "Initialized with range selecting 'abc{<br>}def'");
    669  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    670                         range.startContainer, range.startOffset,
    671                         range.endContainer, range.endOffset);
    672  check(iter,
    673        [document.body.firstChild.nextSibling], // <br>
    674        "Initialized with positions selecting 'abc{<br>}def'");
    675 
    676  range.setStart(document.body.firstChild, 3);
    677  range.setEnd(document.body.firstChild.nextSibling, 0);
    678  iter.initWithRange(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR, range);
    679  check(iter, [], "Initialized with range selecting 'abc[}<br>def' (ending in <br>)");
    680  iter.initWithPositions(Ci.nsIScriptableContentIterator.SUBTREE_ITERATOR,
    681                         range.startContainer, range.startOffset,
    682                         range.endContainer, range.endOffset);
    683  check(iter, [], "Initialized with positions selecting 'abc[}<br>def' (ending in <br>)");
    684 
    685  finish();
    686 });
    687 </script>
    688 </head>
    689 <body></body>
    690 </html>