diff options
Diffstat (limited to 'dom/imptests/html')
17 files changed, 2222 insertions, 0 deletions
diff --git a/dom/imptests/html/dom/common.js b/dom/imptests/html/dom/common.js new file mode 100644 index 000000000..dc7528a9a --- /dev/null +++ b/dom/imptests/html/dom/common.js @@ -0,0 +1,1087 @@ +"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 selection; +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() { + selection = getSelection(); + 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]", + ]; + + 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) { + // "If the context object's detached flag is set, raise an + // INVALID_STATE_ERR exception and abort these steps." + try { + range.collapsed; + } catch (e) { + return "INVALID_STATE_ERR"; + } + + // "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 and original end node are the same, and they are + // a Text or Comment node:" + if (range.startContainer == range.endContainer + && (range.startContainer.nodeType == Node.TEXT_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 or Comment node:" + if (firstPartiallyContainedChild + && (firstPartiallyContainedChild.nodeType == Node.TEXT_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 or Comment node:" + if (lastPartiallyContainedChild + && (lastPartiallyContainedChild.nodeType == Node.TEXT_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 either a ProcessingInstruction or Comment + // node, or a Text node whose parent is null, 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)) { + 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 + && actual.childNodes.length === expected.childNodes.length, + "First differing node: expected " + format_value(expected) + + ", got " + format_value(actual)); + 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; +} diff --git a/dom/imptests/html/dom/test_interface-objects.html b/dom/imptests/html/dom/test_interface-objects.html new file mode 100644 index 000000000..0e2bf1acd --- /dev/null +++ b/dom/imptests/html/dom/test_interface-objects.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<title>Interfaces</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testInterfaceDeletable(iface) { + test(function() { + assert_true(!!window[iface], "Interface should exist.") + assert_true(delete window[iface], "The delete operator should return true.") + assert_equals(window[iface], undefined, "Interface should be gone.") + }, "Should be able to delete " + iface + ".") +} +var interfaces = [ + "Event", + "CustomEvent", + "EventTarget", + "Node", + "Document", + "DOMImplementation", + "DocumentFragment", + "ProcessingInstruction", + "DocumentType", + "Element", + "Attr", + "CharacterData", + "Text", + "Comment", + "NodeIterator", + "TreeWalker", + "NodeFilter", + "NodeList", + "HTMLCollection", + "DOMStringList", + "DOMTokenList", + ]; +test(function() { + for (var p in window) { + interfaces.forEach(function(i) { + assert_not_equals(p, i) + }) + } +}, "Interface objects properties should not be Enumerable") +interfaces.forEach(testInterfaceDeletable); +</script> diff --git a/dom/imptests/html/dom/test_interfaces.html b/dom/imptests/html/dom/test_interfaces.html new file mode 100644 index 000000000..9299ec8b7 --- /dev/null +++ b/dom/imptests/html/dom/test_interfaces.html @@ -0,0 +1,455 @@ +<!doctype html> +<meta charset=utf-8> +<title>DOM IDL tests</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/resources/WebIDLParser.js></script> +<script src=/resources/idlharness.js></script> + +<h1>DOM IDL tests</h1> +<div id=log></div> + +<script type=text/plain> +[Constructor(DOMString name)] +interface DOMError { + readonly attribute DOMString name; +}; + +[Constructor(DOMString type, optional EventInit eventInitDict)] +interface Event { + readonly attribute DOMString type; + readonly attribute EventTarget? target; + readonly attribute EventTarget? currentTarget; + + const unsigned short NONE = 0; + const unsigned short CAPTURING_PHASE = 1; + const unsigned short AT_TARGET = 2; + const unsigned short BUBBLING_PHASE = 3; + readonly attribute unsigned short eventPhase; + + void stopPropagation(); + void stopImmediatePropagation(); + + readonly attribute boolean bubbles; + readonly attribute boolean cancelable; + void preventDefault(); + readonly attribute boolean defaultPrevented; + + [Unforgeable] readonly attribute boolean isTrusted; + readonly attribute /* DOMTimeStamp */ unsigned long long timeStamp; + + void initEvent(DOMString type, boolean bubbles, boolean cancelable); +}; + +dictionary EventInit { + boolean bubbles = false; + boolean cancelable = false; +}; + +[Constructor(DOMString type, optional CustomEventInit eventInitDict)] +interface CustomEvent : Event { + readonly attribute any detail; + + void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any details); +}; + +dictionary CustomEventInit : EventInit { + any detail = null; +}; + +interface EventTarget { + void addEventListener(DOMString type, EventListener? callback, optional boolean capture); + void removeEventListener(DOMString type, EventListener? callback, optional boolean capture); + boolean dispatchEvent(Event event); +}; + +[Callback] +interface EventListener { + void handleEvent(Event event); +}; + +[NoInterfaceObject] +interface ParentNode { + readonly attribute HTMLCollection children; + readonly attribute Element? firstElementChild; + readonly attribute Element? lastElementChild; + readonly attribute unsigned long childElementCount; + + void prepend((Node or DOMString)... nodes); + void append((Node or DOMString)... nodes); +}; +Document implements ParentNode; +DocumentFragment implements ParentNode; +Element implements ParentNode; + +[NoInterfaceObject] +interface ChildNode { + void before((Node or DOMString)... nodes); + void after((Node or DOMString)... nodes); + void replace((Node or DOMString)... nodes); + void remove(); +}; +DocumentType implements ChildNode; +Element implements ChildNode; +CharacterData implements ChildNode; + +[NoInterfaceObject] +interface NonDocumentTypeChildNode { + readonly attribute Element? previousElementSibling; + readonly attribute Element? nextElementSibling; +}; +Element implements NonDocumentTypeChildNode; +CharacterData implements NonDocumentTypeChildNode; + +[Constructor(MutationCallback callback)] +interface MutationObserver { + void observe(Node target, MutationObserverInit options); + void disconnect(); + sequence<MutationRecord> takeRecords(); +}; + +callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer); + +dictionary MutationObserverInit { + boolean childList = false; + boolean attributes = false; + boolean characterData = false; + boolean subtree = false; + boolean attributeOldValue = false; + boolean characterDataOldValue = false; + sequence<DOMString> attributeFilter; +}; + +interface MutationRecord { + readonly attribute DOMString type; + readonly attribute Node target; + readonly attribute NodeList addedNodes; + readonly attribute NodeList removedNodes; + readonly attribute Node? previousSibling; + readonly attribute Node? nextSibling; + readonly attribute DOMString? attributeName; + readonly attribute DOMString? attributeNamespace; + readonly attribute DOMString? oldValue; +}; + +interface Node : EventTarget { + const unsigned short ELEMENT_NODE = 1; + const unsigned short ATTRIBUTE_NODE = 2; // historical + const unsigned short TEXT_NODE = 3; + const unsigned short CDATA_SECTION_NODE = 4; // historical + const unsigned short ENTITY_REFERENCE_NODE = 5; // historical + const unsigned short ENTITY_NODE = 6; // historical + const unsigned short PROCESSING_INSTRUCTION_NODE = 7; + const unsigned short COMMENT_NODE = 8; + const unsigned short DOCUMENT_NODE = 9; + const unsigned short DOCUMENT_TYPE_NODE = 10; + const unsigned short DOCUMENT_FRAGMENT_NODE = 11; + const unsigned short NOTATION_NODE = 12; // historical + readonly attribute unsigned short nodeType; + readonly attribute DOMString nodeName; + + readonly attribute DOMString? baseURI; + + readonly attribute Document? ownerDocument; + readonly attribute Node? parentNode; + readonly attribute Element? parentElement; + boolean hasChildNodes(); + readonly attribute NodeList childNodes; + readonly attribute Node? firstChild; + readonly attribute Node? lastChild; + readonly attribute Node? previousSibling; + readonly attribute Node? nextSibling; + + attribute DOMString? nodeValue; + attribute DOMString? textContent; + void normalize(); + + Node cloneNode(optional boolean deep); + boolean isEqualNode(Node? node); + + const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01; + const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02; + const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04; + const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08; + const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10; + const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; + unsigned short compareDocumentPosition(Node other); + boolean contains(Node? other); + + DOMString? lookupPrefix(DOMString? namespace); + DOMString? lookupNamespaceURI(DOMString? prefix); + boolean isDefaultNamespace(DOMString? namespace); + + Node insertBefore(Node node, Node? child); + Node appendChild(Node node); + Node replaceChild(Node node, Node child); + Node removeChild(Node child); +}; + +[Constructor] +interface Document : Node { + readonly attribute DOMImplementation implementation; + readonly attribute DOMString URL; + readonly attribute DOMString documentURI; + readonly attribute DOMString compatMode; + readonly attribute DOMString characterSet; + readonly attribute DOMString contentType; + + readonly attribute DocumentType? doctype; + readonly attribute Element? documentElement; + HTMLCollection getElementsByTagName(DOMString localName); + HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); + HTMLCollection getElementsByClassName(DOMString classNames); + Element? getElementById(DOMString elementId); + + Element createElement(DOMString localName); + Element createElementNS(DOMString? namespace, DOMString qualifiedName); + DocumentFragment createDocumentFragment(); + Text createTextNode(DOMString data); + Comment createComment(DOMString data); + ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data); + + Node importNode(Node node, optional boolean deep); + Node adoptNode(Node node); + + Event createEvent(DOMString interface); + + Range createRange(); + + // NodeFilter.SHOW_ALL = 0xFFFFFFFF + NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow, optional NodeFilter? filter); + TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow, optional NodeFilter? filter); +}; + +interface XMLDocument : Document {}; + +interface DOMImplementation { + DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId); + XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null); + Document createHTMLDocument(optional DOMString title); + + boolean hasFeature(DOMString feature, [TreatNullAs=EmptyString] DOMString version); +}; + +[Constructor] +interface DocumentFragment : Node { +}; + +interface DocumentType : Node { + readonly attribute DOMString name; + readonly attribute DOMString publicId; + readonly attribute DOMString systemId; +}; + +interface Element : Node { + readonly attribute DOMString? namespaceURI; + readonly attribute DOMString? prefix; + readonly attribute DOMString localName; + readonly attribute DOMString tagName; + + attribute DOMString id; + attribute DOMString className; + [PutForwards=value] + readonly attribute DOMTokenList classList; + + readonly attribute Attr[] attributes; + DOMString? getAttribute(DOMString name); + DOMString? getAttributeNS(DOMString? namespace, DOMString localName); + void setAttribute(DOMString name, DOMString value); + void setAttributeNS(DOMString? namespace, DOMString name, DOMString value); + void removeAttribute(DOMString name); + void removeAttributeNS(DOMString? namespace, DOMString localName); + boolean hasAttribute(DOMString name); + boolean hasAttributeNS(DOMString? namespace, DOMString localName); + + HTMLCollection getElementsByTagName(DOMString localName); + HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); + HTMLCollection getElementsByClassName(DOMString classNames); +}; + +interface Attr { + readonly attribute DOMString localName; + attribute DOMString value; + + readonly attribute DOMString name; + readonly attribute DOMString? namespaceURI; + readonly attribute DOMString? prefix; +}; + +interface CharacterData : Node { + [TreatNullAs=EmptyString] attribute DOMString data; + readonly attribute unsigned long length; + DOMString substringData(unsigned long offset, unsigned long count); + void appendData(DOMString data); + void insertData(unsigned long offset, DOMString data); + void deleteData(unsigned long offset, unsigned long count); + void replaceData(unsigned long offset, unsigned long count, DOMString data); +}; + +[Constructor(optional DOMString data)] +interface Text : CharacterData { + Text splitText(unsigned long offset); + readonly attribute DOMString wholeText; +}; + +interface ProcessingInstruction : CharacterData { + readonly attribute DOMString target; +}; + +[Constructor(optional DOMString data)] +interface Comment : CharacterData { +}; + +[Constructor] +interface Range { + readonly attribute Node startContainer; + readonly attribute unsigned long startOffset; + readonly attribute Node endContainer; + readonly attribute unsigned long endOffset; + readonly attribute boolean collapsed; + readonly attribute Node commonAncestorContainer; + + void setStart(Node refNode, unsigned long offset); + void setEnd(Node refNode, unsigned long offset); + void setStartBefore(Node refNode); + void setStartAfter(Node refNode); + void setEndBefore(Node refNode); + void setEndAfter(Node refNode); + void collapse(optional boolean toStart = false); + void selectNode(Node refNode); + void selectNodeContents(Node refNode); + + const unsigned short START_TO_START = 0; + const unsigned short START_TO_END = 1; + const unsigned short END_TO_END = 2; + const unsigned short END_TO_START = 3; + short compareBoundaryPoints(unsigned short how, Range sourceRange); + + void deleteContents(); + DocumentFragment extractContents(); + DocumentFragment cloneContents(); + void insertNode(Node node); + void surroundContents(Node newParent); + + Range cloneRange(); + void detach(); + + boolean isPointInRange(Node node, unsigned long offset); + short comparePoint(Node node, unsigned long offset); + + boolean intersectsNode(Node node); + + stringifier; +}; + +interface NodeIterator { + readonly attribute Node root; + readonly attribute Node? referenceNode; + readonly attribute boolean pointerBeforeReferenceNode; + readonly attribute unsigned long whatToShow; + readonly attribute NodeFilter? filter; + + Node? nextNode(); + Node? previousNode(); + + void detach(); +}; + +interface TreeWalker { + readonly attribute Node root; + readonly attribute unsigned long whatToShow; + readonly attribute NodeFilter? filter; + attribute Node currentNode; + + Node? parentNode(); + Node? firstChild(); + Node? lastChild(); + Node? previousSibling(); + Node? nextSibling(); + Node? previousNode(); + Node? nextNode(); +}; + +[Callback] +interface NodeFilter { + // Constants for acceptNode() + const unsigned short FILTER_ACCEPT = 1; + const unsigned short FILTER_REJECT = 2; + const unsigned short FILTER_SKIP = 3; + + // Constants for whatToShow + const unsigned long SHOW_ALL = 0xFFFFFFFF; + const unsigned long SHOW_ELEMENT = 0x1; + const unsigned long SHOW_ATTRIBUTE = 0x2; // historical + const unsigned long SHOW_TEXT = 0x4; + const unsigned long SHOW_CDATA_SECTION = 0x8; // historical + const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical + const unsigned long SHOW_ENTITY = 0x20; // historical + const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40; + const unsigned long SHOW_COMMENT = 0x80; + const unsigned long SHOW_DOCUMENT = 0x100; + const unsigned long SHOW_DOCUMENT_TYPE = 0x200; + const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400; + const unsigned long SHOW_NOTATION = 0x800; // historical + + unsigned short acceptNode(Node node); +}; + +[ArrayClass] +interface NodeList { + getter Node? item(unsigned long index); + readonly attribute unsigned long length; +}; + +interface HTMLCollection { + readonly attribute unsigned long length; + getter Element? item(unsigned long index); + getter object? namedItem(DOMString name); // only returns Element +}; + +interface DOMTokenList { + readonly attribute unsigned long length; + getter DOMString? item(unsigned long index); + boolean contains(DOMString token); + void add(DOMString... tokens); + void remove(DOMString... tokens); + boolean toggle(DOMString token, optional boolean force); + stringifier; + attribute DOMString value; +}; +</script> +<script> +"use strict"; +var xmlDoc, detachedRange, element; +var idlArray; +setup(function() { + xmlDoc = document.implementation.createDocument(null, "", null); + detachedRange = document.createRange(); + detachedRange.detach(); + element = xmlDoc.createElementNS(null, "test"); + element.setAttribute("bar", "baz"); + + idlArray = new IdlArray(); + idlArray.add_idls(document.querySelector("script[type=text\\/plain]").textContent); + idlArray.add_objects({ + Event: ['document.createEvent("Event")', 'new Event("foo")'], + CustomEvent: ['new CustomEvent("foo")'], + XMLDocument: ['xmlDoc'], + DOMImplementation: ['document.implementation'], + DocumentFragment: ['document.createDocumentFragment()'], + DocumentType: ['document.doctype'], + Element: ['element'], + Attr: ['document.querySelector("[id]").attributes[0]'], + Text: ['document.createTextNode("abc")'], + ProcessingInstruction: ['xmlDoc.createProcessingInstruction("abc", "def")'], + Comment: ['document.createComment("abc")'], + Range: ['document.createRange()', 'detachedRange'], + NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)'], + TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)'], + NodeList: ['document.querySelectorAll("script")'], + HTMLCollection: ['document.body.children'], + DOMTokenList: ['document.body.classList'], + }); +}); +idlArray.test(); +</script> diff --git a/dom/imptests/html/html/browsers/the-window-object/test_window-named-properties.html b/dom/imptests/html/html/browsers/the-window-object/test_window-named-properties.html new file mode 100644 index 000000000..b01e24da9 --- /dev/null +++ b/dom/imptests/html/html/browsers/the-window-object/test_window-named-properties.html @@ -0,0 +1,69 @@ +<!doctype html> +<meta charset=utf-8> +<title>Changes to named properties of the window object</title> +<link rel="author" title="Ms2ger" href="ms2ger@gmail.com"> +<link rel="author" title="Boris Zbarsky" href="bzbarsky@mit.edu"> +<link rel="help" href="http://www.whatwg.org/html/#window"> +<link rel="help" href="http://www.whatwg.org/html/#dom-window-nameditem"> +<link rel="help" href="http://dev.w3.org/2006/webapi/WebIDL/#named-properties-object"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<iframe name="bar"></iframe> +<iframe name="constructor"></iframe> +<script> +function assert_data_propdesc(pd, Writable, Enumerable, Configurable) { + assert_equals(typeof pd, "object"); + assert_equals(pd.writable, Writable); + assert_equals(pd.enumerable, Enumerable); + assert_equals(pd.configurable, Configurable); +} +test(function() { + assert_true("bar" in window, "bar not in window"); + assert_equals(window["bar"], + document.getElementsByTagName("iframe")[0].contentWindow); +}, "Static name"); +test(function() { + assert_true("bar" in Window.prototype, "bar in Window.prototype"); + assert_false(Window.prototype.hasOwnProperty("bar"), "Window.prototype.hasOwnProperty(\"bar\")"); + + var gsp = Object.getPrototypeOf(Object.getPrototypeOf(window)); + assert_true("bar" in gsp, "bar in gsp"); + assert_true(gsp.hasOwnProperty("bar"), "gsp.hasOwnProperty(\"bar\")"); + assert_data_propdesc(Object.getOwnPropertyDescriptor(gsp, "bar"), + true, false, true); +}, "Static name on the prototype"); +test(function() { + assert_equals(window.constructor, Window); + assert_false(window.hasOwnProperty("constructor"), "window.constructor should not be an own property."); + + var proto = Object.getPrototypeOf(window); + assert_equals(proto.constructor, Window); + assert_true("constructor" in proto, "constructor in proto"); + assert_data_propdesc(Object.getOwnPropertyDescriptor(proto, "constructor"), + true, false, true); + + var gsp = Object.getPrototypeOf(proto); + assert_true("constructor" in gsp, "constructor in gsp"); + assert_false(gsp.hasOwnProperty("constructor"), "gsp.hasOwnProperty(\"constructor\")"); + assert_equals(Object.getOwnPropertyDescriptor(gsp, "constructor"), undefined) +}, "constructor"); +var t = async_test("Dynamic name") +var t2 = async_test("Ghost name") +t.step(function() { + var iframe = document.getElementsByTagName("iframe")[0]; + iframe.setAttribute("src", "data:text/html,<script>window.name='foo'<\/script>"); + iframe.onload = function() { + t.step(function() { + assert_true("foo" in window, "foo not in window"); + assert_equals(window["foo"], iframe.contentWindow); + }); + t.done(); + t2.step(function() { + assert_false("bar" in window, "bar still in window"); + assert_equals(window["bar"], undefined); + }); + t2.done(); + }; +}); +</script> diff --git a/dom/imptests/html/html/dom/documents/dta/test_nameditem-06.html b/dom/imptests/html/html/dom/documents/dta/test_nameditem-06.html new file mode 100644 index 000000000..3fd3d474a --- /dev/null +++ b/dom/imptests/html/html/dom/documents/dta/test_nameditem-06.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Named items: imgs</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<link rel="help" href="http://www.whatwg.org/html/#dom-document-nameditem"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<div id="test"> +<img name=test1> + +<img name=test2> +<img name=test2> + +<img id=test3> + +<img id=test4> +<img id=test4> + +<img name=test5> +<img id=test5> + +<img id=test6> +<img name=test6> + +<img id=test7 name=fail> + +<img name=test8 id=fail> +</div> +<script> +test(function() { + var img = document.getElementsByTagName("img")[0]; + assert_equals(img.name, "test1"); + + assert_true("test1" in document, '"test1" in document should be true'); + assert_equals(document.test1, img); +}, "If there is one img, it should be returned (name)"); + +test(function() { + var img1 = document.getElementsByTagName("img")[1]; + assert_equals(img1.name, "test2"); + var img2 = document.getElementsByTagName("img")[2]; + assert_equals(img2.name, "test2"); + + assert_true("test2" in document, '"test2" in document should be true'); + var collection = document.test2; + assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection"); + assert_array_equals(collection, [img1, img2]); +}, "If there are two imgs, a collection should be returned. (name)"); + +test(function() { + var img = document.getElementsByTagName("img")[3]; + assert_equals(img.id, "test3"); + + assert_false("test3" in document, '"test3" in document should be false'); + assert_equals(document.test3, undefined); +}, "If there is one img, it should not be returned (id)"); + +test(function() { + var img1 = document.getElementsByTagName("img")[4]; + assert_equals(img1.id, "test4"); + var img2 = document.getElementsByTagName("img")[5]; + assert_equals(img2.id, "test4"); + + assert_false("test4" in document, '"test4" in document should be false'); + assert_equals(document.test4, undefined); +}, "If there are two imgs, nothing should be returned. (id)"); + +test(function() { + var img1 = document.getElementsByTagName("img")[6]; + assert_equals(img1.name, "test5"); + var img2 = document.getElementsByTagName("img")[7]; + assert_equals(img2.id, "test5"); + + assert_true("test5" in document, '"test5" in document should be true'); + assert_equals(document.test5, img1); +}, "If there are two imgs, the one with a name should be returned. (name and id)"); + +test(function() { + var img1 = document.getElementsByTagName("img")[8]; + assert_equals(img1.id, "test6"); + var img2 = document.getElementsByTagName("img")[9]; + assert_equals(img2.name, "test6"); + + assert_true("test6" in document, '"test6" in document should be true'); + assert_equals(document.test6, img2); +}, "If there are two imgs, the one with a name should be returned. (id and name)"); + +test(function() { + var img = document.getElementsByTagName("img")[10]; + assert_equals(img.id, "test7"); + + assert_true("test7" in document, '"test7" in document should be true'); + assert_equals(document.test7, img); +}, "A name should affect getting an img by id"); + +test(function() { + var img = document.getElementsByTagName("img")[11]; + assert_equals(img.name, "test8"); + + assert_true("test8" in document, '"test8" in document should be true'); + assert_equals(document.test8, img); +}, "An id shouldn't affect getting an img by name"); +</script> diff --git a/dom/imptests/html/html/dom/elements/global-attributes/reftest-stylo.list b/dom/imptests/html/html/dom/elements/global-attributes/reftest-stylo.list new file mode 100644 index 000000000..4e76b8532 --- /dev/null +++ b/dom/imptests/html/html/dom/elements/global-attributes/reftest-stylo.list @@ -0,0 +1,59 @@ +# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing +# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT + +== dir_auto-contained-bdi-L.html dir_auto-contained-bdi-L.html +== dir_auto-contained-bdi-R.html dir_auto-contained-bdi-R.html +== dir_auto-contained-dir_auto-L.html dir_auto-contained-dir_auto-L.html +== dir_auto-contained-dir_auto-R.html dir_auto-contained-dir_auto-R.html +== dir_auto-contained-dir-L.html dir_auto-contained-dir-L.html +== dir_auto-contained-dir-R.html dir_auto-contained-dir-R.html +== dir_auto-contained-L.html dir_auto-contained-L.html +== dir_auto-contained-R.html dir_auto-contained-R.html +== dir_auto-contained-script-L.html dir_auto-contained-script-L.html +== dir_auto-contained-script-R.html dir_auto-contained-script-R.html +== dir_auto-contained-style-L.html dir_auto-contained-style-L.html +== dir_auto-contained-style-R.html dir_auto-contained-style-R.html +== dir_auto-contained-textarea-L.html dir_auto-contained-textarea-L.html +== dir_auto-contained-textarea-R.html dir_auto-contained-textarea-R.html +== dir_auto-EN-L.html dir_auto-EN-L.html +== dir_auto-EN-R.html dir_auto-EN-R.html +== dir_auto-input-EN-L.html dir_auto-input-EN-L.html +== dir_auto-input-EN-R.html dir_auto-input-EN-R.html +== dir_auto-input-L.html dir_auto-input-L.html +== dir_auto-input-N-EN.html dir_auto-input-N-EN.html +== dir_auto-input-N-EN-L.html dir_auto-input-N-EN-L.html +== dir_auto-input-N-EN-R.html dir_auto-input-N-EN-R.html +== dir_auto-input-N-L.html dir_auto-input-N-L.html +== dir_auto-input-N-R.html dir_auto-input-N-R.html +== dir_auto-input-R.html dir_auto-input-R.html +== dir_auto-input-script-EN-L.html dir_auto-input-script-EN-L.html +== dir_auto-input-script-EN-R.html dir_auto-input-script-EN-R.html +== dir_auto-input-script-L.html dir_auto-input-script-L.html +== dir_auto-input-script-N-EN.html dir_auto-input-script-N-EN.html +== dir_auto-input-script-N-EN-L.html dir_auto-input-script-N-EN-L.html +== dir_auto-input-script-N-EN-R.html dir_auto-input-script-N-EN-R.html +== dir_auto-input-script-N-L.html dir_auto-input-script-N-L.html +== dir_auto-input-script-N-R.html dir_auto-input-script-N-R.html +== dir_auto-input-script-R.html dir_auto-input-script-R.html +== dir_auto-isolate.html dir_auto-isolate.html +== dir_auto-L.html dir_auto-L.html +== dir_auto-N-EN.html dir_auto-N-EN.html +== dir_auto-N-EN-L.html dir_auto-N-EN-L.html +== dir_auto-N-EN-R.html dir_auto-N-EN-R.html +== dir_auto-N-L.html dir_auto-N-L.html +== dir_auto-N-R.html dir_auto-N-R.html +== dir_auto-pre-mixed.html dir_auto-pre-mixed.html +== dir_auto-pre-N-between-Rs.html dir_auto-pre-N-between-Rs.html +== dir_auto-pre-N-EN.html dir_auto-pre-N-EN.html +== dir_auto-R.html dir_auto-R.html +== dir_auto-textarea-mixed.html dir_auto-textarea-mixed.html +fails-if(B2G||Mulet||(Android&&asyncPan)) == dir_auto-textarea-N-between-Rs.html dir_auto-textarea-N-between-Rs.html +# B2G scrollbar on opposite side +== dir_auto-textarea-N-EN.html dir_auto-textarea-N-EN.html +== dir_auto-textarea-script-mixed.html dir_auto-textarea-script-mixed.html +fails-if(B2G||Mulet||(Android&&asyncPan)) == dir_auto-textarea-script-N-between-Rs.html dir_auto-textarea-script-N-between-Rs.html +# B2G scrollbar on reference only +== dir_auto-textarea-script-N-EN.html dir_auto-textarea-script-N-EN.html +== lang-xyzzy.html lang-xyzzy.html +== lang-xmllang-01.html lang-xmllang-01.html +== style-01.html style-01.html diff --git a/dom/imptests/html/html/dom/elements/global-attributes/reftest.list b/dom/imptests/html/html/dom/elements/global-attributes/reftest.list new file mode 100644 index 000000000..a58929e92 --- /dev/null +++ b/dom/imptests/html/html/dom/elements/global-attributes/reftest.list @@ -0,0 +1,56 @@ +# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT + +== dir_auto-contained-bdi-L.html dir_auto-contained-bdi-L-ref.html +== dir_auto-contained-bdi-R.html dir_auto-contained-bdi-R-ref.html +== dir_auto-contained-dir_auto-L.html dir_auto-contained-dir_auto-L-ref.html +== dir_auto-contained-dir_auto-R.html dir_auto-contained-dir_auto-R-ref.html +== dir_auto-contained-dir-L.html dir_auto-contained-dir-L-ref.html +== dir_auto-contained-dir-R.html dir_auto-contained-dir-R-ref.html +== dir_auto-contained-L.html dir_auto-contained-L-ref.html +== dir_auto-contained-R.html dir_auto-contained-R-ref.html +== dir_auto-contained-script-L.html dir_auto-contained-script-L-ref.html +== dir_auto-contained-script-R.html dir_auto-contained-script-R-ref.html +== dir_auto-contained-style-L.html dir_auto-contained-style-L-ref.html +== dir_auto-contained-style-R.html dir_auto-contained-style-R-ref.html +== dir_auto-contained-textarea-L.html dir_auto-contained-textarea-L-ref.html +== dir_auto-contained-textarea-R.html dir_auto-contained-textarea-R-ref.html +== dir_auto-EN-L.html dir_auto-EN-L-ref.html +== dir_auto-EN-R.html dir_auto-EN-R-ref.html +== dir_auto-input-EN-L.html dir_auto-input-EN-L-ref.html +== dir_auto-input-EN-R.html dir_auto-input-EN-R-ref.html +== dir_auto-input-L.html dir_auto-input-L-ref.html +== dir_auto-input-N-EN.html dir_auto-input-N-EN-ref.html +== dir_auto-input-N-EN-L.html dir_auto-input-N-EN-L-ref.html +== dir_auto-input-N-EN-R.html dir_auto-input-N-EN-R-ref.html +== dir_auto-input-N-L.html dir_auto-input-N-L-ref.html +== dir_auto-input-N-R.html dir_auto-input-N-R-ref.html +== dir_auto-input-R.html dir_auto-input-R-ref.html +== dir_auto-input-script-EN-L.html dir_auto-input-script-EN-L-ref.html +== dir_auto-input-script-EN-R.html dir_auto-input-script-EN-R-ref.html +== dir_auto-input-script-L.html dir_auto-input-script-L-ref.html +== dir_auto-input-script-N-EN.html dir_auto-input-script-N-EN-ref.html +== dir_auto-input-script-N-EN-L.html dir_auto-input-script-N-EN-L-ref.html +== dir_auto-input-script-N-EN-R.html dir_auto-input-script-N-EN-R-ref.html +== dir_auto-input-script-N-L.html dir_auto-input-script-N-L-ref.html +== dir_auto-input-script-N-R.html dir_auto-input-script-N-R-ref.html +== dir_auto-input-script-R.html dir_auto-input-script-R-ref.html +== dir_auto-isolate.html dir_auto-isolate-ref.html +== dir_auto-L.html dir_auto-L-ref.html +== dir_auto-N-EN.html dir_auto-N-EN-ref.html +== dir_auto-N-EN-L.html dir_auto-N-EN-L-ref.html +== dir_auto-N-EN-R.html dir_auto-N-EN-R-ref.html +== dir_auto-N-L.html dir_auto-N-L-ref.html +== dir_auto-N-R.html dir_auto-N-R-ref.html +== dir_auto-pre-mixed.html dir_auto-pre-mixed-ref.html +== dir_auto-pre-N-between-Rs.html dir_auto-pre-N-between-Rs-ref.html +== dir_auto-pre-N-EN.html dir_auto-pre-N-EN-ref.html +== dir_auto-R.html dir_auto-R-ref.html +== dir_auto-textarea-mixed.html dir_auto-textarea-mixed-ref.html +fails-if(Android&&asyncPan) == dir_auto-textarea-N-between-Rs.html dir_auto-textarea-N-between-Rs-ref.html +== dir_auto-textarea-N-EN.html dir_auto-textarea-N-EN-ref.html +== dir_auto-textarea-script-mixed.html dir_auto-textarea-script-mixed-ref.html +fails-if(Android&&asyncPan) == dir_auto-textarea-script-N-between-Rs.html dir_auto-textarea-script-N-between-Rs-ref.html +== dir_auto-textarea-script-N-EN.html dir_auto-textarea-script-N-EN-ref.html +== lang-xyzzy.html lang-xyzzy-ref.html +== lang-xmllang-01.html lang-xmllang-01-ref.html +== style-01.html style-01-ref.html diff --git a/dom/imptests/html/js/builtins/test_WeakMap.prototype-properties.html b/dom/imptests/html/js/builtins/test_WeakMap.prototype-properties.html new file mode 100644 index 000000000..0bdb6bb86 --- /dev/null +++ b/dom/imptests/html/js/builtins/test_WeakMap.prototype-properties.html @@ -0,0 +1,103 @@ +<!doctype html> +<title>WeakMap.prototype</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.15.5> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +function assert_propdesc(obj, prop, Writable, Enumerable, Configurable) { + var propdesc = Object.getOwnPropertyDescriptor(obj, prop); + assert_equals(typeof propdesc, "object"); + assert_equals(propdesc.writable, Writable, "[[Writable]]"); + assert_equals(propdesc.enumerable, Enumerable, "[[Enumerable]]"); + assert_equals(propdesc.configurable, Configurable, "[[Configurable]]"); +} + +function test_length(fun, expected) { + test(function() { + assert_propdesc(WeakMap.prototype[fun], "length", false, false, false); + assert_equals(WeakMap.prototype[fun].length, expected); + }, "WeakMap.prototype." + fun + ".length") +} + +function test_thisval(fun, args) { + // Step 1-2 + test(function() { + assert_throws(new TypeError(), function() { + WeakMap.prototype[fun].apply(null, args); + }); + assert_throws(new TypeError(), function() { + WeakMap.prototype[fun].apply(undefined, args); + }); + }, "WeakMap.prototype." + fun + ": ToObject on this") + // Step 3 + test(function() { + assert_throws(new TypeError(), function() { + WeakMap.prototype[fun].apply({}, args); + }); + }, "WeakMap.prototype." + fun + ": this has no [[WeakMapData]] internal property") +} + +// In every case, the length property of a built-in Function object described +// in this clause has the attributes { [[Writable]]: false, [[Enumerable]]: +// false, [[Configurable]]: false }. Every other property described in this +// clause has the attributes { [[Writable]]: true, [[Enumerable]]: false, +// [[Configurable]]: true } unless otherwise specified. + +test(function() { + assert_equals(Object.getPrototypeOf(WeakMap.prototype), Object.prototype); +}, "The value of the [[Prototype]] internal property of the WeakMap prototype object is the standard built-in Object prototype object (15.2.4).") + +// 15.15.5.1 WeakMap.prototype.constructor +test(function() { + assert_equals(WeakMap.prototype.constructor, WeakMap); + assert_propdesc(WeakMap.prototype, "constructor", true, false, true); +}, "The initial value of WeakMap.prototype.constructor is the built-in WeakMap constructor.") + +// 15.15.5.2 WeakMap.prototype.delete ( key ) +test(function() { + assert_propdesc(WeakMap.prototype, "delete", true, false, true); + test_length("delete", 1); + // Step 1-3 + test_thisval("delete", [{}]); +}, "WeakMap.prototype.delete") + +// 15.15.5.3 WeakMap.prototype.get ( key ) +test(function() { + assert_propdesc(WeakMap.prototype, "get", true, false, true); + test_length("get", 1); + // Step 1-3 + test_thisval("get", [{}]); + + // Step 8 + test(function() { + var wm = new WeakMap(); + var key = {}; + var res = wm.get({}, {}); + assert_equals(res, undefined); + }, "WeakMap.prototype.get: return undefined"); +}, "WeakMap.prototype.get") + +// 15.14.5.4 Map.prototype.has ( key ) +test(function() { + assert_propdesc(WeakMap.prototype, "has", true, false, true); + test_length("has", 1); + // Step 1-3 + test_thisval("has", [{}]); +}, "WeakMap.prototype.has") + +// 15.14.5.5 Map.prototype.set ( key , value ) +test(function() { + assert_propdesc(WeakMap.prototype, "set", true, false, true); + test_length("set", 2); + // Step 1-3 + test_thisval("set", [{}, {}]); +}, "WeakMap.prototype.set") + +// 15.15.5.6 Map.prototype.@@toStringTag +test(function() { + assert_class_string(new WeakMap(), "WeakMap"); + assert_class_string(WeakMap.prototype, "WeakMap"); +}, "WeakMap.prototype.@@toStringTag") +</script> diff --git a/dom/imptests/html/mochitest.ini b/dom/imptests/html/mochitest.ini new file mode 100644 index 000000000..87b958f0e --- /dev/null +++ b/dom/imptests/html/mochitest.ini @@ -0,0 +1,24 @@ +# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT +[DEFAULT] +support-files = + webgl/common.js + +[typedarrays/test_constructors.html] +[webgl/test_bufferSubData.html] +subsuite = gpu +skip-if = toolkit == 'android' #android(WebGL) +[webgl/test_compressedTexImage2D.html] +subsuite = gpu +skip-if = toolkit == 'android' #android(WebGL) +[webgl/test_compressedTexSubImage2D.html] +subsuite = gpu +skip-if = true # Bug 1226336 +[webgl/test_texImage2D.html] +subsuite = gpu +skip-if = toolkit == 'android' #android(WebGL) +[webgl/test_texSubImage2D.html] +subsuite = gpu +skip-if = toolkit == 'android' #android(WebGL) +[webgl/test_uniformMatrixNfv.html] +subsuite = gpu +skip-if = toolkit == 'android' #android(WebGL) diff --git a/dom/imptests/html/typedarrays/test_constructors.html b/dom/imptests/html/typedarrays/test_constructors.html new file mode 100644 index 000000000..60e0dc8fe --- /dev/null +++ b/dom/imptests/html/typedarrays/test_constructors.html @@ -0,0 +1,48 @@ +<!doctype html> +<title>Typed Array constructors</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=https://www.khronos.org/registry/typedarray/specs/latest/#7> +<link rel=help href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-overload-resolution-algorithm> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> + +<div id=log></div> +<script> +var args = [ + /* numbers */ + [NaN, 0], [+Infinity, 0], [-Infinity, 0], [+0, 0], [-0, 0], // Step 2 + [-0.4, 0], [-0.9, 0], [1.1, 1], [2.9, 2], // Step 3 + [1, 1], [-0xF1000000, 0xF000000], // Step 4 + /* strings */ + ["1", 1], ["1e2", 100], + /* null, undefined, booleans */ + [undefined, 0], [null, 0], [false, 0], [true, 1], + /* objects */ + [{}, 0], [{ length: 2, 0: 0, 1: 0 }, 0], [[0, 0], 2] +]; +var interfaces = [ + "Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", + "Int32Array", "Uint32Array", "Float32Array", "Float64Array" +]; + +test(function() { + interfaces.concat(["ArrayBuffer", "DataView"]).forEach(function(i) { + test(function() { + // XXX The spec is wrong here. + assert_throws(new TypeError(), function() { + new window[i](); + }); + }, "Constructing interface " + i + " with no arguments should throw."); + }); + interfaces.forEach(function(i) { + args.forEach(function(arg, j) { + var input = arg[0], expected = arg[1]; + test(function() { + var ta = new window[i](input); + assert_equals(ta.length, expected); + }, "The argument " + format_value(input) + " (" + j + ") should be interpreted as " + + expected + " for interface " + i + "."); + }); + }); +}); +</script> diff --git a/dom/imptests/html/webgl/common.js b/dom/imptests/html/webgl/common.js new file mode 100644 index 000000000..416c21ce9 --- /dev/null +++ b/dom/imptests/html/webgl/common.js @@ -0,0 +1,13 @@ +function getGl() { + var c = document.createElement("canvas"); + var gl = c.getContext("experimental-webgl"); + assert_true(!!gl, "Should be able to get a context."); + return gl; +} + +function shouldGenerateGLError(cx, glError, fn) { + test(function() { + fn(); + assert_equals(cx.getError(), glError); + }, "Calling " + fn + " should generate a " + glError + " error."); +} diff --git a/dom/imptests/html/webgl/test_bufferSubData.html b/dom/imptests/html/webgl/test_bufferSubData.html new file mode 100644 index 000000000..a97df9062 --- /dev/null +++ b/dom/imptests/html/webgl/test_bufferSubData.html @@ -0,0 +1,26 @@ +<!doctype html> +<title>bufferSubData</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.5> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=common.js></script> + +<div id=log></div> +<script> +test(function() { + var gl = getGl(); + assert_equals(gl.getError(), WebGLRenderingContext.NO_ERROR); + + var b = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, b); + + var a = new Float32Array(1); + gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW); + + var nan = 0 / 0; + gl.bufferSubData(gl.ARRAY_BUFFER, nan, a); + + assert_equals(gl.getError(), WebGLRenderingContext.NO_ERROR); +}); +</script> diff --git a/dom/imptests/html/webgl/test_compressedTexImage2D.html b/dom/imptests/html/webgl/test_compressedTexImage2D.html new file mode 100644 index 000000000..b0a031add --- /dev/null +++ b/dom/imptests/html/webgl/test_compressedTexImage2D.html @@ -0,0 +1,30 @@ +<!doctype html> +<title>compressedTexImage2D</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=common.js></script> + +<div id=log></div> +<script> +test(function() { + var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; + var gl = getGl(); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + shouldGenerateGLError(gl, gl.INVALID_ENUM, function() { + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8)); + }); + shouldGenerateGLError(gl, gl.INVALID_ENUM, function() { + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8), null); + }); + test(function() { + assert_throws(new TypeError(), function() { + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0); + }); + }, "Should throw a TypeError when passing too few arguments."); +}); +</script> diff --git a/dom/imptests/html/webgl/test_compressedTexSubImage2D.html b/dom/imptests/html/webgl/test_compressedTexSubImage2D.html new file mode 100644 index 000000000..539f9e17f --- /dev/null +++ b/dom/imptests/html/webgl/test_compressedTexSubImage2D.html @@ -0,0 +1,30 @@ +<!doctype html> +<title>compressedTexSubImage2D</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=common.js></script> + +<div id=log></div> +<script> +test(function() { + var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; + var gl = getGl(); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + shouldGenerateGLError(gl, gl.INVALID_ENUM, function() { + gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_S3TC_DXT1_EXT, new Uint8Array(8)); + }); + shouldGenerateGLError(gl, gl.INVALID_ENUM, function() { + gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_S3TC_DXT1_EXT, new Uint8Array(8), null); + }); + test(function() { + assert_throws(new TypeError(), function() { + gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_S3TC_DXT1_EXT); + }); + }, "Should throw a TypeError when passing too few arguments."); +}); +</script> diff --git a/dom/imptests/html/webgl/test_texImage2D.html b/dom/imptests/html/webgl/test_texImage2D.html new file mode 100644 index 000000000..2f769160d --- /dev/null +++ b/dom/imptests/html/webgl/test_texImage2D.html @@ -0,0 +1,20 @@ +<!doctype html> +<title>texImage2D</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=common.js></script> + +<div id=log></div> +<script> +test(function() { + var gl = getGl(); + assert_throws(new TypeError(), function() { + gl.texImage2D(0, 0, 0, 0, 0, window); + }); + assert_throws(new TypeError(), function() { + gl.texImage2D(0, 0, 0, 0, 0, { get width() { throw 7 }, get height() { throw 7 }, data: new Uint8ClampedArray(10) }); + }); +}); +</script> diff --git a/dom/imptests/html/webgl/test_texSubImage2D.html b/dom/imptests/html/webgl/test_texSubImage2D.html new file mode 100644 index 000000000..294b30c76 --- /dev/null +++ b/dom/imptests/html/webgl/test_texSubImage2D.html @@ -0,0 +1,20 @@ +<!doctype html> +<title>texSubImage2D</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=common.js></script> + +<div id=log></div> +<script> +test(function() { + var gl = getGl(); + assert_throws(new TypeError(), function() { + gl.texSubImage2D(0, 0, 0, 0, 0, 0, window); + }); + assert_throws(new TypeError(), function() { + gl.texSubImage2D(0, 0, 0, 0, 0, 0, { get width() { throw 7 }, get height() { throw 7 }, data: new Uint8ClampedArray(10) }); + }); +}); +</script> diff --git a/dom/imptests/html/webgl/test_uniformMatrixNfv.html b/dom/imptests/html/webgl/test_uniformMatrixNfv.html new file mode 100644 index 000000000..f75cbcb99 --- /dev/null +++ b/dom/imptests/html/webgl/test_uniformMatrixNfv.html @@ -0,0 +1,33 @@ +<!doctype html> +<title>uniformMatrix*fv</title> +<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger> +<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#WebGLRenderingContext> +<link rel=help href=http://dev.w3.org/2006/webapi/WebIDL/#es-boolean> +<link rel=help href=http://es5.github.com/#x9.2> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=common.js></script> + +<div id=log></div> +<script id="vshader" type="x-shader/x-vertex"> +uniform mat2 m2; +uniform mat3 m3; +uniform mat4 m4; +</script> +<script> +var floatArray = function(n) { + var a = []; + for (var i = 0; i < n; ++i) { + a.push(1); + } + return a; +}; +[2, 3, 4].forEach(function(n) { + test(function() { + var gl = getGl(); + var f = "uniformMatrix" + n + "fv"; + var loc = gl.getUniformLocation(gl.createProgram(), "m" + n); + gl[f](loc, { valueOf: function() { throw "Error"; } }, floatArray(n)); + }, "Should not throw for " + n); +}); +</script> |