Index: third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/common.js |
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/common.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/common.js |
deleted file mode 100644 |
index 70367b2efff769b3b34121958c0be682ea005820..0000000000000000000000000000000000000000 |
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/common.js |
+++ /dev/null |
@@ -1,1083 +0,0 @@ |
-"use strict"; |
-// Written by Aryeh Gregor <ayg@aryeh.name> |
- |
-// TODO: iframes, contenteditable/designMode |
- |
-// Everything is done in functions in this test harness, so we have to declare |
-// all the variables before use to make sure they can be reused. |
-var testDiv, paras, detachedDiv, detachedPara1, detachedPara2, |
- foreignDoc, foreignPara1, foreignPara2, xmlDoc, xmlElement, |
- detachedXmlElement, detachedTextNode, foreignTextNode, |
- detachedForeignTextNode, xmlTextNode, detachedXmlTextNode, |
- processingInstruction, detachedProcessingInstruction, comment, |
- detachedComment, foreignComment, detachedForeignComment, xmlComment, |
- detachedXmlComment, docfrag, foreignDocfrag, xmlDocfrag, doctype, |
- foreignDoctype, xmlDoctype; |
-var testRangesShort, testRanges, testPoints, testNodesShort, testNodes; |
- |
-function setupRangeTests() { |
- testDiv = document.querySelector("#test"); |
- if (testDiv) { |
- testDiv.parentNode.removeChild(testDiv); |
- } |
- testDiv = document.createElement("div"); |
- testDiv.id = "test"; |
- document.body.insertBefore(testDiv, document.body.firstChild); |
- |
- paras = []; |
- paras.push(document.createElement("p")); |
- paras[0].setAttribute("id", "a"); |
- // Test some diacritics, to make sure browsers are using code units here |
- // and not something like grapheme clusters. |
- paras[0].textContent = "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\n"; |
- testDiv.appendChild(paras[0]); |
- |
- paras.push(document.createElement("p")); |
- paras[1].setAttribute("id", "b"); |
- paras[1].setAttribute("style", "display:none"); |
- paras[1].textContent = "Ijklmnop\n"; |
- testDiv.appendChild(paras[1]); |
- |
- paras.push(document.createElement("p")); |
- paras[2].setAttribute("id", "c"); |
- paras[2].textContent = "Qrstuvwx"; |
- testDiv.appendChild(paras[2]); |
- |
- paras.push(document.createElement("p")); |
- paras[3].setAttribute("id", "d"); |
- paras[3].setAttribute("style", "display:none"); |
- paras[3].textContent = "Yzabcdef"; |
- testDiv.appendChild(paras[3]); |
- |
- paras.push(document.createElement("p")); |
- paras[4].setAttribute("id", "e"); |
- paras[4].setAttribute("style", "display:none"); |
- paras[4].textContent = "Ghijklmn"; |
- testDiv.appendChild(paras[4]); |
- |
- detachedDiv = document.createElement("div"); |
- detachedPara1 = document.createElement("p"); |
- detachedPara1.appendChild(document.createTextNode("Opqrstuv")); |
- detachedPara2 = document.createElement("p"); |
- detachedPara2.appendChild(document.createTextNode("Wxyzabcd")); |
- detachedDiv.appendChild(detachedPara1); |
- detachedDiv.appendChild(detachedPara2); |
- |
- // Opera doesn't automatically create a doctype for a new HTML document, |
- // contrary to spec. It also doesn't let you add doctypes to documents |
- // after the fact through any means I've tried. So foreignDoc in Opera |
- // will have no doctype, foreignDoctype will be null, and Opera will fail |
- // some tests somewhat mysteriously as a result. |
- foreignDoc = document.implementation.createHTMLDocument(""); |
- foreignPara1 = foreignDoc.createElement("p"); |
- foreignPara1.appendChild(foreignDoc.createTextNode("Efghijkl")); |
- foreignPara2 = foreignDoc.createElement("p"); |
- foreignPara2.appendChild(foreignDoc.createTextNode("Mnopqrst")); |
- foreignDoc.body.appendChild(foreignPara1); |
- foreignDoc.body.appendChild(foreignPara2); |
- |
- // Now we get to do really silly stuff, which nobody in the universe is |
- // ever going to actually do, but the spec defines behavior, so too bad. |
- // Testing is fun! |
- xmlDoctype = document.implementation.createDocumentType("qorflesnorf", "abcde", "x\"'y"); |
- xmlDoc = document.implementation.createDocument(null, null, xmlDoctype); |
- detachedXmlElement = xmlDoc.createElement("everyone-hates-hyphenated-element-names"); |
- detachedTextNode = document.createTextNode("Uvwxyzab"); |
- detachedForeignTextNode = foreignDoc.createTextNode("Cdefghij"); |
- detachedXmlTextNode = xmlDoc.createTextNode("Klmnopqr"); |
- // PIs only exist in XML documents, so don't bother with document or |
- // foreignDoc. |
- detachedProcessingInstruction = xmlDoc.createProcessingInstruction("whippoorwill", "chirp chirp chirp"); |
- detachedComment = document.createComment("Stuvwxyz"); |
- // Hurrah, we finally got to "z" at the end! |
- detachedForeignComment = foreignDoc.createComment("אריה יהודה"); |
- detachedXmlComment = xmlDoc.createComment("בן חיים אליעזר"); |
- |
- // We should also test with document fragments that actually contain stuff |
- // . . . but, maybe later. |
- docfrag = document.createDocumentFragment(); |
- foreignDocfrag = foreignDoc.createDocumentFragment(); |
- xmlDocfrag = xmlDoc.createDocumentFragment(); |
- |
- xmlElement = xmlDoc.createElement("igiveuponcreativenames"); |
- xmlTextNode = xmlDoc.createTextNode("do re mi fa so la ti"); |
- xmlElement.appendChild(xmlTextNode); |
- processingInstruction = xmlDoc.createProcessingInstruction("somePI", 'Did you know that ":syn sync fromstart" is very useful when using vim to edit large amounts of JavaScript embedded in HTML?'); |
- xmlDoc.appendChild(xmlElement); |
- xmlDoc.appendChild(processingInstruction); |
- xmlComment = xmlDoc.createComment("I maliciously created a comment that will break incautious XML serializers, but Firefox threw an exception, so all I got was this lousy T-shirt"); |
- xmlDoc.appendChild(xmlComment); |
- |
- comment = document.createComment("Alphabet soup?"); |
- testDiv.appendChild(comment); |
- |
- foreignComment = foreignDoc.createComment('"Commenter" and "commentator" mean different things. I\'ve seen non-native speakers trip up on this.'); |
- foreignDoc.appendChild(foreignComment); |
- foreignTextNode = foreignDoc.createTextNode("I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now."); |
- foreignDoc.body.appendChild(foreignTextNode); |
- |
- doctype = document.doctype; |
- foreignDoctype = foreignDoc.doctype; |
- |
- testRangesShort = [ |
- // Various ranges within the text node children of different |
- // paragraphs. All should be valid. |
- "[paras[0].firstChild, 0, paras[0].firstChild, 0]", |
- "[paras[0].firstChild, 0, paras[0].firstChild, 1]", |
- "[paras[0].firstChild, 2, paras[0].firstChild, 8]", |
- "[paras[0].firstChild, 2, paras[0].firstChild, 9]", |
- "[paras[1].firstChild, 0, paras[1].firstChild, 0]", |
- "[paras[1].firstChild, 2, paras[1].firstChild, 9]", |
- "[detachedPara1.firstChild, 0, detachedPara1.firstChild, 0]", |
- "[detachedPara1.firstChild, 2, detachedPara1.firstChild, 8]", |
- "[foreignPara1.firstChild, 0, foreignPara1.firstChild, 0]", |
- "[foreignPara1.firstChild, 2, foreignPara1.firstChild, 8]", |
- // Now try testing some elements, not just text nodes. |
- "[document.documentElement, 0, document.documentElement, 1]", |
- "[document.documentElement, 0, document.documentElement, 2]", |
- "[document.documentElement, 1, document.documentElement, 2]", |
- "[document.head, 1, document.head, 1]", |
- "[document.body, 4, document.body, 5]", |
- "[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]", |
- "[paras[0], 0, paras[0], 1]", |
- "[detachedPara1, 0, detachedPara1, 1]", |
- // Now try some ranges that span elements. |
- "[paras[0].firstChild, 0, paras[1].firstChild, 0]", |
- "[paras[0].firstChild, 0, paras[1].firstChild, 8]", |
- "[paras[0].firstChild, 3, paras[3], 1]", |
- // How about something that spans a node and its descendant? |
- "[paras[0], 0, paras[0].firstChild, 7]", |
- "[testDiv, 2, paras[4], 1]", |
- // Then a few more interesting things just for good measure. |
- "[document, 0, document, 1]", |
- "[document, 0, document, 2]", |
- "[comment, 2, comment, 3]", |
- "[testDiv, 0, comment, 5]", |
- "[foreignDoc, 1, foreignComment, 2]", |
- "[foreignDoc.body, 0, foreignTextNode, 36]", |
- "[xmlDoc, 1, xmlComment, 0]", |
- "[detachedTextNode, 0, detachedTextNode, 8]", |
- "[detachedForeignTextNode, 0, detachedForeignTextNode, 8]", |
- "[detachedXmlTextNode, 0, detachedXmlTextNode, 8]", |
- "[detachedComment, 3, detachedComment, 4]", |
- "[detachedForeignComment, 0, detachedForeignComment, 1]", |
- "[detachedXmlComment, 2, detachedXmlComment, 6]", |
- "[docfrag, 0, docfrag, 0]", |
- "[processingInstruction, 0, processingInstruction, 4]", |
- ]; |
- |
- testRanges = testRangesShort.concat([ |
- "[paras[1].firstChild, 0, paras[1].firstChild, 1]", |
- "[paras[1].firstChild, 2, paras[1].firstChild, 8]", |
- "[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]", |
- "[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]", |
- "[foreignDoc.head, 1, foreignDoc.head, 1]", |
- "[foreignDoc.body, 0, foreignDoc.body, 0]", |
- "[paras[0], 0, paras[0], 0]", |
- "[detachedPara1, 0, detachedPara1, 0]", |
- "[testDiv, 1, paras[2].firstChild, 5]", |
- "[document.documentElement, 1, document.body, 0]", |
- "[foreignDoc.documentElement, 1, foreignDoc.body, 0]", |
- "[document, 1, document, 2]", |
- "[paras[2].firstChild, 4, comment, 2]", |
- "[paras[3], 1, comment, 8]", |
- "[foreignDoc, 0, foreignDoc, 0]", |
- "[xmlDoc, 0, xmlDoc, 0]", |
- "[detachedForeignTextNode, 7, detachedForeignTextNode, 7]", |
- "[detachedXmlTextNode, 7, detachedXmlTextNode, 7]", |
- "[detachedComment, 5, detachedComment, 5]", |
- "[detachedForeignComment, 4, detachedForeignComment, 4]", |
- "[foreignDocfrag, 0, foreignDocfrag, 0]", |
- "[xmlDocfrag, 0, xmlDocfrag, 0]", |
- ]); |
- |
- testPoints = [ |
- // Various positions within the page, some invalid. Remember that |
- // paras[0] is visible, and paras[1] is display: none. |
- "[paras[0].firstChild, -1]", |
- "[paras[0].firstChild, 0]", |
- "[paras[0].firstChild, 1]", |
- "[paras[0].firstChild, 2]", |
- "[paras[0].firstChild, 8]", |
- "[paras[0].firstChild, 9]", |
- "[paras[0].firstChild, 10]", |
- "[paras[0].firstChild, 65535]", |
- "[paras[1].firstChild, -1]", |
- "[paras[1].firstChild, 0]", |
- "[paras[1].firstChild, 1]", |
- "[paras[1].firstChild, 2]", |
- "[paras[1].firstChild, 8]", |
- "[paras[1].firstChild, 9]", |
- "[paras[1].firstChild, 10]", |
- "[paras[1].firstChild, 65535]", |
- "[detachedPara1.firstChild, 0]", |
- "[detachedPara1.firstChild, 1]", |
- "[detachedPara1.firstChild, 8]", |
- "[detachedPara1.firstChild, 9]", |
- "[foreignPara1.firstChild, 0]", |
- "[foreignPara1.firstChild, 1]", |
- "[foreignPara1.firstChild, 8]", |
- "[foreignPara1.firstChild, 9]", |
- // Now try testing some elements, not just text nodes. |
- "[document.documentElement, -1]", |
- "[document.documentElement, 0]", |
- "[document.documentElement, 1]", |
- "[document.documentElement, 2]", |
- "[document.documentElement, 7]", |
- "[document.head, 1]", |
- "[document.body, 3]", |
- "[foreignDoc.documentElement, 0]", |
- "[foreignDoc.documentElement, 1]", |
- "[foreignDoc.head, 0]", |
- "[foreignDoc.body, 1]", |
- "[paras[0], 0]", |
- "[paras[0], 1]", |
- "[paras[0], 2]", |
- "[paras[1], 0]", |
- "[paras[1], 1]", |
- "[paras[1], 2]", |
- "[detachedPara1, 0]", |
- "[detachedPara1, 1]", |
- "[testDiv, 0]", |
- "[testDiv, 3]", |
- // Then a few more interesting things just for good measure. |
- "[document, -1]", |
- "[document, 0]", |
- "[document, 1]", |
- "[document, 2]", |
- "[document, 3]", |
- "[comment, -1]", |
- "[comment, 0]", |
- "[comment, 4]", |
- "[comment, 96]", |
- "[foreignDoc, 0]", |
- "[foreignDoc, 1]", |
- "[foreignComment, 2]", |
- "[foreignTextNode, 0]", |
- "[foreignTextNode, 36]", |
- "[xmlDoc, -1]", |
- "[xmlDoc, 0]", |
- "[xmlDoc, 1]", |
- "[xmlDoc, 5]", |
- "[xmlComment, 0]", |
- "[xmlComment, 4]", |
- "[processingInstruction, 0]", |
- "[processingInstruction, 5]", |
- "[processingInstruction, 9]", |
- "[detachedTextNode, 0]", |
- "[detachedTextNode, 8]", |
- "[detachedForeignTextNode, 0]", |
- "[detachedForeignTextNode, 8]", |
- "[detachedXmlTextNode, 0]", |
- "[detachedXmlTextNode, 8]", |
- "[detachedProcessingInstruction, 12]", |
- "[detachedComment, 3]", |
- "[detachedComment, 5]", |
- "[detachedForeignComment, 0]", |
- "[detachedForeignComment, 4]", |
- "[detachedXmlComment, 2]", |
- "[docfrag, 0]", |
- "[foreignDocfrag, 0]", |
- "[xmlDocfrag, 0]", |
- "[doctype, 0]", |
- "[doctype, -17]", |
- "[doctype, 1]", |
- "[foreignDoctype, 0]", |
- "[xmlDoctype, 0]", |
- ]; |
- |
- testNodesShort = [ |
- "paras[0]", |
- "paras[0].firstChild", |
- "paras[1].firstChild", |
- "foreignPara1", |
- "foreignPara1.firstChild", |
- "detachedPara1", |
- "detachedPara1.firstChild", |
- "document", |
- "detachedDiv", |
- "foreignDoc", |
- "foreignPara2", |
- "xmlDoc", |
- "xmlElement", |
- "detachedTextNode", |
- "foreignTextNode", |
- "processingInstruction", |
- "detachedProcessingInstruction", |
- "comment", |
- "detachedComment", |
- "docfrag", |
- "doctype", |
- "foreignDoctype", |
- ]; |
- |
- testNodes = testNodesShort.concat([ |
- "paras[1]", |
- "detachedPara2", |
- "detachedPara2.firstChild", |
- "testDiv", |
- "detachedXmlElement", |
- "detachedForeignTextNode", |
- "xmlTextNode", |
- "detachedXmlTextNode", |
- "xmlComment", |
- "foreignComment", |
- "detachedForeignComment", |
- "detachedXmlComment", |
- "foreignDocfrag", |
- "xmlDocfrag", |
- "xmlDoctype", |
- ]); |
-} |
-if ("setup" in window) { |
- setup(setupRangeTests); |
-} else { |
- // Presumably we're running from within an iframe or something |
- setupRangeTests(); |
-} |
- |
-/** |
- * The "length" of a node as defined by the Ranges section of DOM4. |
- */ |
-function nodeLength(node) { |
- // "The length of a node node depends on node: |
- // |
- // "DocumentType |
- // "0." |
- if (node.nodeType == Node.DOCUMENT_TYPE_NODE) { |
- return 0; |
- } |
- // "Text |
- // "ProcessingInstruction |
- // "Comment |
- // "Its length attribute value." |
- // Browsers don't historically support the length attribute on |
- // ProcessingInstruction, so to avoid spurious failures, do |
- // node.data.length instead of node.length. |
- if (node.nodeType == Node.TEXT_NODE || node.nodeType == Node.PROCESSING_INSTRUCTION_NODE || node.nodeType == Node.COMMENT_NODE) { |
- return node.data.length; |
- } |
- // "Any other node |
- // "Its number of children." |
- return node.childNodes.length; |
-} |
- |
-/** |
- * Returns the furthest ancestor of a Node as defined by the spec. |
- */ |
-function furthestAncestor(node) { |
- var root = node; |
- while (root.parentNode != null) { |
- root = root.parentNode; |
- } |
- return root; |
-} |
- |
-/** |
- * "The ancestor containers of a Node are the Node itself and all its |
- * ancestors." |
- * |
- * Is node1 an ancestor container of node2? |
- */ |
-function isAncestorContainer(node1, node2) { |
- return node1 == node2 || |
- (node2.compareDocumentPosition(node1) & Node.DOCUMENT_POSITION_CONTAINS); |
-} |
- |
-/** |
- * Returns the first Node that's after node in tree order, or null if node is |
- * the last Node. |
- */ |
-function nextNode(node) { |
- if (node.hasChildNodes()) { |
- return node.firstChild; |
- } |
- return nextNodeDescendants(node); |
-} |
- |
-/** |
- * Returns the last Node that's before node in tree order, or null if node is |
- * the first Node. |
- */ |
-function previousNode(node) { |
- if (node.previousSibling) { |
- node = node.previousSibling; |
- while (node.hasChildNodes()) { |
- node = node.lastChild; |
- } |
- return node; |
- } |
- return node.parentNode; |
-} |
- |
-/** |
- * Returns the next Node that's after node and all its descendants in tree |
- * order, or null if node is the last Node or an ancestor of it. |
- */ |
-function nextNodeDescendants(node) { |
- while (node && !node.nextSibling) { |
- node = node.parentNode; |
- } |
- if (!node) { |
- return null; |
- } |
- return node.nextSibling; |
-} |
- |
-/** |
- * Returns the ownerDocument of the Node, or the Node itself if it's a |
- * Document. |
- */ |
-function ownerDocument(node) { |
- return node.nodeType == Node.DOCUMENT_NODE |
- ? node |
- : node.ownerDocument; |
-} |
- |
-/** |
- * Returns true if ancestor is an ancestor of descendant, false otherwise. |
- */ |
-function isAncestor(ancestor, descendant) { |
- if (!ancestor || !descendant) { |
- return false; |
- } |
- while (descendant && descendant != ancestor) { |
- descendant = descendant.parentNode; |
- } |
- return descendant == ancestor; |
-} |
- |
-/** |
- * Returns true if ancestor is an inclusive ancestor of descendant, false |
- * otherwise. |
- */ |
-function isInclusiveAncestor(ancestor, descendant) { |
- return ancestor === descendant || isAncestor(ancestor, descendant); |
-} |
- |
-/** |
- * Returns true if descendant is a descendant of ancestor, false otherwise. |
- */ |
-function isDescendant(descendant, ancestor) { |
- return isAncestor(ancestor, descendant); |
-} |
- |
-/** |
- * Returns true if descendant is an inclusive descendant of ancestor, false |
- * otherwise. |
- */ |
-function isInclusiveDescendant(descendant, ancestor) { |
- return descendant === ancestor || isDescendant(descendant, ancestor); |
-} |
- |
-/** |
- * The position of two boundary points relative to one another, as defined by |
- * the spec. |
- */ |
-function getPosition(nodeA, offsetA, nodeB, offsetB) { |
- // "If node A is the same as node B, return equal if offset A equals offset |
- // B, before if offset A is less than offset B, and after if offset A is |
- // greater than offset B." |
- if (nodeA == nodeB) { |
- if (offsetA == offsetB) { |
- return "equal"; |
- } |
- if (offsetA < offsetB) { |
- return "before"; |
- } |
- if (offsetA > offsetB) { |
- return "after"; |
- } |
- } |
- |
- // "If node A is after node B in tree order, compute the position of (node |
- // B, offset B) relative to (node A, offset A). If it is before, return |
- // after. If it is after, return before." |
- if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_FOLLOWING) { |
- var pos = getPosition(nodeB, offsetB, nodeA, offsetA); |
- if (pos == "before") { |
- return "after"; |
- } |
- if (pos == "after") { |
- return "before"; |
- } |
- } |
- |
- // "If node A is an ancestor of node B:" |
- if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_CONTAINS) { |
- // "Let child equal node B." |
- var child = nodeB; |
- |
- // "While child is not a child of node A, set child to its parent." |
- while (child.parentNode != nodeA) { |
- child = child.parentNode; |
- } |
- |
- // "If the index of child is less than offset A, return after." |
- if (indexOf(child) < offsetA) { |
- return "after"; |
- } |
- } |
- |
- // "Return before." |
- return "before"; |
-} |
- |
-/** |
- * "contained" as defined by DOM Range: "A Node node is contained in a range |
- * range if node's furthest ancestor is the same as range's root, and (node, 0) |
- * is after range's start, and (node, length of node) is before range's end." |
- */ |
-function isContained(node, range) { |
- var pos1 = getPosition(node, 0, range.startContainer, range.startOffset); |
- var pos2 = getPosition(node, nodeLength(node), range.endContainer, range.endOffset); |
- |
- return furthestAncestor(node) == furthestAncestor(range.startContainer) |
- && pos1 == "after" |
- && pos2 == "before"; |
-} |
- |
-/** |
- * "partially contained" as defined by DOM Range: "A Node is partially |
- * contained in a range if it is an ancestor container of the range's start but |
- * not its end, or vice versa." |
- */ |
-function isPartiallyContained(node, range) { |
- var cond1 = isAncestorContainer(node, range.startContainer); |
- var cond2 = isAncestorContainer(node, range.endContainer); |
- return (cond1 && !cond2) || (cond2 && !cond1); |
-} |
- |
-/** |
- * Index of a node as defined by the spec. |
- */ |
-function indexOf(node) { |
- if (!node.parentNode) { |
- // No preceding sibling nodes, right? |
- return 0; |
- } |
- var i = 0; |
- while (node != node.parentNode.childNodes[i]) { |
- i++; |
- } |
- return i; |
-} |
- |
-/** |
- * extractContents() implementation, following the spec. If an exception is |
- * supposed to be thrown, will return a string with the name (e.g., |
- * "HIERARCHY_REQUEST_ERR") instead of a document fragment. It might also |
- * return an arbitrary human-readable string if a condition is hit that implies |
- * a spec bug. |
- */ |
-function myExtractContents(range) { |
- // "Let frag be a new DocumentFragment whose ownerDocument is the same as |
- // the ownerDocument of the context object's start node." |
- var ownerDoc = range.startContainer.nodeType == Node.DOCUMENT_NODE |
- ? range.startContainer |
- : range.startContainer.ownerDocument; |
- var frag = ownerDoc.createDocumentFragment(); |
- |
- // "If the context object's start and end are the same, abort this method, |
- // returning frag." |
- if (range.startContainer == range.endContainer |
- && range.startOffset == range.endOffset) { |
- return frag; |
- } |
- |
- // "Let original start node, original start offset, original end node, and |
- // original end offset be the context object's start and end nodes and |
- // offsets, respectively." |
- var originalStartNode = range.startContainer; |
- var originalStartOffset = range.startOffset; |
- var originalEndNode = range.endContainer; |
- var originalEndOffset = range.endOffset; |
- |
- // "If original start node is original end node, and they are a Text, |
- // ProcessingInstruction, or Comment node:" |
- if (range.startContainer == range.endContainer |
- && (range.startContainer.nodeType == Node.TEXT_NODE |
- || range.startContainer.nodeType == Node.PROCESSING_INSTRUCTION_NODE |
- || range.startContainer.nodeType == Node.COMMENT_NODE)) { |
- // "Let clone be the result of calling cloneNode(false) on original |
- // start node." |
- var clone = originalStartNode.cloneNode(false); |
- |
- // "Set the data of clone to the result of calling |
- // substringData(original start offset, original end offset − original |
- // start offset) on original start node." |
- clone.data = originalStartNode.substringData(originalStartOffset, |
- originalEndOffset - originalStartOffset); |
- |
- // "Append clone as the last child of frag." |
- frag.appendChild(clone); |
- |
- // "Call deleteData(original start offset, original end offset − |
- // original start offset) on original start node." |
- originalStartNode.deleteData(originalStartOffset, |
- originalEndOffset - originalStartOffset); |
- |
- // "Abort this method, returning frag." |
- return frag; |
- } |
- |
- // "Let common ancestor equal original start node." |
- var commonAncestor = originalStartNode; |
- |
- // "While common ancestor is not an ancestor container of original end |
- // node, set common ancestor to its own parent." |
- while (!isAncestorContainer(commonAncestor, originalEndNode)) { |
- commonAncestor = commonAncestor.parentNode; |
- } |
- |
- // "If original start node is an ancestor container of original end node, |
- // let first partially contained child be null." |
- var firstPartiallyContainedChild; |
- if (isAncestorContainer(originalStartNode, originalEndNode)) { |
- firstPartiallyContainedChild = null; |
- // "Otherwise, let first partially contained child be the first child of |
- // common ancestor that is partially contained in the context object." |
- } else { |
- for (var i = 0; i < commonAncestor.childNodes.length; i++) { |
- if (isPartiallyContained(commonAncestor.childNodes[i], range)) { |
- firstPartiallyContainedChild = commonAncestor.childNodes[i]; |
- break; |
- } |
- } |
- if (!firstPartiallyContainedChild) { |
- throw "Spec bug: no first partially contained child!"; |
- } |
- } |
- |
- // "If original end node is an ancestor container of original start node, |
- // let last partially contained child be null." |
- var lastPartiallyContainedChild; |
- if (isAncestorContainer(originalEndNode, originalStartNode)) { |
- lastPartiallyContainedChild = null; |
- // "Otherwise, let last partially contained child be the last child of |
- // common ancestor that is partially contained in the context object." |
- } else { |
- for (var i = commonAncestor.childNodes.length - 1; i >= 0; i--) { |
- if (isPartiallyContained(commonAncestor.childNodes[i], range)) { |
- lastPartiallyContainedChild = commonAncestor.childNodes[i]; |
- break; |
- } |
- } |
- if (!lastPartiallyContainedChild) { |
- throw "Spec bug: no last partially contained child!"; |
- } |
- } |
- |
- // "Let contained children be a list of all children of common ancestor |
- // that are contained in the context object, in tree order." |
- // |
- // "If any member of contained children is a DocumentType, raise a |
- // HIERARCHY_REQUEST_ERR exception and abort these steps." |
- var containedChildren = []; |
- for (var i = 0; i < commonAncestor.childNodes.length; i++) { |
- if (isContained(commonAncestor.childNodes[i], range)) { |
- if (commonAncestor.childNodes[i].nodeType |
- == Node.DOCUMENT_TYPE_NODE) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- containedChildren.push(commonAncestor.childNodes[i]); |
- } |
- } |
- |
- // "If original start node is an ancestor container of original end node, |
- // set new node to original start node and new offset to original start |
- // offset." |
- var newNode, newOffset; |
- if (isAncestorContainer(originalStartNode, originalEndNode)) { |
- newNode = originalStartNode; |
- newOffset = originalStartOffset; |
- // "Otherwise:" |
- } else { |
- // "Let reference node equal original start node." |
- var referenceNode = originalStartNode; |
- |
- // "While reference node's parent is not null and is not an ancestor |
- // container of original end node, set reference node to its parent." |
- while (referenceNode.parentNode |
- && !isAncestorContainer(referenceNode.parentNode, originalEndNode)) { |
- referenceNode = referenceNode.parentNode; |
- } |
- |
- // "Set new node to the parent of reference node, and new offset to one |
- // plus the index of reference node." |
- newNode = referenceNode.parentNode; |
- newOffset = 1 + indexOf(referenceNode); |
- } |
- |
- // "If first partially contained child is a Text, ProcessingInstruction, or |
- // Comment node:" |
- if (firstPartiallyContainedChild |
- && (firstPartiallyContainedChild.nodeType == Node.TEXT_NODE |
- || firstPartiallyContainedChild.nodeType == Node.PROCESSING_INSTRUCTION_NODE |
- || firstPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) { |
- // "Let clone be the result of calling cloneNode(false) on original |
- // start node." |
- var clone = originalStartNode.cloneNode(false); |
- |
- // "Set the data of clone to the result of calling substringData() on |
- // original start node, with original start offset as the first |
- // argument and (length of original start node − original start offset) |
- // as the second." |
- clone.data = originalStartNode.substringData(originalStartOffset, |
- nodeLength(originalStartNode) - originalStartOffset); |
- |
- // "Append clone as the last child of frag." |
- frag.appendChild(clone); |
- |
- // "Call deleteData() on original start node, with original start |
- // offset as the first argument and (length of original start node − |
- // original start offset) as the second." |
- originalStartNode.deleteData(originalStartOffset, |
- nodeLength(originalStartNode) - originalStartOffset); |
- // "Otherwise, if first partially contained child is not null:" |
- } else if (firstPartiallyContainedChild) { |
- // "Let clone be the result of calling cloneNode(false) on first |
- // partially contained child." |
- var clone = firstPartiallyContainedChild.cloneNode(false); |
- |
- // "Append clone as the last child of frag." |
- frag.appendChild(clone); |
- |
- // "Let subrange be a new Range whose start is (original start node, |
- // original start offset) and whose end is (first partially contained |
- // child, length of first partially contained child)." |
- var subrange = ownerDoc.createRange(); |
- subrange.setStart(originalStartNode, originalStartOffset); |
- subrange.setEnd(firstPartiallyContainedChild, |
- nodeLength(firstPartiallyContainedChild)); |
- |
- // "Let subfrag be the result of calling extractContents() on |
- // subrange." |
- var subfrag = myExtractContents(subrange); |
- |
- // "For each child of subfrag, in order, append that child to clone as |
- // its last child." |
- for (var i = 0; i < subfrag.childNodes.length; i++) { |
- clone.appendChild(subfrag.childNodes[i]); |
- } |
- } |
- |
- // "For each contained child in contained children, append contained child |
- // as the last child of frag." |
- for (var i = 0; i < containedChildren.length; i++) { |
- frag.appendChild(containedChildren[i]); |
- } |
- |
- // "If last partially contained child is a Text, ProcessingInstruction, or |
- // Comment node:" |
- if (lastPartiallyContainedChild |
- && (lastPartiallyContainedChild.nodeType == Node.TEXT_NODE |
- || lastPartiallyContainedChild.nodeType == Node.PROCESSING_INSTRUCTION_NODE |
- || lastPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) { |
- // "Let clone be the result of calling cloneNode(false) on original |
- // end node." |
- var clone = originalEndNode.cloneNode(false); |
- |
- // "Set the data of clone to the result of calling substringData(0, |
- // original end offset) on original end node." |
- clone.data = originalEndNode.substringData(0, originalEndOffset); |
- |
- // "Append clone as the last child of frag." |
- frag.appendChild(clone); |
- |
- // "Call deleteData(0, original end offset) on original end node." |
- originalEndNode.deleteData(0, originalEndOffset); |
- // "Otherwise, if last partially contained child is not null:" |
- } else if (lastPartiallyContainedChild) { |
- // "Let clone be the result of calling cloneNode(false) on last |
- // partially contained child." |
- var clone = lastPartiallyContainedChild.cloneNode(false); |
- |
- // "Append clone as the last child of frag." |
- frag.appendChild(clone); |
- |
- // "Let subrange be a new Range whose start is (last partially |
- // contained child, 0) and whose end is (original end node, original |
- // end offset)." |
- var subrange = ownerDoc.createRange(); |
- subrange.setStart(lastPartiallyContainedChild, 0); |
- subrange.setEnd(originalEndNode, originalEndOffset); |
- |
- // "Let subfrag be the result of calling extractContents() on |
- // subrange." |
- var subfrag = myExtractContents(subrange); |
- |
- // "For each child of subfrag, in order, append that child to clone as |
- // its last child." |
- for (var i = 0; i < subfrag.childNodes.length; i++) { |
- clone.appendChild(subfrag.childNodes[i]); |
- } |
- } |
- |
- // "Set the context object's start and end to (new node, new offset)." |
- range.setStart(newNode, newOffset); |
- range.setEnd(newNode, newOffset); |
- |
- // "Return frag." |
- return frag; |
-} |
- |
-/** |
- * insertNode() implementation, following the spec. If an exception is meant |
- * to be thrown, will return a string with the expected exception name, for |
- * instance "HIERARCHY_REQUEST_ERR". |
- */ |
-function myInsertNode(range, node) { |
- // "If range's start node is a ProcessingInstruction or Comment node, or is |
- // a Text node whose parent is null, or is node, throw an |
- // "HierarchyRequestError" exception and terminate these steps." |
- if (range.startContainer.nodeType == Node.PROCESSING_INSTRUCTION_NODE |
- || range.startContainer.nodeType == Node.COMMENT_NODE |
- || (range.startContainer.nodeType == Node.TEXT_NODE |
- && !range.startContainer.parentNode) |
- || range.startContainer == node) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- // "Let referenceNode be null." |
- var referenceNode = null; |
- |
- // "If range's start node is a Text node, set referenceNode to that Text node." |
- if (range.startContainer.nodeType == Node.TEXT_NODE) { |
- referenceNode = range.startContainer; |
- |
- // "Otherwise, set referenceNode to the child of start node whose index is |
- // start offset, and null if there is no such child." |
- } else { |
- if (range.startOffset < range.startContainer.childNodes.length) { |
- referenceNode = range.startContainer.childNodes[range.startOffset]; |
- } else { |
- referenceNode = null; |
- } |
- } |
- |
- // "Let parent be range's start node if referenceNode is null, and |
- // referenceNode's parent otherwise." |
- var parent_ = referenceNode === null ? range.startContainer : |
- referenceNode.parentNode; |
- |
- // "Ensure pre-insertion validity of node into parent before |
- // referenceNode." |
- var error = ensurePreInsertionValidity(node, parent_, referenceNode); |
- if (error) { |
- return error; |
- } |
- |
- // "If range's start node is a Text node, set referenceNode to the result |
- // of splitting it with offset range's start offset." |
- if (range.startContainer.nodeType == Node.TEXT_NODE) { |
- referenceNode = range.startContainer.splitText(range.startOffset); |
- } |
- |
- // "If node is referenceNode, set referenceNode to its next sibling." |
- if (node == referenceNode) { |
- referenceNode = referenceNode.nextSibling; |
- } |
- |
- // "If node's parent is not null, remove node from its parent." |
- if (node.parentNode) { |
- node.parentNode.removeChild(node); |
- } |
- |
- // "Let newOffset be parent's length if referenceNode is null, and |
- // referenceNode's index otherwise." |
- var newOffset = referenceNode === null ? nodeLength(parent_) : |
- indexOf(referenceNode); |
- |
- // "Increase newOffset by node's length if node is a DocumentFragment node, |
- // and one otherwise." |
- newOffset += node.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? |
- nodeLength(node) : 1; |
- |
- // "Pre-insert node into parent before referenceNode." |
- parent_.insertBefore(node, referenceNode); |
- |
- // "If range's start and end are the same, set range's end to (parent, |
- // newOffset)." |
- if (range.startContainer == range.endContainer |
- && range.startOffset == range.endOffset) { |
- range.setEnd(parent_, newOffset); |
- } |
-} |
- |
-// To make filter() calls more readable |
-function isElement(node) { |
- return node.nodeType == Node.ELEMENT_NODE; |
-} |
- |
-function isText(node) { |
- return node.nodeType == Node.TEXT_NODE; |
-} |
- |
-function isDoctype(node) { |
- return node.nodeType == Node.DOCUMENT_TYPE_NODE; |
-} |
- |
-function ensurePreInsertionValidity(node, parent_, child) { |
- // "If parent is not a Document, DocumentFragment, or Element node, throw a |
- // HierarchyRequestError." |
- if (parent_.nodeType != Node.DOCUMENT_NODE |
- && parent_.nodeType != Node.DOCUMENT_FRAGMENT_NODE |
- && parent_.nodeType != Node.ELEMENT_NODE) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- // "If node is a host-including inclusive ancestor of parent, throw a |
- // HierarchyRequestError." |
- // |
- // XXX Does not account for host |
- if (isInclusiveAncestor(node, parent_)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- // "If child is not null and its parent is not parent, throw a NotFoundError |
- // exception." |
- if (child && child.parentNode != parent_) { |
- return "NOT_FOUND_ERR"; |
- } |
- |
- // "If node is not a DocumentFragment, DocumentType, Element, Text, |
- // ProcessingInstruction, or Comment node, throw a HierarchyRequestError." |
- if (node.nodeType != Node.DOCUMENT_FRAGMENT_NODE |
- && node.nodeType != Node.DOCUMENT_TYPE_NODE |
- && node.nodeType != Node.ELEMENT_NODE |
- && node.nodeType != Node.TEXT_NODE |
- && node.nodeType != Node.PROCESSING_INSTRUCTION_NODE |
- && node.nodeType != Node.COMMENT_NODE) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- // "If either node is a Text node and parent is a document, or node is a |
- // doctype and parent is not a document, throw a HierarchyRequestError." |
- if ((node.nodeType == Node.TEXT_NODE |
- && parent_.nodeType == Node.DOCUMENT_NODE) |
- || (node.nodeType == Node.DOCUMENT_TYPE_NODE |
- && parent_.nodeType != Node.DOCUMENT_NODE)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- // "If parent is a document, and any of the statements below, switched on |
- // node, are true, throw a HierarchyRequestError." |
- if (parent_.nodeType == Node.DOCUMENT_NODE) { |
- switch (node.nodeType) { |
- case Node.DOCUMENT_FRAGMENT_NODE: |
- // "If node has more than one element child or has a Text node |
- // child. Otherwise, if node has one element child and either |
- // parent has an element child, child is a doctype, or child is not |
- // null and a doctype is following child." |
- if ([].filter.call(node.childNodes, isElement).length > 1) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if ([].some.call(node.childNodes, isText)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if ([].filter.call(node.childNodes, isElement).length == 1) { |
- if ([].some.call(parent_.childNodes, isElement)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if (child && child.nodeType == Node.DOCUMENT_TYPE_NODE) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if (child && [].slice.call(parent_.childNodes, indexOf(child) + 1) |
- .filter(isDoctype)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- } |
- break; |
- |
- case Node.ELEMENT_NODE: |
- // "parent has an element child, child is a doctype, or child is |
- // not null and a doctype is following child." |
- if ([].some.call(parent_.childNodes, isElement)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if (child.nodeType == Node.DOCUMENT_TYPE_NODE) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if (child && [].slice.call(parent_.childNodes, indexOf(child) + 1) |
- .filter(isDoctype)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- break; |
- |
- case Node.DOCUMENT_TYPE_NODE: |
- // "parent has a doctype child, an element is preceding child, or |
- // child is null and parent has an element child." |
- if ([].some.call(parent_.childNodes, isDoctype)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if (child && [].slice.call(parent_.childNodes, 0, indexOf(child)) |
- .some(isElement)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- |
- if (!child && [].some.call(parent_.childNodes, isElement)) { |
- return "HIERARCHY_REQUEST_ERR"; |
- } |
- break; |
- } |
- } |
-} |
- |
-/** |
- * Asserts that two nodes are equal, in the sense of isEqualNode(). If they |
- * aren't, tries to print a relatively informative reason why not. TODO: Move |
- * this to testharness.js? |
- */ |
-function assertNodesEqual(actual, expected, msg) { |
- if (!actual.isEqualNode(expected)) { |
- msg = "Actual and expected mismatch for " + msg + ". "; |
- |
- while (actual && expected) { |
- assert_true(actual.nodeType === expected.nodeType |
- && actual.nodeName === expected.nodeName |
- && actual.nodeValue === expected.nodeValue, |
- "First differing node: expected " + format_value(expected) |
- + ", got " + format_value(actual) + " [" + msg + "]"); |
- actual = nextNode(actual); |
- expected = nextNode(expected); |
- } |
- |
- assert_unreached("DOMs were not equal but we couldn't figure out why"); |
- } |
-} |
- |
-/** |
- * Given a DOMException, return the name (e.g., "HIERARCHY_REQUEST_ERR"). |
- */ |
-function getDomExceptionName(e) { |
- var ret = null; |
- for (var prop in e) { |
- if (/^[A-Z_]+_ERR$/.test(prop) && e[prop] == e.code) { |
- return prop; |
- } |
- } |
- |
- throw "Exception seems to not be a DOMException? " + e; |
-} |
- |
-/** |
- * Given an array of endpoint data [start container, start offset, end |
- * container, end offset], returns a Range with those endpoints. |
- */ |
-function rangeFromEndpoints(endpoints) { |
- // If we just use document instead of the ownerDocument of endpoints[0], |
- // WebKit will throw on setStart/setEnd. This is a WebKit bug, but it's in |
- // range, not selection, so we don't want to fail anything for it. |
- var range = ownerDocument(endpoints[0]).createRange(); |
- range.setStart(endpoints[0], endpoints[1]); |
- range.setEnd(endpoints[2], endpoints[3]); |
- return range; |
-} |