description("Test of behavior NodeIterator when nodes are removed, from Acid3."); var iframe = document.createElement("iframe"); iframe.setAttribute("src", "about:blank"); document.body.appendChild(iframe); var doc = iframe.contentDocument; for (var i = doc.documentElement.childNodes.length-1; i >= 0; i -= 1) doc.documentElement.removeChild(doc.documentElement.childNodes[i]); doc.documentElement.appendChild(doc.createElement('head')); doc.documentElement.firstChild.appendChild(doc.createElement('title')); doc.documentElement.appendChild(doc.createElement('body')); // test 2: Removing nodes during iteration var count = 0; var t1 = doc.body.appendChild(doc.createElement('t1')); var t2 = doc.body.appendChild(doc.createElement('t2')); var t3 = doc.body.appendChild(doc.createElement('t3')); var t4 = doc.body.appendChild(doc.createElement('t4')); var expect = function(n, node1, node2) { count += 1; shouldBe("count", "" + n); nodea = node1; nodeb = node2; shouldBe("nodea", "nodeb"); }; var callCount = 0; var filterFunctions = [ function (node) { expect(1, node, doc.body); return true; }, // filter 0 function (node) { expect(3, node, t1); return true; }, // filter 1 function (node) { expect(5, node, t2); return true; }, // filter 2 function (node) { expect(7, node, t3); doc.body.removeChild(t4); return true; }, // filter 3 function (node) { expect(9, node, t4); return true; }, // filter 4 function (node) { expect(11, node, t4); doc.body.removeChild(t4); return 2 /* REJECT */; }, // filter 5 function (node) { expect(12, node, t3); return true; }, // filter 6 function (node) { expect(14, node, t2); doc.body.removeChild(t2); return true; }, // filter 7 function (node) { expect(16, node, t1); return true; }, // filter 8 ]; var i = doc.createNodeIterator(doc.documentElement.lastChild, 0xFFFFFFFF, function (node) { return filterFunctions[callCount++](node); }, true); // * B 1 2 3 4 expect(2, i.nextNode(), doc.body); // filter 0 // [B] * 1 2 3 4 expect(4, i.nextNode(), t1); // filter 1 // B [1] * 2 3 4 expect(6, i.nextNode(), t2); // filter 2 // B 1 [2] * 3 4 expect(8, i.nextNode(), t3); // filter 3 // B 1 2 [3] * doc.body.appendChild(t4); // B 1 2 [3] * 4 expect(10, i.nextNode(), t4); // filter 4 // B 1 2 3 [4] * expect(13, i.previousNode(), t3); // filters 5, 6 // B 1 2 3 * (4) // filter 5 // B 1 2 [3] * // between 5 and 6 // B 1 2 * (3) // filter 6 // B 1 2 * [3] expect(15, i.previousNode(), t2); // filter 7 // B 1 * (2) [3] // -- spec says "For instance, if a NodeFilter removes a node // from a document, it can still accept the node, which // means that the node may be returned by the NodeIterator // or TreeWalker even though it is no longer in the subtree // being traversed." // -- but it also says "If changes to the iterated list do not // remove the reference node, they do not affect the state // of the NodeIterator." // B 1 * [3] expect(17, i.previousNode(), t1); // filter 8 // B [1] * 3 document.body.removeChild(iframe); var successfullyParsed = true;