diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/dom/traversal | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/dom/traversal')
29 files changed, 2255 insertions, 0 deletions
diff --git a/testing/web-platform/tests/dom/traversal/NodeFilter-constants.html b/testing/web-platform/tests/dom/traversal/NodeFilter-constants.html new file mode 100644 index 0000000000..1ce4736cc6 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/NodeFilter-constants.html @@ -0,0 +1,34 @@ +<!doctype html> +<title>NodeFilter constants</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../constants.js"></script> +<div id="log"></div> +<script> +var objects; +setup(function() { + objects = [ + [NodeFilter, "NodeFilter interface object"], + ] +}) +testConstants(objects, [ + ["FILTER_ACCEPT", 1], + ["FILTER_REJECT", 2], + ["FILTER_SKIP", 3] +], "acceptNode") +testConstants(objects, [ + ["SHOW_ALL", 0xFFFFFFFF], + ["SHOW_ELEMENT", 0x1], + ["SHOW_ATTRIBUTE", 0x2], + ["SHOW_TEXT", 0x4], + ["SHOW_CDATA_SECTION", 0x8], + ["SHOW_ENTITY_REFERENCE", 0x10], + ["SHOW_ENTITY", 0x20], + ["SHOW_PROCESSING_INSTRUCTION", 0x40], + ["SHOW_COMMENT", 0x80], + ["SHOW_DOCUMENT", 0x100], + ["SHOW_DOCUMENT_TYPE", 0x200], + ["SHOW_DOCUMENT_FRAGMENT", 0x400], + ["SHOW_NOTATION", 0x800] +], "whatToShow") +</script> diff --git a/testing/web-platform/tests/dom/traversal/NodeIterator-removal.html b/testing/web-platform/tests/dom/traversal/NodeIterator-removal.html new file mode 100644 index 0000000000..b5fc69541a --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/NodeIterator-removal.html @@ -0,0 +1,100 @@ +<!doctype html> +<title>NodeIterator removal tests</title> +<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name> +<meta name=timeout content=long> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=../common.js></script> +<script> +"use strict"; + +for (var i = 0; i < testNodes.length; i++) { + var node = eval(testNodes[i]); + if (!node.parentNode) { + // Nothing to test + continue; + } + test(function() { + var iters = []; + var descs = []; + var expectedReferenceNodes = []; + var expectedPointers = []; + + for (var j = 0; j < testNodes.length; j++) { + var root = eval(testNodes[j]); + // Add all distinct iterators with this root, calling nextNode() + // repeatedly until it winds up with the same iterator. + for (var k = 0; ; k++) { + var iter = document.createNodeIterator(root); + for (var l = 0; l < k; l++) { + iter.nextNode(); + } + if (k && iter.referenceNode == iters[iters.length - 1].referenceNode + && iter.pointerBeforeReferenceNode + == iters[iters.length - 1].pointerBeforeReferenceNode) { + break; + } else { + iters.push(iter); + descs.push("document.createNodeIterator(" + testNodes[j] + + ") advanced " + k + " times"); + expectedReferenceNodes.push(iter.referenceNode); + expectedPointers.push(iter.pointerBeforeReferenceNode); + + var idx = iters.length - 1; + + // "If the node is root or is not an inclusive ancestor of the + // referenceNode attribute value, terminate these steps." + // + // We also have to rule out the case where node is an ancestor of + // root, which is implicitly handled by the spec since such a node + // was not part of the iterator collection to start with. + if (isInclusiveAncestor(node, root) + || !isInclusiveAncestor(node, iter.referenceNode)) { + continue; + } + + // "If the pointerBeforeReferenceNode attribute value is false, set + // the referenceNode attribute to the first node preceding the node + // that is being removed, and terminate these steps." + if (!iter.pointerBeforeReferenceNode) { + expectedReferenceNodes[idx] = previousNode(node); + continue; + } + + // "If there is a node following the last inclusive descendant of the + // node that is being removed, set the referenceNode attribute to the + // first such node, and terminate these steps." + var next = nextNodeDescendants(node); + if (next) { + expectedReferenceNodes[idx] = next; + continue; + } + + // "Set the referenceNode attribute to the first node preceding the + // node that is being removed and set the pointerBeforeReferenceNode + // attribute to false." + expectedReferenceNodes[idx] = previousNode(node); + expectedPointers[idx] = false; + } + } + } + + var oldParent = node.parentNode; + var oldSibling = node.nextSibling; + oldParent.removeChild(node); + + for (var j = 0; j < iters.length; j++) { + var iter = iters[j]; + assert_equals(iter.referenceNode, expectedReferenceNodes[j], + ".referenceNode of " + descs[j]); + assert_equals(iter.pointerBeforeReferenceNode, expectedPointers[j], + ".pointerBeforeReferenceNode of " + descs[j]); + } + + oldParent.insertBefore(node, oldSibling); + }, "Test removing node " + testNodes[i]); +} + +testDiv.style.display = "none"; +</script> diff --git a/testing/web-platform/tests/dom/traversal/NodeIterator.html b/testing/web-platform/tests/dom/traversal/NodeIterator.html new file mode 100644 index 0000000000..fb81676cc5 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/NodeIterator.html @@ -0,0 +1,215 @@ +<!doctype html> +<title>NodeIterator tests</title> +<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name> +<meta name=timeout content=long> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=../common.js></script> +<script> +"use strict"; + +function check_iter(iter, root, whatToShowValue) { + whatToShowValue = whatToShowValue === undefined ? 0xFFFFFFFF : whatToShowValue; + + assert_equals(iter.toString(), '[object NodeIterator]', 'toString'); + assert_equals(iter.root, root, 'root'); + assert_equals(iter.whatToShow, whatToShowValue, 'whatToShow'); + assert_equals(iter.filter, null, 'filter'); + assert_equals(iter.referenceNode, root, 'referenceNode'); + assert_equals(iter.pointerBeforeReferenceNode, true, 'pointerBeforeReferenceNode'); + assert_readonly(iter, 'root'); + assert_readonly(iter, 'whatToShow'); + assert_readonly(iter, 'filter'); + assert_readonly(iter, 'referenceNode'); + assert_readonly(iter, 'pointerBeforeReferenceNode'); +} + +test(function() { + var iter = document.createNodeIterator(document); + iter.detach(); + iter.detach(); +}, "detach() should be a no-op"); + +test(function() { + var iter = document.createNodeIterator(document); + check_iter(iter, document); +}, "createNodeIterator() parameter defaults"); + +test(function() { + var iter = document.createNodeIterator(document, null, null); + check_iter(iter, document, 0); +}, "createNodeIterator() with null as arguments"); + +test(function() { + var iter = document.createNodeIterator(document, undefined, undefined); + check_iter(iter, document); +}, "createNodeIterator() with undefined as arguments"); + +test(function() { + var err = {name: "failed"}; + var iter = document.createNodeIterator(document, NodeFilter.SHOW_ALL, + function() { throw err; }); + assert_throws_exactly(err, function() { iter.nextNode() }); +}, "Propagate exception from filter function"); + +test(function() { + var depth = 0; + var iter = document.createNodeIterator(document, NodeFilter.SHOW_ALL, + function() { + if (iter.referenceNode != document && depth == 0) { + depth++; + iter.nextNode(); + } + return NodeFilter.FILTER_ACCEPT; + }); + iter.nextNode(); + iter.nextNode(); + assert_throws_dom("InvalidStateError", function() { iter.nextNode() }); + depth--; + assert_throws_dom("InvalidStateError", function() { iter.previousNode() }); +}, "Recursive filters need to throw"); + +function testIterator(root, whatToShow, filter) { + var iter = document.createNodeIterator(root, whatToShow, filter); + + assert_equals(iter.root, root, ".root"); + assert_equals(iter.referenceNode, root, "Initial .referenceNode"); + assert_equals(iter.pointerBeforeReferenceNode, true, + ".pointerBeforeReferenceNode"); + assert_equals(iter.whatToShow, whatToShow, ".whatToShow"); + assert_equals(iter.filter, filter, ".filter"); + + var expectedReferenceNode = root; + var expectedBeforeNode = true; + // "Let node be the value of the referenceNode attribute." + var node = root; + // "Let before node be the value of the pointerBeforeReferenceNode + // attribute." + var beforeNode = true; + var i = 1; + // Each loop iteration runs nextNode() once. + while (node) { + do { + if (!beforeNode) { + // "If before node is false, let node be the first node following node + // in the iterator collection. If there is no such node return null." + node = nextNode(node); + if (!isInclusiveDescendant(node, root)) { + node = null; + break; + } + } else { + // "If before node is true, set it to false." + beforeNode = false; + } + // "Filter node and let result be the return value. + // + // "If result is FILTER_ACCEPT, go to the next step in the overall set of + // steps. + // + // "Otherwise, run these substeps again." + if (!((1 << (node.nodeType - 1)) & whatToShow) + || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) { + continue; + } + + // "Set the referenceNode attribute to node, set the + // pointerBeforeReferenceNode attribute to before node, and return node." + expectedReferenceNode = node; + expectedBeforeNode = beforeNode; + + break; + } while (true); + + assert_equals(iter.nextNode(), node, ".nextNode() " + i + " time(s)"); + assert_equals(iter.referenceNode, expectedReferenceNode, + ".referenceNode after nextNode() " + i + " time(s)"); + assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode, + ".pointerBeforeReferenceNode after nextNode() " + i + " time(s)"); + + i++; + } + + // Same but for previousNode() (mostly copy-pasted, oh well) + var iter = document.createNodeIterator(root, whatToShow, filter); + + var expectedReferenceNode = root; + var expectedBeforeNode = true; + // "Let node be the value of the referenceNode attribute." + var node = root; + // "Let before node be the value of the pointerBeforeReferenceNode + // attribute." + var beforeNode = true; + var i = 1; + // Each loop iteration runs previousNode() once. + while (node) { + do { + if (beforeNode) { + // "If before node is true, let node be the first node preceding node + // in the iterator collection. If there is no such node return null." + node = previousNode(node); + if (!isInclusiveDescendant(node, root)) { + node = null; + break; + } + } else { + // "If before node is false, set it to true." + beforeNode = true; + } + // "Filter node and let result be the return value. + // + // "If result is FILTER_ACCEPT, go to the next step in the overall set of + // steps. + // + // "Otherwise, run these substeps again." + if (!((1 << (node.nodeType - 1)) & whatToShow) + || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) { + continue; + } + + // "Set the referenceNode attribute to node, set the + // pointerBeforeReferenceNode attribute to before node, and return node." + expectedReferenceNode = node; + expectedBeforeNode = beforeNode; + + break; + } while (true); + + assert_equals(iter.previousNode(), node, ".previousNode() " + i + " time(s)"); + assert_equals(iter.referenceNode, expectedReferenceNode, + ".referenceNode after previousNode() " + i + " time(s)"); + assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode, + ".pointerBeforeReferenceNode after previousNode() " + i + " time(s)"); + + i++; + } +} + +var whatToShows = [ + "0", + "0xFFFFFFFF", + "NodeFilter.SHOW_ELEMENT", + "NodeFilter.SHOW_ATTRIBUTE", + "NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT", +]; + +var callbacks = [ + "null", + "(function(node) { return true })", + "(function(node) { return false })", + "(function(node) { return node.nodeName[0] == '#' })", +]; + +for (var i = 0; i < testNodes.length; i++) { + for (var j = 0; j < whatToShows.length; j++) { + for (var k = 0; k < callbacks.length; k++) { + test(() => { + testIterator(eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k])); + }, "document.createNodeIterator(" + testNodes[i] + ", " + whatToShows[j] + ", " + callbacks[k] + ")"); + } + } +} + +testDiv.style.display = "none"; +</script> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter-cross-realm-null-browsing-context.html b/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter-cross-realm-null-browsing-context.html new file mode 100644 index 0000000000..f8e71bcdf5 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter-cross-realm-null-browsing-context.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TreeWalker: NodeFilter from detached iframe doesn't get called</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<div></div> + +<script> +const t = async_test(); + +const iframe = document.createElement("iframe"); +iframe.src = "support/TreeWalker-acceptNode-filter-cross-realm-null-browsing-context-subframe.html"; +iframe.onload = t.step_func_done(() => { + const nodeIterator = iframe.contentWindow.createNodeIterator(); + iframe.remove(); + + assert_equals(iframe.contentWindow, null); + + let errorWasThrown = false; + try { nodeIterator.nextNode(); } + catch { errorWasThrown = true; } + + assert_true(errorWasThrown); + assert_false(nodeIterator.dummyFilterCalled); +}); + +document.body.append(iframe); +</script> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter-cross-realm.html b/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter-cross-realm.html new file mode 100644 index 0000000000..da91cf6cb2 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter-cross-realm.html @@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TreeWalker: cross-realm NodeFilter throws TypeError of its associated Realm</title> +<link rel="help" href="https://webidl.spec.whatwg.org/#ref-for-prepare-to-run-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe name="nodeFilterGlobalObject" src="support/empty-document.html"></iframe> + +<div id="treeWalkerRoot"> + <div class="firstChild"></div> +</div> + +<script> +test_onload(() => { + const nodeFilter = new nodeFilterGlobalObject.Object; + + const walker = document.createTreeWalker(treeWalkerRoot, NodeFilter.SHOW_ELEMENT, nodeFilter); + assert_throws_js(nodeFilterGlobalObject.TypeError, () => { walker.firstChild(); }); +}, "NodeFilter is cross-realm plain object without 'acceptNode' property"); + +test_onload(() => { + const nodeFilter = new nodeFilterGlobalObject.Object; + nodeFilter.acceptNode = {}; + + const walker = document.createTreeWalker(treeWalkerRoot, NodeFilter.SHOW_ELEMENT, nodeFilter); + assert_throws_js(nodeFilterGlobalObject.TypeError, () => { walker.firstChild(); }); +}, "NodeFilter is cross-realm plain object with non-callable 'acceptNode' property"); + +test_onload(() => { + const { proxy, revoke } = Proxy.revocable(() => {}, {}); + revoke(); + + const nodeFilter = new nodeFilterGlobalObject.Object; + nodeFilter.acceptNode = proxy; + + const walker = document.createTreeWalker(treeWalkerRoot, NodeFilter.SHOW_ELEMENT, nodeFilter); + assert_throws_js(nodeFilterGlobalObject.TypeError, () => { walker.firstChild(); }); +}, "NodeFilter is cross-realm plain object with revoked Proxy as 'acceptNode' property"); + +test_onload(() => { + const { proxy, revoke } = nodeFilterGlobalObject.Proxy.revocable({}, {}); + revoke(); + + const walker = document.createTreeWalker(treeWalkerRoot, NodeFilter.SHOW_ELEMENT, proxy); + assert_throws_js(nodeFilterGlobalObject.TypeError, () => { walker.firstChild(); }); +}, "NodeFilter is cross-realm non-callable revoked Proxy"); + +test_onload(() => { + const { proxy, revoke } = nodeFilterGlobalObject.Proxy.revocable(() => {}, {}); + revoke(); + + const walker = document.createTreeWalker(treeWalkerRoot, NodeFilter.SHOW_ELEMENT, proxy); + assert_throws_js(nodeFilterGlobalObject.TypeError, () => { walker.firstChild(); }); +}, "NodeFilter is cross-realm callable revoked Proxy"); + +function test_onload(fn, desc) { + async_test(t => { window.addEventListener("load", t.step_func_done(fn)); }, desc); +} +</script> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter.html b/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter.html new file mode 100644 index 0000000000..282dc9d142 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-acceptNode-filter.html @@ -0,0 +1,195 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/acceptNode-filter.js +--> +<head> +<title>TreeWalker: acceptNode-filter</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<link rel="help" href="https://dom.spec.whatwg.org/#callbackdef-nodefilter"> +<div id=log></div> +</head> +<body> +<p>Test JS objects as NodeFilters</p> +<script> +var testElement; +setup(function() { + testElement = document.createElement("div"); + testElement.id = 'root'; + //testElement.innerHTML='<div id="A1"><div id="B1"></div><div id="B2"></div></div>'; + + // XXX for Servo, build the tree without using innerHTML + var a1 = document.createElement("div"); + a1.id = "A1"; + var b1 = document.createElement("div"); + b1.id = "B1"; + var b2 = document.createElement("div"); + b2.id = "B2"; + testElement.appendChild(a1); + a1.appendChild(b1); + a1.appendChild(b2); +}); + +test(function() +{ + function filter(node) + { + if (node.id == "B1") + return NodeFilter.FILTER_SKIP; + return NodeFilter.FILTER_ACCEPT; + } + + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.currentNode, { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B2' }); + assert_node(walker.currentNode, { type: Element, id: 'B2' }); +}, 'Testing with raw function filter'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, { + acceptNode : function(node) { + if (node.id == "B1") + return NodeFilter.FILTER_SKIP; + return NodeFilter.FILTER_ACCEPT; + } + }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.currentNode, { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B2' }); + assert_node(walker.currentNode, { type: Element, id: 'B2' }); +}, 'Testing with object filter'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, null); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.currentNode, { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B1' }); + assert_node(walker.currentNode, { type: Element, id: 'B1' }); +}, 'Testing with null filter'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, undefined); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.currentNode, { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B1' }); + assert_node(walker.currentNode, { type: Element, id: 'B1' }); +}, 'Testing with undefined filter'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, {}); + assert_throws_js(TypeError, function () { walker.firstChild(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_throws_js(TypeError, function () { walker.nextNode(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); +}, 'Testing with object lacking acceptNode property'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, { acceptNode: "foo" }); + assert_throws_js(TypeError, function () { walker.firstChild(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_throws_js(TypeError, function () { walker.nextNode(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); +}, 'Testing with object with non-function acceptNode property'); + +test(function(t) +{ + var filter = function() { return NodeFilter.FILTER_ACCEPT; }; + filter.acceptNode = t.unreached_func("`acceptNode` method should not be called on functions"); + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B1' }); +}, 'Testing with function having acceptNode function'); + +test(function() +{ + var test_error = { name: "test" }; + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, + function(node) { + throw test_error; + }); + assert_throws_exactly(test_error, function () { walker.firstChild(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_throws_exactly(test_error, function () { walker.nextNode(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); +}, 'Testing with filter function that throws'); + +test(function() { + var testError = { name: "test" }; + var filter = { + get acceptNode() { + throw testError; + }, + }; + + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + assert_throws_exactly(testError, function() { walker.firstChild(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_throws_exactly(testError, function() { walker.nextNode(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); +}, "rethrows errors when getting `acceptNode`"); + +test(function() { + var calls = 0; + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, { + get acceptNode() { + calls++; + return function() { + return NodeFilter.FILTER_ACCEPT; + }; + }, + }); + + assert_equals(calls, 0); + walker.nextNode(); + walker.nextNode(); + assert_equals(calls, 2); +}, "performs `Get` on every traverse"); + +test(function() +{ + var test_error = { name: "test" }; + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, + { + acceptNode : function(node) { + throw test_error; + } + }); + assert_throws_exactly(test_error, function () { walker.firstChild(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_throws_exactly(test_error, function () { walker.nextNode(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); +}, 'Testing with filter object that throws'); + +test(() => +{ + let thisValue, nodeArgID; + const filter = { + acceptNode(node) { + thisValue = this; + nodeArgID = node.id; + return NodeFilter.FILTER_ACCEPT; + }, + }; + + const walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + walker.nextNode(); + + assert_equals(thisValue, filter); + assert_equals(nodeArgID, 'A1'); +}, 'Testing with filter object: this value and `node` argument'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-basic.html b/testing/web-platform/tests/dom/traversal/TreeWalker-basic.html new file mode 100644 index 0000000000..bd8b112840 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-basic.html @@ -0,0 +1,154 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/TreeWalker-basic.html +--> +<head> +<title>TreeWalker: Basic test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<p>This test checks the basic functionality of TreeWalker.</p> +<script> +function createSampleDOM() +{ + // Tree structure: + // #a + // | + // +----+----+ + // | | + // "b" #c + // | + // +----+----+ + // | | + // #d <!--j--> + // | + // +----+----+ + // | | | + // "e" #f "i" + // | + // +--+--+ + // | | + // "g" <!--h--> + var div = document.createElement('div'); + div.id = 'a'; + // div.innerHTML = 'b<div id="c"><div id="d">e<span id="f">g<!--h--></span>i</div><!--j--></div>'; + + div.appendChild(document.createTextNode("b")); + + var c = document.createElement("div"); + c.id = 'c'; + div.appendChild(c); + + var d = document.createElement("div"); + d.id = 'd'; + c.appendChild(d); + + var e = document.createTextNode("e"); + d.appendChild(e); + + var f = document.createElement("span"); + f.id = 'f'; + d.appendChild(f); + + var g = document.createTextNode("g"); + f.appendChild(g); + + var h = document.createComment("h"); + f.appendChild(h); + + var i = document.createTextNode("i"); + d.appendChild(i); + + var j = document.createComment("j"); + c.appendChild(j); + + return div; +} + +function check_walker(walker, root, whatToShowValue) +{ + whatToShowValue = whatToShowValue === undefined ? 0xFFFFFFFF : whatToShowValue; + + assert_equals(walker.toString(), '[object TreeWalker]', 'toString'); + assert_equals(walker.root, root, 'root'); + assert_equals(walker.whatToShow, whatToShowValue, 'whatToShow'); + assert_equals(walker.filter, null, 'filter'); + assert_equals(walker.currentNode, root, 'currentNode'); + assert_readonly(walker, 'root'); + assert_readonly(walker, 'whatToShow'); + assert_readonly(walker, 'filter'); +} + +test(function () +{ + var root = createSampleDOM(); + var walker = document.createTreeWalker(root); + check_walker(walker, root); +}, 'Construct a TreeWalker by document.createTreeWalker(root).'); + +test(function () +{ + var root = createSampleDOM(); + var walker = document.createTreeWalker(root, null, null); + check_walker(walker, root, 0); +}, 'Construct a TreeWalker by document.createTreeWalker(root, null, null).'); + +test(function () +{ + var root = createSampleDOM(); + var walker = document.createTreeWalker(root, undefined, undefined); + check_walker(walker, root); +}, 'Construct a TreeWalker by document.createTreeWalker(root, undefined, undefined).'); + +test(function () +{ + assert_throws_js(TypeError, function () { document.createTreeWalker(); }); + assert_throws_js(TypeError, function () { document.createTreeWalker(null); }); + assert_throws_js(TypeError, function () { document.createTreeWalker(undefined); }); + assert_throws_js(TypeError, function () { document.createTreeWalker(new Object()); }); + assert_throws_js(TypeError, function () { document.createTreeWalker(1); }); +}, 'Give an invalid root node to document.createTreeWalker().'); + +test(function () +{ + var root = createSampleDOM(); + var walker = document.createTreeWalker(root); + var f = root.lastChild.firstChild.childNodes[1]; // An element node: div#f. + + assert_node(walker.currentNode, { type: Element, id: 'a' }); + assert_equals(walker.parentNode(), null); + assert_node(walker.currentNode, { type: Element, id: 'a' }); + assert_node(walker.firstChild(), { type: Text, nodeValue: 'b' }); + assert_node(walker.currentNode, { type: Text, nodeValue: 'b' }); + assert_node(walker.nextSibling(), { type: Element, id: 'c' }); + assert_node(walker.currentNode, { type: Element, id: 'c' }); + assert_node(walker.lastChild(), { type: Comment, nodeValue: 'j' }); + assert_node(walker.currentNode, { type: Comment, nodeValue: 'j' }); + assert_node(walker.previousSibling(), { type: Element, id: 'd' }); + assert_node(walker.currentNode, { type: Element, id: 'd' }); + assert_node(walker.nextNode(), { type: Text, nodeValue: 'e' }); + assert_node(walker.currentNode, { type: Text, nodeValue: 'e' }); + assert_node(walker.parentNode(), { type: Element, id: 'd' }); + assert_node(walker.currentNode, { type: Element, id: 'd' }); + assert_node(walker.previousNode(), { type: Element, id: 'c' }); + assert_node(walker.currentNode, { type: Element, id: 'c' }); + assert_equals(walker.nextSibling(), null); + assert_node(walker.currentNode, { type: Element, id: 'c' }); + walker.currentNode = f; + assert_equals(walker.currentNode, f); +}, 'Walk over nodes.'); + +test(function() { + var treeWalker = document.createTreeWalker(document.body, 42, null); + assert_equals(treeWalker.root, document.body); + assert_equals(treeWalker.currentNode, document.body); + assert_equals(treeWalker.whatToShow, 42); + assert_equals(treeWalker.filter, null); +}, "Optional arguments to createTreeWalker should be optional (3 passed, null)."); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-currentNode.html b/testing/web-platform/tests/dom/traversal/TreeWalker-currentNode.html new file mode 100644 index 0000000000..f795abe0d2 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-currentNode.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/resources/TreeWalker-currentNode.js +--> +<head> +<title>TreeWalker: currentNode</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<div id='parent'> +<div id='subTree'><p>Lorem ipsum <span>dolor <b>sit</b> amet</span>, consectetur <i>adipisicing</i> elit, sed do eiusmod <tt>tempor <b><i>incididunt ut</i> labore</b> et dolore magna</tt> aliqua.</p></div> +</div> +<p>Test TreeWalker currentNode functionality</p> +<script> +// var subTree = document.createElement('div'); +// subTree.innerHTML = "<p>Lorem ipsum <span>dolor <b>sit</b> amet</span>, consectetur <i>adipisicing</i> elit, sed do eiusmod <tt>tempor <b><i>incididunt ut</i> labore</b> et dolore magna</tt> aliqua.</p>" +// document.body.appendChild(subTree); +var subTree = document.getElementById("subTree"); + +var all = function(node) { return true; } + +test(function() +{ + var w = document.createTreeWalker(subTree, NodeFilter.SHOW_ELEMENT, all); + assert_node(w.currentNode, { type: Element, id: 'subTree' }); + assert_equals(w.parentNode(), null); + assert_node(w.currentNode, { type: Element, id: 'subTree' }); +}, "Test that TreeWalker.parent() doesn't set the currentNode to a node not under the root."); + +test(function() +{ + var w = document.createTreeWalker(subTree, + NodeFilter.SHOW_ELEMENT + | NodeFilter.SHOW_COMMENT, + all); + w.currentNode = document.documentElement; + assert_equals(w.parentNode(), null); + assert_equals(w.currentNode, document.documentElement); + w.currentNode = document.documentElement; + assert_equals(w.nextNode(), document.documentElement.firstChild); + assert_equals(w.currentNode, document.documentElement.firstChild); + w.currentNode = document.documentElement; + assert_equals(w.previousNode(), null); + assert_equals(w.currentNode, document.documentElement); + w.currentNode = document.documentElement; + assert_equals(w.firstChild(), document.documentElement.firstChild); + assert_equals(w.currentNode, document.documentElement.firstChild); + w.currentNode = document.documentElement; + assert_equals(w.lastChild(), document.documentElement.lastChild); + assert_equals(w.currentNode, document.documentElement.lastChild); + w.currentNode = document.documentElement; + assert_equals(w.nextSibling(), null); + assert_equals(w.currentNode, document.documentElement); + w.currentNode = document.documentElement; + assert_equals(w.previousSibling(), null); + assert_equals(w.currentNode, document.documentElement); +}, "Test that we handle setting the currentNode to arbitrary nodes not under the root element."); + +test(function() +{ + var w = document.createTreeWalker(subTree, NodeFilter.SHOW_ELEMENT, all); + w.currentNode = subTree.previousSibling; + assert_equals(w.nextNode(), subTree); + w.currentNode = document.getElementById("parent"); + assert_equals(w.firstChild(), subTree); +}, "Test how we handle the case when the traversed to node is within the root, but the currentElement is not."); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html b/testing/web-platform/tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html new file mode 100644 index 0000000000..e24ca06e20 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html @@ -0,0 +1,87 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/previousNodeLastChildReject.js +--> +<head> +<title>TreeWalker: previousNodeLastChildReject</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<p>Test that previousNode properly respects the filter.</p> +<script> +var testElement; +setup(function() { + testElement = document.createElement("div"); + testElement.id = 'root'; + // testElement.innerHTML='<div id="A1"><div id="B1"><div id="C1"></div><div id="C2"><div id="D1"></div><div id="D2"></div></div></div><div id="B2"><div id="C3"></div><div id="C4"></div></div></div>'; + // testElement.innerHTML=' + // <div id="A1"> + // <div id="B1"> + // <div id="C1"> + // </div> + // <div id="C2"> + // <div id="D1"> + // </div> + // <div id="D2"> + // </div> + // </div> + // </div> + // <div id="B2"> + // <div id="C3"> + // </div> + // <div id="C4"> + // </div> + // </div> + // </div>'; + + // XXX for Servo, build the tree without using innerHTML + var a1 = document.createElement("div"); a1.id = "A1"; + var b1 = document.createElement("div"); b1.id = "B1"; + var b2 = document.createElement("div"); b2.id = "B2"; + var c1 = document.createElement("div"); c1.id = "C1"; + var c2 = document.createElement("div"); c2.id = "C2"; + var c3 = document.createElement("div"); c3.id = "C3"; + var c4 = document.createElement("div"); c4.id = "C4"; + var d1 = document.createElement("div"); d1.id = "D1"; + var d2 = document.createElement("div"); d2.id = "D2"; + + testElement.appendChild(a1); + a1.appendChild(b1); + a1.appendChild(b2); + b1.appendChild(c1); + b1.appendChild(c2); + b2.appendChild(c3); + b2.appendChild(c4); + c2.appendChild(d1); + c2.appendChild(d2); +}); + +test(function() +{ + function filter(node) + { + if (node.id == "C2") + return NodeFilter.FILTER_REJECT; + return NodeFilter.FILTER_ACCEPT; + } + + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.currentNode, { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B1' }); + assert_node(walker.currentNode, { type: Element, id: 'B1' }); + assert_node(walker.nextNode(), { type: Element, id: 'C1' }); + assert_node(walker.currentNode, { type: Element, id: 'C1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B2' }); + assert_node(walker.currentNode, { type: Element, id: 'B2' }); + assert_node(walker.previousNode(), { type: Element, id: 'C1' }); + assert_node(walker.currentNode, { type: Element, id: 'C1' }); +}, 'Test that previousNode properly respects the filter.'); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html b/testing/web-platform/tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html new file mode 100644 index 0000000000..5e28aa5142 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html @@ -0,0 +1,91 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/previousSiblingLastChildSkip.js +--> +<head> +<title>TreeWalker: previousSiblingLastChildSkip</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<p>Test that previousSibling properly respects the filter.</p> +<script> +var testElement; +setup(function() { + testElement = document.createElement("div"); + testElement.id = 'root'; + // testElement.innerHTML='<div id="A1"><div id="B1"><div id="C1"></div><div id="C2"><div id="D1"></div><div id="D2"></div></div></div><div id="B2"><div id="C3"></div><div id="C4"></div></div></div>'; + // testElement.innerHTML=' + // <div id="A1"> + // <div id="B1"> + // <div id="C1"> + // </div> + // <div id="C2"> + // <div id="D1"> + // </div> + // <div id="D2"> + // </div> + // </div> + // </div> + // <div id="B2"> + // <div id="C3"> + // </div> + // <div id="C4"> + // </div> + // </div> + // </div>'; + + // XXX for Servo, build the tree without using innerHTML + var a1 = document.createElement("div"); a1.id = "A1"; + var b1 = document.createElement("div"); b1.id = "B1"; + var b2 = document.createElement("div"); b2.id = "B2"; + var c1 = document.createElement("div"); c1.id = "C1"; + var c2 = document.createElement("div"); c2.id = "C2"; + var c3 = document.createElement("div"); c3.id = "C3"; + var c4 = document.createElement("div"); c4.id = "C4"; + var d1 = document.createElement("div"); d1.id = "D1"; + var d2 = document.createElement("div"); d2.id = "D2"; + + testElement.appendChild(a1); + a1.appendChild(b1); + a1.appendChild(b2); + b1.appendChild(c1); + b1.appendChild(c2); + b2.appendChild(c3); + b2.appendChild(c4); + c2.appendChild(d1); + c2.appendChild(d2); +}); + +test(function() +{ + function filter(node) + { + if (node.id == "B1") + return NodeFilter.FILTER_SKIP; + return NodeFilter.FILTER_ACCEPT; + } + + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.currentNode, { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'C1' }); + assert_node(walker.currentNode, { type: Element, id: 'C1' }); + assert_node(walker.nextNode(), { type: Element, id: 'C2' }); + assert_node(walker.currentNode, { type: Element, id: 'C2' }); + assert_node(walker.nextNode(), { type: Element, id: 'D1' }); + assert_node(walker.currentNode, { type: Element, id: 'D1' }); + assert_node(walker.nextNode(), { type: Element, id: 'D2' }); + assert_node(walker.currentNode, { type: Element, id: 'D2' }); + assert_node(walker.nextNode(), { type: Element, id: 'B2' }); + assert_node(walker.currentNode, { type: Element, id: 'B2' }); + assert_node(walker.previousSibling(), { type: Element, id: 'C2' }); + assert_node(walker.currentNode, { type: Element, id: 'C2' }); +}, 'Test that previousSibling properly respects the filter.'); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-reject.html b/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-reject.html new file mode 100644 index 0000000000..d6c96adc11 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-reject.html @@ -0,0 +1,109 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-reject.js +--> +<head> +<title>TreeWalker: traversal-reject</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<p>Test TreeWalker with rejection</p> +<script> +var testElement; +setup(function() { + testElement = document.createElement("div"); + testElement.id = 'root'; + //testElement.innerHTML='<div id="A1"> <div id="B1"> <div id="C1"></div> </div> <div id="B2"></div><div id="B3"></div> </div>'; + // <div id="A1"> + // <div id="B1"> + // <div id="C1"></div> + // </div> + // <div id="B2"></div> + // <div id="B3"></div> + // </div> + + + // XXX for Servo, build the tree without using innerHTML + var a1 = document.createElement("div"); a1.id = "A1"; + var b1 = document.createElement("div"); b1.id = "B1"; + var b2 = document.createElement("div"); b2.id = "B2"; + var b3 = document.createElement("div"); b3.id = "B3"; + var c1 = document.createElement("div"); c1.id = "C1"; + + testElement.appendChild(a1); + a1.appendChild(b1); + a1.appendChild(b2); + a1.appendChild(b3); + b1.appendChild(c1); +}); + +var rejectB1Filter = { + acceptNode: function(node) { + if (node.id == 'B1') + return NodeFilter.FILTER_REJECT; + + return NodeFilter.FILTER_ACCEPT; + } +} + +var skipB2Filter = { + acceptNode: function(node) { + if (node.id == 'B2') + return NodeFilter.FILTER_SKIP; + + return NodeFilter.FILTER_ACCEPT; + } +} + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter); + assert_node(walker.nextNode(), { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B2' }); + assert_node(walker.nextNode(), { type: Element, id: 'B3' }); +}, 'Testing nextNode'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.firstChild(), { type: Element, id: 'B2' }); +}, 'Testing firstChild'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.firstChild(), { type: Element, id: 'B1' }); + assert_node(walker.nextSibling(), { type: Element, id: 'B3' }); +}, 'Testing nextSibling'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter); + walker.currentNode = testElement.querySelectorAll('#C1')[0]; + assert_node(walker.parentNode(), { type: Element, id: 'A1' }); +}, 'Testing parentNode'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter); + walker.currentNode = testElement.querySelectorAll('#B3')[0]; + assert_node(walker.previousSibling(), { type: Element, id: 'B1' }); +}, 'Testing previousSibling'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter); + walker.currentNode = testElement.querySelectorAll('#B3')[0]; + assert_node(walker.previousNode(), { type: Element, id: 'B2' }); + assert_node(walker.previousNode(), { type: Element, id: 'A1' }); +}, 'Testing previousNode'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-skip-most.html b/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-skip-most.html new file mode 100644 index 0000000000..b6eafd4596 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-skip-most.html @@ -0,0 +1,66 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-skip-most.js +--> +<head> +<title>TreeWalker: traversal-skip-most</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<p>Test TreeWalker with skipping</p> +<script> +var testElement; +setup(function() { + testElement = document.createElement("div"); + testElement.id = 'root'; + // testElement.innerHTML='<div id="A1"><div id="B1" class="keep"></div><div id="B2">this text matters</div><div id="B3" class="keep"></div></div>'; + // <div id="A1"> + // <div id="B1" class="keep"></div> + // <div id="B2">this text matters</div> + // <div id="B3" class="keep"></div> + // </div> + + + // XXX for Servo, build the tree without using innerHTML + var a1 = document.createElement("div"); a1.id = "A1"; + var b1 = document.createElement("div"); b1.id = "B1"; b1.className = "keep"; + var b2 = document.createElement("div"); b2.id = "B2"; + var b3 = document.createElement("div"); b3.id = "B3"; b3.className = "keep"; + + testElement.appendChild(a1); + a1.appendChild(b1); + a1.appendChild(b2) + .appendChild(document.createTextNode("this text matters")); + a1.appendChild(b3); +}); + +var filter = { + acceptNode: function(node) { + if (node.className == 'keep') + return NodeFilter.FILTER_ACCEPT; + + return NodeFilter.FILTER_SKIP; + } +} + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + assert_node(walker.firstChild(), { type: Element, id: 'B1' }); + assert_node(walker.nextSibling(), { type: Element, id: 'B3' }); +}, 'Testing nextSibling'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + walker.currentNode = testElement.querySelectorAll('#B3')[0]; + assert_node(walker.previousSibling(), { type: Element, id: 'B1' }); +}, 'Testing previousSibling'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-skip.html b/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-skip.html new file mode 100644 index 0000000000..6bbebe667e --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-traversal-skip.html @@ -0,0 +1,111 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-skip.js +--> +<head> +<title>TreeWalker: traversal-skip</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<p>Test TreeWalker with skipping</p> +<script> +var testElement; +setup(function() { + testElement = document.createElement("div"); + testElement.id = 'root'; + // testElement.innerHTML='<div id="A1"> <div id="B1"> <div id="C1"></div> </div> <div id="B2"></div><div id="B3"></div> </div>'; + // <div id="A1"> + // <div id="B1"> + // <div id="C1"></div> + // </div> + // <div id="B2"></div> + // <div id="B3"></div> + // </div> + + + // XXX for Servo, build the tree without using innerHTML + var a1 = document.createElement("div"); a1.id = "A1"; + var b1 = document.createElement("div"); b1.id = "B1"; + var b2 = document.createElement("div"); b2.id = "B2"; + var b3 = document.createElement("div"); b3.id = "B3"; + var c1 = document.createElement("div"); c1.id = "C1"; + + testElement.appendChild(a1); + a1.appendChild(b1); + a1.appendChild(b2); + a1.appendChild(b3); + b1.appendChild(c1); +}); + +var skipB1Filter = { + acceptNode: function(node) { + if (node.id == 'B1') + return NodeFilter.FILTER_SKIP; + + return NodeFilter.FILTER_ACCEPT; + } +} + +var skipB2Filter = { + acceptNode: function(node) { + if (node.id == 'B2') + return NodeFilter.FILTER_SKIP; + + return NodeFilter.FILTER_ACCEPT; + } +} + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter); + assert_node(walker.nextNode(), { type: Element, id: 'A1' }); + assert_node(walker.nextNode(), { type: Element, id: 'C1' }); + assert_node(walker.nextNode(), { type: Element, id: 'B2' }); + assert_node(walker.nextNode(), { type: Element, id: 'B3' }); +}, 'Testing nextNode'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.firstChild(), { type: Element, id: 'C1' }); +}, 'Testing firstChild'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter); + assert_node(walker.firstChild(), { type: Element, id: 'A1' }); + assert_node(walker.firstChild(), { type: Element, id: 'B1' }); + assert_node(walker.nextSibling(), { type: Element, id: 'B3' }); +}, 'Testing nextSibling'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter); + walker.currentNode = testElement.querySelectorAll('#C1')[0]; + assert_node(walker.parentNode(), { type: Element, id: 'A1' }); +}, 'Testing parentNode'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter); + walker.currentNode = testElement.querySelectorAll('#B3')[0]; + assert_node(walker.previousSibling(), { type: Element, id: 'B1' }); +}, 'Testing previousSibling'); + +test(function() +{ + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter); + walker.currentNode = testElement.querySelectorAll('#B3')[0]; + assert_node(walker.previousNode(), { type: Element, id: 'B2' }); + assert_node(walker.previousNode(), { type: Element, id: 'C1' }); + assert_node(walker.previousNode(), { type: Element, id: 'A1' }); +}, 'Testing previousNode'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker-walking-outside-a-tree.html b/testing/web-platform/tests/dom/traversal/TreeWalker-walking-outside-a-tree.html new file mode 100644 index 0000000000..b99e33e01f --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker-walking-outside-a-tree.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<!-- +Test adapted from https://github.com/operasoftware/presto-testo/blob/master/core/standards/acid3/individual/006a.html +--> +<head> +<title>TreeWalker: walking-outside-a-tree</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/assert-node.js"></script> +<div id=log></div> +</head> +<body> +<p>[Acid3 - Test 006a] walking outside a tree</p> +<script> +test(function () { + // test 6: walking outside a tree + var doc = document.createElement("div"); + var head = document.createElement('head'); + var title = document.createElement('title'); + var body = document.createElement('body'); + var p = document.createElement('p'); + doc.appendChild(head); + head.appendChild(title); + doc.appendChild(body); + body.appendChild(p); + + var w = document.createTreeWalker(body, 0xFFFFFFFF, null); + doc.removeChild(body); + assert_equals(w.lastChild(), p, "TreeWalker failed after removing the current node from the tree"); + doc.appendChild(p); + assert_equals(w.previousNode(), title, "failed to handle regrafting correctly"); + p.appendChild(body); + assert_equals(w.nextNode(), p, "couldn't retrace steps"); + assert_equals(w.nextNode(), body, "couldn't step back into root"); + assert_equals(w.previousNode(), null, "root didn't retake its rootish position"); +}, "walking outside a tree"); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker.html b/testing/web-platform/tests/dom/traversal/TreeWalker.html new file mode 100644 index 0000000000..093c781447 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/TreeWalker.html @@ -0,0 +1,324 @@ +<!doctype html> +<title>TreeWalker tests</title> +<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name> +<meta name=timeout content=long> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=../common.js></script> +<script> +"use strict"; + +// TODO .previousNode, .nextNode + +test(function() { + var depth = 0; + var walker = document.createTreeWalker(document, NodeFilter.SHOW_ALL, + function() { + if (depth == 0) { + depth++; + walker.firstChild(); + } + return NodeFilter.FILTER_ACCEPT; + }); + walker.currentNode = document.body; + assert_throws_dom("InvalidStateError", function() { walker.parentNode() }); + depth--; + assert_throws_dom("InvalidStateError", function() { walker.firstChild() }); + depth--; + assert_throws_dom("InvalidStateError", function() { walker.lastChild() }); + depth--; + assert_throws_dom("InvalidStateError", function() { walker.previousSibling() }); + depth--; + assert_throws_dom("InvalidStateError", function() { walker.nextSibling() }); + depth--; + assert_throws_dom("InvalidStateError", function() { walker.previousNode() }); + depth--; + assert_throws_dom("InvalidStateError", function() { walker.nextNode() }); +}, "Recursive filters need to throw"); + +function filterNode(node, whatToShow, filter) { + // "If active flag is set throw an "InvalidStateError"." + // Ignore active flag for these tests, we aren't calling recursively + // TODO Test me + + // "Let n be node's nodeType attribute value minus 1." + var n = node.nodeType - 1; + + // "If the nth bit (where 0 is the least significant bit) of whatToShow is + // not set, return FILTER_SKIP." + if (!(whatToShow & (1 << n))) { + return NodeFilter.FILTER_SKIP; + } + + // "If filter is null, return FILTER_ACCEPT." + if (!filter) { + return NodeFilter.FILTER_ACCEPT; + } + + // "Set the active flag." + // + // "Let result be the return value of invoking filter." + // + // "Unset the active flag." + // + // "If an exception was thrown, re-throw the exception." + // TODO Test me + // + // "Return result." + return filter(node); +} + +function testTraverseChildren(type, walker, root, whatToShow, filter) { + // TODO We don't test .currentNode other than the root + walker.currentNode = root; + assert_equals(walker.currentNode, root, "Setting .currentNode"); + + var expectedReturn = null; + var expectedCurrentNode = root; + + // "To traverse children of type type, run these steps: + // + // "Let node be the value of the currentNode attribute." + var node = walker.currentNode; + + // "Set node to node's first child if type is first, and node's last child + // if type is last." + node = type == "first" ? node.firstChild : node.lastChild; + + // "Main: While node is not null, run these substeps:" + while (node) { + // "Filter node and let result be the return value." + var result = filterNode(node, whatToShow, filter); + + // "If result is FILTER_ACCEPT, then set the currentNode attribute to + // node and return node." + if (result == NodeFilter.FILTER_ACCEPT) { + expectedCurrentNode = expectedReturn = node; + break; + } + + // "If result is FILTER_SKIP, run these subsubsteps:" + if (result == NodeFilter.FILTER_SKIP) { + // "Let child be node's first child if type is first, and node's + // last child if type is last." + var child = type == "first" ? node.firstChild : node.lastChild; + + // "If child is not null, set node to child and goto Main." + if (child) { + node = child; + continue; + } + } + + // "While node is not null, run these subsubsteps:" + while (node) { + // "Let sibling be node's next sibling if type is first, and node's + // previous sibling if type is last." + var sibling = type == "first" ? node.nextSibling + : node.previousSibling; + + // "If sibling is not null, set node to sibling and goto Main." + if (sibling) { + node = sibling; + break; + } + + // "Let parent be node's parent." + var parent = node.parentNode; + + // "If parent is null, parent is root, or parent is currentNode + // attribute's value, return null." + if (!parent || parent == root || parent == walker.currentNode) { + expectedReturn = node = null; + break; + } else { + // "Otherwise, set node to parent." + node = parent; + } + } + } + + if (type == "first") { + assert_equals(walker.firstChild(), expectedReturn, ".firstChild()"); + assert_equals(walker.currentNode, expectedCurrentNode, + ".currentNode after .firstChild()"); + } else { + assert_equals(walker.lastChild(), expectedReturn, ".lastChild()"); + assert_equals(walker.currentNode, expectedCurrentNode, + ".currentNode after .lastChild()"); + } +} + +function testTraverseSiblings(type, walker, root, whatToShow, filter) { + // TODO We don't test .currentNode other than the root's first or last child + if (!root.firstChild) { + // Nothing much to test + + walker.currentNode = root; + assert_equals(walker.currentNode, root, "Setting .currentNode"); + + if (type == "next") { + assert_equals(walker.nextSibling(), null, ".nextSibling()"); + assert_equals(walker.currentNode, root, + ".currentNode after .nextSibling()") + } else { + assert_equals(walker.previousSibling(), null, ".previousSibling()"); + assert_equals(walker.currentNode, root, + ".currentNode after .previousSibling()") + } + return; + } + + if (type == "next") { + walker.currentNode = root.firstChild; + assert_equals(walker.currentNode, root.firstChild, + "Setting .currentNode"); + } else { + walker.currentNode = root.lastChild; + assert_equals(walker.currentNode, root.lastChild, + "Setting .currentNode"); + } + + var expectedReturn = null; + var expectedCurrentNode = type == "next" ? root.firstChild : root.lastChild; + + // "To traverse siblings of type type run these steps:" + (function() { + // "Let node be the value of the currentNode attribute." + var node = type == "next" ? root.firstChild : root.lastChild; + + // "If node is root, return null. + // + // "Run these substeps: + do { + // "Let sibling be node's next sibling if type is next, and node's + // previous sibling if type is previous." + var sibling = type == "next" ? node.nextSibling : + node.previousSibling; + + // "While sibling is not null, run these subsubsteps:" + while (sibling) { + // "Set node to sibling." + node = sibling; + + // "Filter node and let result be the return value." + var result = filterNode(node, whatToShow, filter); + + // "If result is FILTER_ACCEPT, then set the currentNode + // attribute to node and return node." + if (result == NodeFilter.FILTER_ACCEPT) { + expectedCurrentNode = expectedReturn = node; + return; + } + + // "Set sibling to node's first child if type is next, and + // node's last child if type is previous." + sibling = type == "next" ? node.firstChild : node.lastChild; + + // "If result is FILTER_REJECT or sibling is null, then set + // sibling to node's next sibling if type is next, and node's + // previous sibling if type is previous." + if (result == NodeFilter.FILTER_REJECT || !sibling) { + sibling = type == "next" ? node.nextSibling : + node.previousSibling; + } + } + + // "Set node to its parent." + node = node.parentNode; + + // "If node is null or is root, return null. + if (!node || node == root) { + return; + } + // "Filter node and if the return value is FILTER_ACCEPT, then + // return null." + if (filterNode(node, whatToShow, filter)) { + return; + } + + // "Run these substeps again." + } while (true); + })(); + + if (type == "next") { + assert_equals(walker.nextSibling(), expectedReturn, ".nextSibling()"); + assert_equals(walker.currentNode, expectedCurrentNode, + ".currentNode after .nextSibling()"); + } else { + assert_equals(walker.previousSibling(), expectedReturn, ".previousSibling()"); + assert_equals(walker.currentNode, expectedCurrentNode, + ".currentNode after .previousSibling()"); + } +} + +function testWalker(root, whatToShow, filter) { + var walker = document.createTreeWalker(root, whatToShow, filter); + + assert_equals(walker.root, root, ".root"); + assert_equals(walker.whatToShow, whatToShow, ".whatToShow"); + assert_equals(walker.filter, filter, ".filter"); + assert_equals(walker.currentNode, root, ".currentNode"); + + var expectedReturn = null; + var expectedCurrentNode = walker.currentNode; + // "The parentNode() method must run these steps:" + // + // "Let node be the value of the currentNode attribute." + var node = walker.currentNode; + + // "While node is not null and is not root, run these substeps:" + while (node && node != root) { + // "Let node be node's parent." + node = node.parentNode; + + // "If node is not null and filtering node returns FILTER_ACCEPT, then + // set the currentNode attribute to node, return node." + if (node && filterNode(node, whatToShow, filter) == + NodeFilter.FILTER_ACCEPT) { + expectedCurrentNode = expectedReturn = node; + } + } + assert_equals(walker.parentNode(), expectedReturn, ".parentNode()"); + assert_equals(walker.currentNode, expectedCurrentNode, + ".currentNode after .parentNode()"); + + testTraverseChildren("first", walker, root, whatToShow, filter); + testTraverseChildren("last", walker, root, whatToShow, filter); + + testTraverseSiblings("next", walker, root, whatToShow, filter); + testTraverseSiblings("previous", walker, root, whatToShow, filter); +} + +var whatToShows = [ + "0", + "0xFFFFFFFF", + "NodeFilter.SHOW_ELEMENT", + "NodeFilter.SHOW_ATTRIBUTE", + "NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT", +]; + +var callbacks = [ + "null", + "(function(node) { return true })", + "(function(node) { return false })", + "(function(node) { return node.nodeName[0] == '#' })", +]; + +var tests = []; +for (var i = 0; i < testNodes.length; i++) { + for (var j = 0; j < whatToShows.length; j++) { + for (var k = 0; k < callbacks.length; k++) { + tests.push([ + "document.createTreeWalker(" + testNodes[i] + + ", " + whatToShows[j] + ", " + callbacks[k] + ")", + eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k]) + ]); + } + } +} +generate_tests(testWalker, tests); + +testDiv.style.display = "none"; +</script> diff --git a/testing/web-platform/tests/dom/traversal/support/TreeWalker-acceptNode-filter-cross-realm-null-browsing-context-subframe.html b/testing/web-platform/tests/dom/traversal/support/TreeWalker-acceptNode-filter-cross-realm-null-browsing-context-subframe.html new file mode 100644 index 0000000000..f5e393d0f0 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/support/TreeWalker-acceptNode-filter-cross-realm-null-browsing-context-subframe.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> + +<script> +function createNodeIterator() { + function filter() { + nodeIterator.dummyFilterCalled = true; + return true; + } + const nodeIterator = parent.document.createNodeIterator(parent.document.body, NodeFilter.SHOW_ELEMENT, filter); + nodeIterator.dummyFilterCalled = false; + return nodeIterator; +} +</script> diff --git a/testing/web-platform/tests/dom/traversal/support/assert-node.js b/testing/web-platform/tests/dom/traversal/support/assert-node.js new file mode 100644 index 0000000000..0d5d8ad74f --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/support/assert-node.js @@ -0,0 +1,10 @@ +// |expected| should be an object indicating the expected type of node. +function assert_node(actual, expected) +{ + assert_true(actual instanceof expected.type, + 'Node type mismatch: actual = ' + actual.nodeType + ', expected = ' + expected.nodeType); + if (typeof(expected.id) !== 'undefined') + assert_equals(actual.id, expected.id); + if (typeof(expected.nodeValue) !== 'undefined') + assert_equals(actual.nodeValue, expected.nodeValue); +} diff --git a/testing/web-platform/tests/dom/traversal/support/empty-document.html b/testing/web-platform/tests/dom/traversal/support/empty-document.html new file mode 100644 index 0000000000..b9cd130a07 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/support/empty-document.html @@ -0,0 +1,3 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<body> diff --git a/testing/web-platform/tests/dom/traversal/unfinished/001.xml b/testing/web-platform/tests/dom/traversal/unfinished/001.xml new file mode 100644 index 0000000000..08bce72fcf --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/001.xml @@ -0,0 +1,53 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Basics</title> + <script type="text/javascript"> <![CDATA[ + function doTest() { + var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, null, false); + var expected = new Array(9, // document + 1, // html + 3, 1, // head + 3, 1, 3, // title + 3, 1, 3, 4, // script and CDATA block + 3, 3, 1, // body + 3, 1, 3, // pre + 3, // </body> + 3, 8, // <!-- --> + 3, 7, // <? ?>, + 3, 4, 3); // CDATA + var found = new Array(); + + // walk document + var node; + while (node = iterator.nextNode()) + found.push(node.nodeType); + + // check results + var errors = 0; + var s = ''; + var length = (found.length > expected.length) ? found.length : expected.length; + s += 'EXPECTED FOUND\n'; + for (var i = 0; i < length; i += 1) { + s += ' ' + (expected[i] ? expected[i] : '-') + + ' ' + (found[i] ? found[i] : '-'); + if (found[i] != expected[i]) { + s += ' MISMATCH'; + errors += 1; + } + s += '\n'; + } + var p = document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'pre')[0]; + if (errors) + p.firstChild.data = 'FAIL: ' + errors + ' errors found:\n\n' + s; + else + p.firstChild.data = 'PASS'; + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script failed to run.</pre> + </body> + <!-- some more nodes to test this: --> + <?test node?> + <![CDATA[]]> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/traversal/unfinished/002.xml b/testing/web-platform/tests/dom/traversal/unfinished/002.xml new file mode 100644 index 0000000000..bf3489688c --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/002.xml @@ -0,0 +1,54 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Basics Backwards</title> + <script type="text/javascript"> <![CDATA[ + function doTest() { + var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, null, false); + var expected = new Array(9, // document + 1, // html + 3, 1, // head + 3, 1, 3, // title + 3, 1, 3, 4, // script and CDATA block + 3, 3, 1, // body + 3, 1, 3, // pre + 3, // </body> + 3, 8, // <!-- --> + 3, 7, // <? ?>, + 3, 4, 3); // CDATA + var found = new Array(); + + // walk document + var node; + while (node = iterator.nextNode()); + while (node = iterator.previousNode()) + found.unshift(node.nodeType); + + // check results + var errors = 0; + var s = ''; + var length = (found.length > expected.length) ? found.length : expected.length; + s += 'EXPECTED FOUND\n'; + for (var i = 0; i < length; i += 1) { + s += ' ' + (expected[i] ? expected[i] : '-') + + ' ' + (found[i] ? found[i] : '-'); + if (found[i] != expected[i]) { + s += ' MISMATCH'; + errors += 1; + } + s += '\n'; + } + var p = document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'pre')[0]; + if (errors) + p.firstChild.data = 'FAIL: ' + errors + ' errors found:\n\n' + s; + else + p.firstChild.data = 'PASS'; + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script failed to run.</pre> + </body> + <!-- some more nodes to test this: --> + <?test node?> + <![CDATA[]]> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/traversal/unfinished/003.xml b/testing/web-platform/tests/dom/traversal/unfinished/003.xml new file mode 100644 index 0000000000..268e6bb4d7 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/003.xml @@ -0,0 +1,58 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Removal of nodes that should have no effect</title> + <!-- + This tests these cases that should have no effect: + 1. Remove a node unrelated to the reference node + 2. Remove an ancestor of the root node + 3. Remove the root node itself + 4. Remove descendant of reference node + --> + <script type="text/javascript"> <![CDATA[ + var errors = 0; + var log = ''; + function doTest() { + var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false); + var root = document.getElementById('root'); + var A = document.getElementById('A'); + var B = document.getElementById('B'); + var C = document.getElementById('C'); + var D = document.getElementById('D'); + var E = document.getElementById('E'); + check(iterator.nextNode(), root); + remove(document.getElementById('X')); + check(iterator.nextNode(), A); + remove(document.getElementById('Y')); + check(iterator.nextNode(), B); + remove(root); + check(iterator.nextNode(), C); + remove(E); + check(iterator.nextNode(), D); + if (errors) + document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log; + else + document.getElementById('result').firstChild.data = 'PASS'; + } + function check(a, b) { + if (!a) { + errors += 1; + log += 'Found null but expected ' + b + ' (' + b.id + ').\n'; + } else if (a != b) { + errors += 1; + log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n'; + } + } + function remove(a) { + if (!a) { + errors += 1; + log += 'Tried removing null node.\n'; + } else + a.parentNode.removeChild(a); + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script did not complete.</pre> + <p><span id="X"></span><span id="Y"><span id="root"><span id="A"><span id="B"><span id="C"><span id="D"><span id="E"></span></span></span></span></span></span></span></p> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/traversal/unfinished/004.xml b/testing/web-platform/tests/dom/traversal/unfinished/004.xml new file mode 100644 index 0000000000..618978f021 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/004.xml @@ -0,0 +1,49 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Removal of the Reference Node</title> + <script type="text/javascript"> <![CDATA[ + var errors = 0; + var log = ''; + function doTest() { + var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false); + var root = document.getElementById('root'); + var A = document.getElementById('A'); + var AA = document.getElementById('AA'); + var B = document.getElementById('B'); + var C = document.getElementById('C'); + check(iterator.nextNode(), root); + check(iterator.nextNode(), A); + check(iterator.nextNode(), AA); + check(iterator.nextNode(), B); + remove(B); + check(iterator.previousNode(), AA); + remove(AA); + check(iterator.nextNode(), C); + if (errors) + document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log; + else + document.getElementById('result').firstChild.data = 'PASS'; + } + function check(a, b) { + if (!a) { + errors += 1; + log += 'Found null but expected ' + b + ' (' + b.id + ').\n'; + } else if (a != b) { + errors += 1; + log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n'; + } + } + function remove(a) { + if (!a) { + errors += 1; + log += 'Tried removing null node.\n'; + } else + a.parentNode.removeChild(a); + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script did not complete.</pre> + <p><span id="root"><span id="A"><span id="AA"></span></span><span id="B"></span><span id="C"><span id="CC"></span></span></span></p> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/traversal/unfinished/005.xml b/testing/web-platform/tests/dom/traversal/unfinished/005.xml new file mode 100644 index 0000000000..643e2f1cd4 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/005.xml @@ -0,0 +1,57 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Removal of the Reference Node (deep check)</title> + <script type="text/javascript"> <![CDATA[ + var errors = 0; + var log = ''; + function doTest() { + var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false); + var root = document.getElementById('root'); + var A = document.getElementById('A'); + var AA = document.getElementById('AA'); + var B = document.getElementById('B'); + var C = document.getElementById('C'); + check(iterator.nextNode(), root); + check(iterator.nextNode(), A); + check(iterator.nextNode(), AA); + check(iterator.nextNode(), B); + remove(B); + var X = addChildTo(AA); + check(iterator.nextNode(), X); + check(iterator.previousNode(), X); + remove(X); + var Y = addChildTo(AA); + check(iterator.previousNode(), Y); + if (errors) + document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log; + else + document.getElementById('result').firstChild.data = 'PASS'; + } + function check(a, b) { + if (!a) { + errors += 1; + log += 'Found null but expected ' + b + ' (' + b.id + ').\n'; + } else if (a != b) { + errors += 1; + log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n'; + } + } + function remove(a) { + if (!a) { + errors += 1; + log += 'Tried removing null node.\n'; + } else + a.parentNode.removeChild(a); + } + function addChildTo(a) { + var x = document.createElementNS('http://www.w3.org/1999/xhtml', 'span'); + a.appendChild(x); + return x; + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script did not complete.</pre> + <p><span id="root"><span id="A"><span id="AA"></span></span><span id="B"></span><span id="C"><span id="CC"></span></span></span></p> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/traversal/unfinished/006.xml b/testing/web-platform/tests/dom/traversal/unfinished/006.xml new file mode 100644 index 0000000000..c2302af836 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/006.xml @@ -0,0 +1,47 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (forwards)</title> + <script type="text/javascript"> <![CDATA[ + var errors = 0; + var log = ''; + function doTest() { + var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false); + var root = document.getElementById('root'); + var A = document.getElementById('A'); + var B = document.getElementById('B'); + var BB = document.getElementById('BB'); + var C = document.getElementById('C'); + check(iterator.nextNode(), root); + check(iterator.nextNode(), A); + check(iterator.nextNode(), B); + check(iterator.nextNode(), BB); + remove(B); + check(iterator.previousNode(), A); + if (errors) + document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log; + else + document.getElementById('result').firstChild.data = 'PASS'; + } + function check(a, b) { + if (!a) { + errors += 1; + log += 'Found null but expected ' + b + ' (' + b.id + ').\n'; + } else if (a != b) { + errors += 1; + log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n'; + } + } + function remove(a) { + if (!a) { + errors += 1; + log += 'Tried removing null node.\n'; + } else + a.parentNode.removeChild(a); + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script did not complete.</pre> + <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p> + </body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/unfinished/007.xml b/testing/web-platform/tests/dom/traversal/unfinished/007.xml new file mode 100644 index 0000000000..98b212e4e5 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/007.xml @@ -0,0 +1,54 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (forwards) (deep check)</title> + <script type="text/javascript"> <![CDATA[ + var errors = 0; + var log = ''; + function doTest() { + var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false); + var root = document.getElementById('root'); + var A = document.getElementById('A'); + var B = document.getElementById('B'); + var BB = document.getElementById('BB'); + var C = document.getElementById('C'); + check(iterator.nextNode(), root); + check(iterator.nextNode(), A); + check(iterator.nextNode(), B); + check(iterator.nextNode(), BB); + remove(B); + var X = addChildTo(A); + check(iterator.nextNode(), X); + if (errors) + document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log; + else + document.getElementById('result').firstChild.data = 'PASS'; + } + function check(a, b) { + if (!a) { + errors += 1; + log += 'Found null but expected ' + b + ' (' + b.id + ').\n'; + } else if (a != b) { + errors += 1; + log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n'; + } + } + function remove(a) { + if (!a) { + errors += 1; + log += 'Tried removing null node.\n'; + } else + a.parentNode.removeChild(a); + } + function addChildTo(a) { + var x = document.createElementNS('http://www.w3.org/1999/xhtml', 'span'); + x.id = 'X'; + a.appendChild(x); + return x; + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script did not complete.</pre> + <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p> + </body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/unfinished/008.xml b/testing/web-platform/tests/dom/traversal/unfinished/008.xml new file mode 100644 index 0000000000..41d7008ae4 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/008.xml @@ -0,0 +1,48 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (backwards)</title> + <script type="text/javascript"> <![CDATA[ + var errors = 0; + var log = ''; + function doTest() { + var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false); + var root = document.getElementById('root'); + var A = document.getElementById('A'); + var B = document.getElementById('B'); + var BB = document.getElementById('BB'); + var C = document.getElementById('C'); + check(iterator.nextNode(), root); + check(iterator.nextNode(), A); + check(iterator.nextNode(), B); + check(iterator.nextNode(), BB); + check(iterator.previousNode(), BB); + remove(B); + check(iterator.nextNode(), C); + if (errors) + document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log; + else + document.getElementById('result').firstChild.data = 'PASS'; + } + function check(a, b) { + if (!a) { + errors += 1; + log += 'Found null but expected ' + b + ' (' + b.id + ').\n'; + } else if (a != b) { + errors += 1; + log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n'; + } + } + function remove(a) { + if (!a) { + errors += 1; + log += 'Tried removing null node.\n'; + } else + a.parentNode.removeChild(a); + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script did not complete.</pre> + <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p> + </body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/unfinished/009.xml b/testing/web-platform/tests/dom/traversal/unfinished/009.xml new file mode 100644 index 0000000000..c3006ecbd6 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/009.xml @@ -0,0 +1,55 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (backwards) (deep check)</title> + <script type="text/javascript"> <![CDATA[ + var errors = 0; + var log = ''; + function doTest() { + var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false); + var root = document.getElementById('root'); + var A = document.getElementById('A'); + var B = document.getElementById('B'); + var BB = document.getElementById('BB'); + var C = document.getElementById('C'); + check(iterator.nextNode(), root); + check(iterator.nextNode(), A); + check(iterator.nextNode(), B); + check(iterator.nextNode(), BB); + check(iterator.previousNode(), BB); + remove(B); + var X = addChildTo(A); + check(iterator.previousNode(), X); + if (errors) + document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log; + else + document.getElementById('result').firstChild.data = 'PASS'; + } + function check(a, b) { + if (!a) { + errors += 1; + log += 'Found null but expected ' + b + ' (' + b.id + ').\n'; + } else if (a != b) { + errors += 1; + log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n'; + } + } + function remove(a) { + if (!a) { + errors += 1; + log += 'Tried removing null node.\n'; + } else + a.parentNode.removeChild(a); + } + function addChildTo(a) { + var x = document.createElementNS('http://www.w3.org/1999/xhtml', 'span'); + x.id = 'X'; + a.appendChild(x); + return x; + } + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script did not complete.</pre> + <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p> + </body> +</html> diff --git a/testing/web-platform/tests/dom/traversal/unfinished/010.xml b/testing/web-platform/tests/dom/traversal/unfinished/010.xml new file mode 100644 index 0000000000..63263a5fd7 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/010.xml @@ -0,0 +1,64 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>DOM Traversal: NodeIterator: Filters</title> + <script type="text/javascript"> <![CDATA[ + function doTest() { + var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, testFilter, false); + // skips text nodes and body element + var expected = new Array(9, // document + 1, // html + 1, // head + 1, // title + 1, 4, // script and CDATA block + // body (skipped) + 1, // pre + // </body> + 8, // <!-- --> + // PI skipped + 4); // CDATA + var found = new Array(); + + // walk document + var node; + while (node = iterator.nextNode()) + found.push(node.nodeType); + + // check results + var errors = 0; + var s = ''; + var length = (found.length > expected.length) ? found.length : expected.length; + s += 'EXPECTED FOUND\n'; + for (var i = 0; i < length; i += 1) { + s += ' ' + (expected[i] ? expected[i] : '-') + + ' ' + (found[i] ? found[i] : '-'); + if (found[i] != expected[i]) { + s += ' MISMATCH'; + errors += 1; + } + s += '\n'; + } + var p = document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'pre')[0]; + if (errors) + p.firstChild.data = 'FAIL: ' + errors + ' errors found:\n\n' + s; + else + p.firstChild.data = 'PASS'; + } + + function testFilter(n) { + if (n.nodeType == 3) { + return NodeFilter.FILTER_SKIP; + } else if (n.nodeName == 'body') { + return NodeFilter.FILTER_REJECT; // same as _SKIP + } + return 1; // FILTER_ACCEPT + } + + ]]></script> + </head> + <body onload="doTest()"> + <pre id="result">FAIL: Script failed to run.</pre> + </body> + <!-- some more nodes to test this: --> + <?body test?> + <![CDATA[]]> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/traversal/unfinished/TODO b/testing/web-platform/tests/dom/traversal/unfinished/TODO new file mode 100644 index 0000000000..cecdf98b08 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/unfinished/TODO @@ -0,0 +1 @@ +Check what happens when a NodeFilter turns a number not in the range 1..3
\ No newline at end of file |