diff options
Diffstat (limited to 'parser/htmlparser/tests/mochitest/parser_datreader.js')
-rw-r--r-- | parser/htmlparser/tests/mochitest/parser_datreader.js | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/parser/htmlparser/tests/mochitest/parser_datreader.js b/parser/htmlparser/tests/mochitest/parser_datreader.js new file mode 100644 index 0000000000..d3d3ea2c89 --- /dev/null +++ b/parser/htmlparser/tests/mochitest/parser_datreader.js @@ -0,0 +1,218 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * A test suite that runs WHATWG HTML parser tests. + * The tests are from html5lib. + * + * http://html5lib.googlecode.com/ + */ + +/** + * A few utility functions. + */ +function log(entry) {} + +function startsWith(s, s2) { + return s.indexOf(s2) == 0; +} + +function trimString(s) { + return s.replace(/^\s+/, "").replace(/\s+$/, ""); +} + +/** + * Parses an individual testcase into an array containing the input + * string, a string representing the expected tree (DOM), and a list + * of error messages. + * + * @param A string containing a single testcase + */ +function parseTestcase(testcase) { + var lines = testcase.split("\n"); + + /* check that the first non-empty, non-comment line is #data */ + for (let line of lines) { + if (!line || startsWith(line, "##")) { + continue; + } + if (line == "#data") { + break; + } + log(lines); + throw new Error("Unknown test format."); + } + + var input = []; + var output = []; + var errors = []; + var fragment = []; + var currentList = input; + for (let line of lines) { + if (startsWith(line, "##todo")) { + todo(false, line.substring(6)); + continue; + } + if ( + !( + startsWith(line, "#error") || + startsWith(line, "#document") || + startsWith(line, "#document-fragment") || + startsWith(line, "#data") + ) + ) { + currentList.push(line); + } else if (line == "#errors") { + currentList = errors; + } else if (line == "#document") { + currentList = output; + } else if (line == "#document-fragment") { + currentList = fragment; + } + } + while (!output[output.length - 1]) { + output.pop(); // zap trailing blank lines + } + // logger.log(input.length, output.length, errors.length); + return [input.join("\n"), output.join("\n"), errors, fragment[0]]; +} + +/** + * A generator function that accepts a list of strings. Each list + * member corresponds to the contents of a ".dat" file from the + * html5lib test suite. + * + * @param The list of strings + */ +function* test_parser(testlist) { + for (var testgroup of testlist) { + var tests = testgroup.split("#data\n"); + tests = tests.filter(test => test).map(test => "#data\n" + test); + for (var test of tests) { + yield parseTestcase(test); + } + } +} + +/** + * Transforms a DOM document to a string matching the format in + * the test cases. + * + * @param the DOM document + */ +function docToTestOutput(doc) { + var walker = doc.createTreeWalker(doc, NodeFilter.SHOW_ALL, null); + return addLevels(walker, "", "| ").slice(0, -1); // remove the last newline +} + +/** + * Creates a walker for a fragment that skips over the root node. + * + * @param an element + */ +function createFragmentWalker(elt) { + return elt.ownerDocument.createTreeWalker( + elt, + NodeFilter.SHOW_ALL, + function (node) { + return elt == node ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT; + } + ); +} + +/** + * Transforms the descendants of an element to a string matching the format + * in the test cases. + * + * @param an element + */ +function fragmentToTestOutput(elt) { + var walker = createFragmentWalker(elt); + return addLevels(walker, "", "| ").slice(0, -1); // remove the last newline +} + +function addLevels(walker, buf, indent) { + if (walker.firstChild()) { + do { + buf += indent; + switch (walker.currentNode.nodeType) { + case Node.ELEMENT_NODE: + buf += "<"; + var ns = walker.currentNode.namespaceURI; + if ("http://www.w3.org/1998/Math/MathML" == ns) { + buf += "math "; + } else if ("http://www.w3.org/2000/svg" == ns) { + buf += "svg "; + } else if ("http://www.w3.org/1999/xhtml" != ns) { + buf += "otherns "; + } + buf += walker.currentNode.localName + ">"; + if (walker.currentNode.hasAttributes()) { + var valuesByName = {}; + var attrs = walker.currentNode.attributes; + for (let i = 0; i < attrs.length; ++i) { + var localName = attrs[i].localName; + var name; + var attrNs = attrs[i].namespaceURI; + if (null == attrNs) { + name = localName; + } else if ("http://www.w3.org/XML/1998/namespace" == attrNs) { + name = "xml " + localName; + } else if ("http://www.w3.org/1999/xlink" == attrNs) { + name = "xlink " + localName; + } else if ("http://www.w3.org/2000/xmlns/" == attrNs) { + name = "xmlns " + localName; + } else { + name = "otherns " + localName; + } + valuesByName[name] = attrs[i].value; + } + var keys = Object.keys(valuesByName).sort(); + for (let i = 0; i < keys.length; ++i) { + buf += + "\n" + + indent + + " " + + keys[i] + + '="' + + valuesByName[keys[i]] + + '"'; + } + } + break; + case Node.DOCUMENT_TYPE_NODE: + buf += "<!DOCTYPE " + walker.currentNode.name; + if (walker.currentNode.publicId || walker.currentNode.systemId) { + buf += ' "'; + buf += walker.currentNode.publicId; + buf += '" "'; + buf += walker.currentNode.systemId; + buf += '"'; + } + buf += ">"; + break; + case Node.COMMENT_NODE: + buf += "<!-- " + walker.currentNode.nodeValue + " -->"; + break; + case Node.TEXT_NODE: + buf += '"' + walker.currentNode.nodeValue + '"'; + break; + } + buf += "\n"; + // In the case of template elements, children do not get inserted as + // children of the template element, instead they are inserted + // as children of the template content (which is a document fragment). + if (walker.currentNode.constructor.name === "HTMLTemplateElement") { + buf += indent + " content\n"; + // Walk through the template content. + var templateWalker = createFragmentWalker(walker.currentNode.content); + buf = addLevels(templateWalker, buf, indent + " "); + } + buf = addLevels(walker, buf, indent + " "); + } while (walker.nextSibling()); + walker.parentNode(); + } + return buf; +} |