diff options
Diffstat (limited to 'parser/html/java')
10 files changed, 513 insertions, 81 deletions
diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/Creator.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/Creator.java new file mode 100644 index 000000000..0be53cd59 --- /dev/null +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/Creator.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Mozilla Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * Applied to an integer type to generate the unsigned variant in C++. + */ +package nu.validator.htmlparser.annotation; + +public @interface Creator { + +} diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/HtmlCreator.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/HtmlCreator.java new file mode 100644 index 000000000..a96bf0f0d --- /dev/null +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/HtmlCreator.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Mozilla Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * Applied to an integer type to generate the unsigned variant in C++. + */ +package nu.validator.htmlparser.annotation; + +public @interface HtmlCreator { + +} diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/SvgCreator.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/SvgCreator.java new file mode 100644 index 000000000..f317b09f1 --- /dev/null +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/annotation/SvgCreator.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Mozilla Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * Applied to an integer type to generate the unsigned variant in C++. + */ +package nu.validator.htmlparser.annotation; + +public @interface SvgCreator { + +} diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/ElementName.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/ElementName.java index ebfd8294b..c47ceb1a2 100644 --- a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/ElementName.java +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/ElementName.java @@ -24,10 +24,21 @@ package nu.validator.htmlparser.impl; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +// uncomment to regenerate self +//import java.io.BufferedReader; +//import java.io.File; +//import java.io.FileInputStream; +//import java.io.IOException; +//import java.io.InputStreamReader; +//import java.util.Arrays; +//import java.util.Collections; +//import java.util.HashMap; +//import java.util.LinkedList; +//import java.util.List; +//import java.util.Map; +//import java.util.Map.Entry; +//import java.util.regex.Matcher; +//import java.util.regex.Pattern; import nu.validator.htmlparser.annotation.Inline; import nu.validator.htmlparser.annotation.Local; @@ -46,14 +57,14 @@ public final class ElementName public static final int GROUP_MASK = 127; /** - * Indicates that the element is not a pre-interned element. Forbidden - * on preinterned elements. + * Indicates that the element is not a pre-interned element. Forbidden on + * preinterned elements. */ public static final int NOT_INTERNED = (1 << 30); /** - * Indicates that the element is in the "special" category. This bit - * should not be pre-set on MathML or SVG specials--only on HTML specials. + * Indicates that the element is in the "special" category. This bit should + * not be pre-set on MathML or SVG specials--only on HTML specials. */ public static final int SPECIAL = (1 << 29); @@ -64,8 +75,8 @@ public final class ElementName public static final int FOSTER_PARENTING = (1 << 28); /** - * The element is scoping. This bit should be pre-set on elements - * that are scoping as HTML. + * The element is scoping. This bit should be pre-set on elements that are + * scoping as HTML. */ public static final int SCOPING = (1 << 27); @@ -93,6 +104,10 @@ public final class ElementName private @Local String camelCaseName; + // CPPONLY: private @HtmlCreator Object htmlCreator; + + // CPPONLY: private @SvgCreator Object svgCreator; + /** * The lowest 7 bits are the dispatch group. The high bits are flags. */ @@ -106,6 +121,14 @@ public final class ElementName return camelCaseName; } + // CPPONLY: @Inline public @HtmlCreator Object getHtmlCreator() { + // CPPONLY: return htmlCreator; + // CPPONLY: } + + // CPPONLY: @Inline public @SvgCreator Object getSvgCreator() { + // CPPONLY: return svgCreator; + // CPPONLY: } + @Inline public int getFlags() { return flags; } @@ -136,7 +159,8 @@ public final class ElementName return -1; } - @Inline static ElementName elementNameByBuffer(@NoLength char[] buf, int offset, int length, Interner interner) { + @Inline static ElementName elementNameByBuffer(@NoLength char[] buf, + int offset, int length, Interner interner) { @Unsigned int hash = ElementName.bufToHash(buf, length); int[] hashes; hashes = ElementName.ELEMENT_HASHES; @@ -161,7 +185,8 @@ public final class ElementName * @param len * @return */ - @Inline private static @Unsigned int bufToHash(@NoLength char[] buf, int length) { + @Inline private static @Unsigned int bufToHash(@NoLength char[] buf, + int length) { @Unsigned int len = length; @Unsigned int first = buf[0]; first <<= 19; @@ -191,15 +216,21 @@ public final class ElementName } private ElementName(@Local String name, @Local String camelCaseName, + // CPPONLY: @HtmlCreator Object htmlCreator, @SvgCreator Object + // CPPONLY: svgCreator, int flags) { this.name = name; this.camelCaseName = camelCaseName; + // CPPONLY: this.htmlCreator = htmlCreator; + // CPPONLY: this.svgCreator = svgCreator; this.flags = flags; } public ElementName() { this.name = null; this.camelCaseName = null; + // CPPONLY: this.htmlCreator = NS_NewHTMLUnknownElement; + // CPPONLY: this.svgCreator = NS_NewSVGUnknownElement; this.flags = TreeBuilder.OTHER | NOT_INTERNED; } @@ -207,31 +238,139 @@ public final class ElementName // The translator adds refcount debug code here. } - @Inline public void setNameForNonInterned(@Local String name) { + @Inline public void setNameForNonInterned(@Local String name + // CPPONLY: , boolean custom + ) { // No need to worry about refcounting the local name, because in the // C++ case the scoped atom table remembers its own atoms. this.name = name; this.camelCaseName = name; + // CPPONLY: if (custom) { + // CPPONLY: this.htmlCreator = NS_NewCustomElement; + // CPPONLY: } else { + // CPPONLY: this.htmlCreator = NS_NewHTMLUnknownElement; + // CPPONLY: } // The assertion below relies on TreeBuilder.OTHER being zero! // TreeBuilder.OTHER isn't referenced here, because it would create // a circular C++ header dependency given that this method is inlined. assert this.flags == ElementName.NOT_INTERNED; } - // CPPONLY: public static final ElementName ISINDEX = new ElementName("isindex", "isindex", TreeBuilder.ISINDEX | SPECIAL); + // CPPONLY: @Inline public boolean isCustom() { + // CPPONLY: return this.htmlCreator == NS_NewCustomElement; + // CPPONLY: } + + // CPPONLY: public static final ElementName ISINDEX = new ElementName( + // CPPONLY: "isindex", "isindex", + // CPPONLY: NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement, + // CPPONLY: TreeBuilder.ISINDEX | SPECIAL); // [NOCPP[ public static final ElementName ISINDEX = new ElementName("isindex", "isindex", TreeBuilder.OTHER); // ]NOCPP] - public static final ElementName ANNOTATION_XML = new ElementName("annotation-xml", "annotation-xml", TreeBuilder.ANNOTATION_XML | SCOPING_AS_MATHML); + public static final ElementName ANNOTATION_XML = new ElementName( + "annotation-xml", "annotation-xml", + // CPPONLY: NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement, + TreeBuilder.ANNOTATION_XML | SCOPING_AS_MATHML); // START CODE ONLY USED FOR GENERATING CODE uncomment and run to regenerate +// private static final Pattern HTML_TAG_DEF = Pattern.compile( +// "^HTML_TAG\\(([^,]+),\\s*([^,]+),\\s*[^,]+\\).*$"); +// +// private static final Pattern HTML_HTMLELEMENT_TAG_DEF = Pattern.compile( +// "^HTML_HTMLELEMENT_TAG\\(([^\\)]+)\\).*$"); +// +// private static final Pattern SVG_TAG_DEF = Pattern.compile( +// "^SVG_(?:FROM_PARSER_)?TAG\\(([^,]+),\\s*([^\\)]+)\\).*$"); +// +// private static final Map<String, String> htmlMap = new HashMap<String, String>(); +// +// private static final Map<String, String> svgMap = new HashMap<String, String>(); +// +// private static void ingestHtmlTags(File htmlList) throws IOException { +// // This doesn't need to be efficient, so let's make it easy to write. +// BufferedReader htmlReader = new BufferedReader( +// new InputStreamReader(new FileInputStream(htmlList), "utf-8")); +// try { +// String line; +// while ((line = htmlReader.readLine()) != null) { +// if (!line.startsWith("HTML_")) { +// continue; +// } +// if (line.startsWith("HTML_OTHER")) { +// continue; +// } +// Matcher m = HTML_TAG_DEF.matcher(line); +// if (m.matches()) { +// String iface = m.group(2); +// if ("Unknown".equals(iface)) { +// continue; +// } +// htmlMap.put(m.group(1), "NS_NewHTML" + iface + "Element"); +// } else { +// m = HTML_HTMLELEMENT_TAG_DEF.matcher(line); +// if (!m.matches()) { +// throw new RuntimeException( +// "Malformed HTML element definition: " + line); +// } +// htmlMap.put(m.group(1), "NS_NewHTMLElement"); +// } +// } +// } finally { +// htmlReader.close(); +// } +// } +// +// private static void ingestSvgTags(File svgList) throws IOException { +// // This doesn't need to be efficient, so let's make it easy to write. +// BufferedReader svgReader = new BufferedReader( +// new InputStreamReader(new FileInputStream(svgList), "utf-8")); +// try { +// String line; +// while ((line = svgReader.readLine()) != null) { +// if (!line.startsWith("SVG_")) { +// continue; +// } +// Matcher m = SVG_TAG_DEF.matcher(line); +// if (!m.matches()) { +// throw new RuntimeException( +// "Malformed SVG element definition: " + line); +// } +// String name = m.group(1); +// if ("svgSwitch".equals(name)) { +// name = "switch"; +// } +// svgMap.put(name, "NS_NewSVG" + m.group(2) + "Element"); +// } +// } finally { +// svgReader.close(); +// } +// } +// +// private static String htmlCreator(String name) { +// String creator = htmlMap.remove(name); +// if (creator != null) { +// return creator; +// } +// return "NS_NewHTMLUnknownElement"; +// } +// +// private static String svgCreator(String name) { +// String creator = svgMap.remove(name); +// if (creator != null) { +// return creator; +// } +// return "NS_NewSVGUnknownElement"; +// } +// // /** // * @see java.lang.Object#toString() // */ // @Override public String toString() { -// return "(\"" + name + "\", \"" + camelCaseName + "\", " + decomposedFlags() + ")"; +// return "(\"" + name + "\", \"" + camelCaseName + "\", \n// CPP" +// + "ONLY: " + htmlCreator(name) + ",\n//CPP" + "ONLY: " +// + svgCreator(camelCaseName) + ", \n" + decomposedFlags() + ")"; // } // // private String decomposedFlags() { @@ -264,7 +403,9 @@ public final class ElementName // char c = name.charAt(i); // if (c == '-') { // // if (!"annotation-xml".equals(name)) { -// // throw new RuntimeException("Non-annotation-xml element name with hyphen: " + name); +// // throw new RuntimeException( +// // "Non-annotation-xml element name with hyphen: " +// // + name); // // } // buf[i] = '_'; // } else if (c >= '0' && c <= '9') { @@ -456,9 +597,23 @@ public final class ElementName // /** // * Regenerate self // * -// * @param args +// * The args should be the paths to m-c files +// * parser/htmlparser/nsHTMLTagList.h and dom/svg/SVGTagList.h. // */ // public static void main(String[] args) { +// File htmlList = new File(args[0]); +// File svgList = new File(args[1]); +// try { +// ingestHtmlTags(htmlList); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// try { +// ingestSvgTags(svgList); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// // Arrays.sort(ELEMENT_NAMES); // for (int i = 0; i < ELEMENT_NAMES.length; i++) { // int hash = ELEMENT_NAMES[i].hash(); @@ -468,8 +623,9 @@ public final class ElementName // } // for (int j = i + 1; j < ELEMENT_NAMES.length; j++) { // if (hash == ELEMENT_NAMES[j].hash()) { -// System.err.println("Hash collision: " + ELEMENT_NAMES[i].name -// + ", " + ELEMENT_NAMES[j].name); +// System.err.println( +// "Hash collision: " + ELEMENT_NAMES[i].name + ", " +// + ELEMENT_NAMES[j].name); // return; // } // } @@ -479,18 +635,20 @@ public final class ElementName // if ("isindex".equals(el.name)) { // continue; // } -// System.out.println("public static final ElementName " -// + el.constName() + " = new ElementName" + el.toString() -// + ";"); +// System.out.println( +// "public static final ElementName " + el.constName() +// + " = new ElementName" + el.toString() + ";"); // } // // LinkedList<ElementName> sortedNames = new LinkedList<ElementName>(); // Collections.addAll(sortedNames, ELEMENT_NAMES); // ElementName[] levelOrder = new ElementName[ELEMENT_NAMES.length]; -// int bstDepth = (int) Math.ceil(Math.log(ELEMENT_NAMES.length) / Math.log(2)); +// int bstDepth = (int) Math.ceil( +// Math.log(ELEMENT_NAMES.length) / Math.log(2)); // fillLevelOrderArray(sortedNames, bstDepth, 0, levelOrder); // -// System.out.println("private final static @NoLength ElementName[] ELEMENT_NAMES = {"); +// System.out.println( +// "private final static @NoLength ElementName[] ELEMENT_NAMES = {"); // for (int i = 0; i < levelOrder.length; i++) { // ElementName el = levelOrder[i]; // System.out.println(el.constName() + ","); @@ -502,6 +660,13 @@ public final class ElementName // System.out.println(Integer.toString(el.hash()) + ","); // } // System.out.println("};"); +// +// for (Entry<String, String> entry : htmlMap.entrySet()) { +// System.err.println("Missing HTML element: " + entry.getKey()); +// } +// for (Entry<String, String> entry : svgMap.entrySet()) { +// System.err.println("Missing SVG element: " + entry.getKey()); +// } // } diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/StackNode.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/StackNode.java index 3be685920..5225145e0 100644 --- a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/StackNode.java +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/StackNode.java @@ -45,6 +45,11 @@ final class StackNode<T> { private int refcount = 1; + /* + * Only valid for formatting elements + */ + // CPPONLY: private @HtmlCreator Object htmlCreator; + // [NOCPP[ private final TaintableLocatorImpl locator; @@ -87,6 +92,10 @@ final class StackNode<T> { // ]NOCPP] + // CPPONLY: public @HtmlCreator Object getHtmlCreator() { + // CPPONLY: return htmlCreator; + // CPPONLY: } + /** * Constructor for copying. This doesn't take another <code>StackNode</code> * because in C++ the caller is reponsible for reobtaining the local names @@ -100,9 +109,10 @@ final class StackNode<T> { * @param attributes */ StackNode(int flags, @NsUri String ns, @Local String name, T node, - @Local String popName, HtmlAttributes attributes + @Local String popName, HtmlAttributes attributes, + // CPPONLY: @HtmlCreator Object htmlCreator // [NOCPP[ - , TaintableLocatorImpl locator + TaintableLocatorImpl locator // ]NOCPP] ) { this.flags = flags; @@ -112,6 +122,10 @@ final class StackNode<T> { this.node = node; this.attributes = attributes; this.refcount = 1; + /* + * Need to track creator for formatting elements when copying. + */ + // CPPONLY: this.htmlCreator = htmlCreator; // [NOCPP[ this.locator = locator; // ]NOCPP] @@ -136,6 +150,10 @@ final class StackNode<T> { this.attributes = null; this.refcount = 1; assert elementName.isInterned() : "Don't use this constructor for custom elements."; + /* + * Not used for formatting elements, so no need to track creator. + */ + // CPPONLY: this.htmlCreator = null; // [NOCPP[ this.locator = locator; // ]NOCPP] @@ -161,6 +179,11 @@ final class StackNode<T> { this.attributes = attributes; this.refcount = 1; assert elementName.isInterned() : "Don't use this constructor for custom elements."; + /* + * Need to track creator for formatting elements in order to be able + * to clone them. + */ + // CPPONLY: this.htmlCreator = elementName.getHtmlCreator(); // [NOCPP[ this.locator = locator; // ]NOCPP] @@ -185,6 +208,10 @@ final class StackNode<T> { this.node = node; this.attributes = null; this.refcount = 1; + /* + * Not used for formatting elements, so no need to track creator. + */ + // CPPONLY: this.htmlCreator = null; // [NOCPP[ this.locator = locator; // ]NOCPP] @@ -212,6 +239,10 @@ final class StackNode<T> { this.node = node; this.attributes = null; this.refcount = 1; + /* + * Not used for formatting elements, so no need to track creator. + */ + // CPPONLY: this.htmlCreator = null; // [NOCPP[ this.locator = locator; // ]NOCPP] @@ -239,6 +270,10 @@ final class StackNode<T> { this.node = node; this.attributes = null; this.refcount = 1; + /* + * Not used for formatting elements, so no need to track creator. + */ + // CPPONLY: this.htmlCreator = null; // [NOCPP[ this.locator = locator; // ]NOCPP] diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java index c0ab7378e..996bd9ceb 100644 --- a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java @@ -1140,7 +1140,9 @@ public class Tokenizer implements Locator { tagName = ElementName.ANNOTATION_XML; } else { nonInternedTagName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, 0, strBufLen, - interner)); + interner) + // CPPONLY: , true + ); tagName = nonInternedTagName; } } else { @@ -1148,7 +1150,9 @@ public class Tokenizer implements Locator { interner); if (tagName == null) { nonInternedTagName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, 0, strBufLen, - interner)); + interner) + // CPPONLY: , false + ); tagName = nonInternedTagName; } } @@ -6699,7 +6703,9 @@ public class Tokenizer implements Locator { publicIdentifier = null; } tagName = null; - nonInternedTagName.setNameForNonInterned(null); + nonInternedTagName.setNameForNonInterned(null + // CPPONLY: , false + ); attributeName = null; // CPPONLY: nonInternedAttributeName.setNameForNonInterned(null); tokenHandler.endTokenization(); @@ -6849,7 +6855,9 @@ public class Tokenizer implements Locator { // In the C++ case, the atoms in the other tokenizer are from a // different tokenizer-scoped atom table. Therefore, we have to // obtain the correspoding atom from our own atom table. - nonInternedTagName.setNameForNonInterned(Portability.newLocalFromLocal(other.tagName.getName(), interner)); + nonInternedTagName.setNameForNonInterned(Portability.newLocalFromLocal(other.tagName.getName(), interner) + // CPPONLY: , other.tagName.isCustom() + ); tagName = nonInternedTagName; } diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/TreeBuilder.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/TreeBuilder.java index 5e1a93bfd..b4e67d58c 100644 --- a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/TreeBuilder.java +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/TreeBuilder.java @@ -478,6 +478,18 @@ public abstract class TreeBuilder<T> implements TokenHandler, protected void fatal() throws SAXException { } + // CPPONLY: @Inline private @Creator Object htmlCreator(@HtmlCreator Object htmlCreator) { + // CPPONLY: @Creator Object creator; + // CPPONLY: creator.html = htmlCreator; + // CPPONLY: return creator; + // CPPONLY: } + // CPPONLY: + // CPPONLY: @Inline private @Creator Object svgCreator(@SvgCreator Object svgCreator) { + // CPPONLY: @Creator Object creator; + // CPPONLY: creator.svg = svgCreator; + // CPPONLY: return creator; + // CPPONLY: } + // [NOCPP[ protected final void fatal(Exception e) throws SAXException { @@ -714,7 +726,8 @@ public abstract class TreeBuilder<T> implements TokenHandler, // CPPONLY: if (tokenizer.isViewingXmlSource()) { // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg", // CPPONLY: "svg", - // CPPONLY: tokenizer.emptyAttributes(), null); + // CPPONLY: tokenizer.emptyAttributes(), null, + // CPPONLY: svgCreator(NS_NewSVGSVGElement)); // CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG, // CPPONLY: "svg", // CPPONLY: elt); @@ -1958,8 +1971,8 @@ public abstract class TreeBuilder<T> implements TokenHandler, attributes.getValue(AttributeName.TYPE))) { break intableloop; } - appendVoidElementToCurrent( - name, attributes, + appendVoidInputToCurrent( + attributes, formPointer); selfClosing = false; attributes = null; // CPP @@ -2321,7 +2334,7 @@ public abstract class TreeBuilder<T> implements TokenHandler, case INPUT: reconstructTheActiveFormattingElements(); appendVoidElementToCurrentMayFoster( - name, attributes, + elementName, attributes, formPointer); selfClosing = false; attributes = null; // CPP @@ -4798,9 +4811,12 @@ public abstract class TreeBuilder<T> implements TokenHandler, assert node == listOfActiveFormattingElements[nodeListPos]; assert node == stack[nodePos]; T clone = createElement("http://www.w3.org/1999/xhtml", - node.name, node.attributes.cloneAttributes(null), commonAncestor.node); + node.name, node.attributes.cloneAttributes(null), commonAncestor.node + // CPPONLY: , htmlCreator(node.getHtmlCreator()) + ); StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, node.name, clone, node.popName, node.attributes + // CPPONLY: , node.getHtmlCreator() // [NOCPP[ , node.getLocator() // ]NOCPP] @@ -4827,11 +4843,14 @@ public abstract class TreeBuilder<T> implements TokenHandler, } T clone = createElement("http://www.w3.org/1999/xhtml", formattingElt.name, - formattingElt.attributes.cloneAttributes(null), furthestBlock.node); + formattingElt.attributes.cloneAttributes(null), furthestBlock.node + // CPPONLY: , htmlCreator(formattingElt.getHtmlCreator()) + ); StackNode<T> formattingClone = new StackNode<T>( formattingElt.getFlags(), formattingElt.ns, formattingElt.name, clone, formattingElt.popName, formattingElt.attributes + // CPPONLY: , formattingElt.getHtmlCreator() // [NOCPP[ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) // ]NOCPP] @@ -5011,16 +5030,21 @@ public abstract class TreeBuilder<T> implements TokenHandler, T clone; if (currentNode.isFosterParenting()) { clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name, - entry.attributes.cloneAttributes(null)); + entry.attributes.cloneAttributes(null) + // CPPONLY: , htmlCreator(entry.getHtmlCreator()) + ); } else { clone = createElement("http://www.w3.org/1999/xhtml", entry.name, - entry.attributes.cloneAttributes(null), currentNode.node); + entry.attributes.cloneAttributes(null), currentNode.node + // CPPONLY: , htmlCreator(entry.getHtmlCreator()) + ); appendElement(clone, currentNode.node); } StackNode<T> entryClone = new StackNode<T>(entry.getFlags(), entry.ns, entry.name, clone, entry.popName, entry.attributes + // CPPONLY: , entry.getHtmlCreator() // [NOCPP[ , entry.getLocator() // ]NOCPP] @@ -5051,23 +5075,33 @@ public abstract class TreeBuilder<T> implements TokenHandler, } private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name, - HtmlAttributes attributes) throws SAXException { - return createAndInsertFosterParentedElement(ns, name, attributes, null); + HtmlAttributes attributes + // CPPONLY: , @Creator Object creator + ) throws SAXException { + return createAndInsertFosterParentedElement(ns, name, attributes, null + // CPPONLY: , creator + ); } private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name, - HtmlAttributes attributes, T form) throws SAXException { + HtmlAttributes attributes, T form + // CPPONLY: , @Creator Object creator + ) throws SAXException { int tablePos = findLastOrRoot(TreeBuilder.TABLE); int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE); if (templatePos >= tablePos) { - T child = createElement(ns, name, attributes, form, stack[templatePos].node); + T child = createElement(ns, name, attributes, form, stack[templatePos].node + // CPPONLY: , creator + ); appendElement(child, stack[templatePos].node); return child; } StackNode<T> node = stack[tablePos]; - return createAndInsertFosterParentedElement(ns, name, attributes, form, node.node, stack[tablePos - 1].node); + return createAndInsertFosterParentedElement(ns, name, attributes, form, node.node, stack[tablePos - 1].node + // CPPONLY: , creator + ); } private boolean isInStack(StackNode<T> node) { @@ -5225,7 +5259,12 @@ public abstract class TreeBuilder<T> implements TokenHandler, checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); // ]NOCPP] T currentNode = stack[currentPtr].node; - T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode); + T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode + /* + * head uses NS_NewHTMLSharedElement creator + */ + // CPPONLY: , htmlCreator(NS_NewHTMLSharedElement) + ); appendElement(elt, currentNode); headPointer = elt; StackNode<T> node = new StackNode<T>(ElementName.HEAD, @@ -5257,9 +5296,13 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", "form", attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", "form", attributes + // CPPONLY: , htmlCreator(NS_NewHTMLFormElement) + ); } else { - elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, current.node); + elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, current.node + // CPPONLY: , htmlCreator(NS_NewHTMLFormElement) + ); appendElement(elt, current.node); } @@ -5290,9 +5333,13 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); } else { - elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, current.node); + elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, current.node + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); appendElement(elt, current.node); } StackNode<T> node = new StackNode<T>(elementName, elt, clone @@ -5313,7 +5360,9 @@ public abstract class TreeBuilder<T> implements TokenHandler, // ]NOCPP] // This method can't be called for custom elements T currentNode = stack[currentPtr].node; - T elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, currentNode); + T elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, currentNode + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); appendElement(elt, currentNode); if (ElementName.TEMPLATE == elementName) { elt = getDocumentFragmentForTemplate(elt); @@ -5340,9 +5389,13 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); } else { - elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node); + elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); appendElement(elt, current.node); } StackNode<T> node = new StackNode<T>(elementName, elt, popName @@ -5374,9 +5427,13 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes + // CPPONLY: , htmlCreator(null) + ); } else { - elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node); + elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node + // CPPONLY: , htmlCreator(null) + ); appendElement(elt, current.node); } StackNode<T> node = new StackNode<T>(elementName, elt, popName, @@ -5423,9 +5480,13 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); } else { - elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node); + elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); appendElement(elt, current.node); } StackNode<T> node = new StackNode<T>(elementName, popName, elt @@ -5449,10 +5510,14 @@ public abstract class TreeBuilder<T> implements TokenHandler, if (current.isFosterParenting()) { fatal(); elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), - attributes, formOwner); + attributes, formOwner + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); } else { elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), - attributes, formOwner, current.node); + attributes, formOwner, current.node + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); appendElement(elt, current.node); } StackNode<T> node = new StackNode<T>(elementName, elt @@ -5464,7 +5529,8 @@ public abstract class TreeBuilder<T> implements TokenHandler, } private void appendVoidElementToCurrentMayFoster( - @Local String name, HtmlAttributes attributes, T form) throws SAXException { + ElementName elementName, HtmlAttributes attributes, T form) throws SAXException { + @Local String name = elementName.getName(); // [NOCPP[ checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); // ]NOCPP] @@ -5475,10 +5541,14 @@ public abstract class TreeBuilder<T> implements TokenHandler, if (current.isFosterParenting()) { fatal(); elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", name, - attributes, formOwner); + attributes, formOwner + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); } else { elt = createElement("http://www.w3.org/1999/xhtml", name, - attributes, formOwner, current.node); + attributes, formOwner, current.node + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); appendElement(elt, current.node); } elementPushed("http://www.w3.org/1999/xhtml", name, elt); @@ -5499,9 +5569,13 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); } else { - elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node); + elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); appendElement(elt, current.node); } elementPushed("http://www.w3.org/1999/xhtml", popName, elt); @@ -5522,9 +5596,13 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); } else { - elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node); + elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); appendElement(elt, current.node); } elementPushed("http://www.w3.org/2000/svg", popName, elt); @@ -5545,27 +5623,32 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> current = stack[currentPtr]; if (current.isFosterParenting()) { fatal(); - elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes + // CPPONLY: , htmlCreator(null) + ); } else { - elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node); + elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node + // CPPONLY: , htmlCreator(null) + ); appendElement(elt, current.node); } elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt); elementPopped("http://www.w3.org/1998/Math/MathML", popName, elt); } - private void appendVoidElementToCurrent( - @Local String name, HtmlAttributes attributes, T form) throws SAXException { + private void appendVoidInputToCurrent(HtmlAttributes attributes, T form) throws SAXException { // [NOCPP[ checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); // ]NOCPP] // Can't be called for custom elements T currentNode = stack[currentPtr].node; - T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes, - form == null || fragment || isTemplateContents() ? null : form, currentNode); + T elt = createElement("http://www.w3.org/1999/xhtml", "input", attributes, + form == null || fragment || isTemplateContents() ? null : form, currentNode + // CPPONLY: , htmlCreator(NS_NewHTMLInputElement) + ); appendElement(elt, currentNode); - elementPushed("http://www.w3.org/1999/xhtml", name, elt); - elementPopped("http://www.w3.org/1999/xhtml", name, elt); + elementPushed("http://www.w3.org/1999/xhtml", "input", elt); + elementPopped("http://www.w3.org/1999/xhtml", "input", elt); } private void appendVoidFormToCurrent(HtmlAttributes attributes) throws SAXException { @@ -5574,7 +5657,9 @@ public abstract class TreeBuilder<T> implements TokenHandler, // ]NOCPP] T currentNode = stack[currentPtr].node; T elt = createElement("http://www.w3.org/1999/xhtml", "form", - attributes, currentNode); + attributes, currentNode + // CPPONLY: , htmlCreator(NS_NewHTMLFormElement) + ); formPointer = elt; // ownership transferred to form pointer appendElement(elt, currentNode); @@ -5626,11 +5711,17 @@ public abstract class TreeBuilder<T> implements TokenHandler, } protected abstract T createElement(@NsUri String ns, @Local String name, - HtmlAttributes attributes, T intendedParent) throws SAXException; + HtmlAttributes attributes, T intendedParent + // CPPONLY: , @Creator Object creator + ) throws SAXException; protected T createElement(@NsUri String ns, @Local String name, - HtmlAttributes attributes, T form, T intendedParent) throws SAXException { - return createElement("http://www.w3.org/1999/xhtml", name, attributes, intendedParent); + HtmlAttributes attributes, T form, T intendedParent + // CPPONLY: , @Creator Object creator + ) throws SAXException { + return createElement("http://www.w3.org/1999/xhtml", name, attributes, intendedParent + // CPPONLY: , creator + ); } protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes) @@ -5659,7 +5750,9 @@ public abstract class TreeBuilder<T> implements TokenHandler, // ]NOCPP] protected T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name, - HtmlAttributes attributes, T form, T table, T stackParent) throws SAXException { + HtmlAttributes attributes, T form, T table, T stackParent + // CPPONLY: , @Creator Object creator + ) throws SAXException { return createAndInsertFosterParentedElement(ns, name, attributes, table, stackParent); }; @@ -5941,6 +6034,7 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, node.name, node.node, node.popName, node.attributes.cloneAttributes(null) + // CPPONLY: , node.getHtmlCreator() // [NOCPP[ , node.getLocator() // ]NOCPP] @@ -5958,6 +6052,7 @@ public abstract class TreeBuilder<T> implements TokenHandler, StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, node.name, node.node, node.popName, null + // CPPONLY: , node.getHtmlCreator() // [NOCPP[ , node.getLocator() // ]NOCPP] @@ -6063,6 +6158,7 @@ public abstract class TreeBuilder<T> implements TokenHandler, Portability.newLocalFromLocal(node.name, interner), node.node, Portability.newLocalFromLocal(node.popName, interner), node.attributes.cloneAttributes(null) + // CPPONLY: , node.getHtmlCreator() // [NOCPP[ , node.getLocator() // ]NOCPP] @@ -6080,6 +6176,7 @@ public abstract class TreeBuilder<T> implements TokenHandler, Portability.newLocalFromLocal(node.name, interner), node.node, Portability.newLocalFromLocal(node.popName, interner), null + // CPPONLY: , node.getHtmlCreator() // [NOCPP[ , node.getLocator() // ]NOCPP] diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java index dc524820f..432f08b90 100644 --- a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java +++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java @@ -92,6 +92,18 @@ public class AnnotationHelperVisitor<T> extends VoidVisitorAdapter<T> { return hasAnnotation("CharacterName"); } + protected boolean creator() { + return hasAnnotation("Creator"); + } + + protected boolean htmlCreator() { + return hasAnnotation("HtmlCreator"); + } + + protected boolean svgCreator() { + return hasAnnotation("SvgCreator"); + } + private boolean hasAnnotation(String anno) { if (currentAnnotations == null) { return false; diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java index 7943368f7..963d1ac68 100644 --- a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java +++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java @@ -117,7 +117,8 @@ public class CppTypes { "nsHtml5String", "nsNameSpaceManager", "nsIContent", "nsTraceRefcnt", "jArray", "nsHtml5ArrayCopy", "nsAHtml5TreeBuilderState", "nsHtml5Atoms", "nsHtml5ByteReadable", "nsIUnicodeDecoder", - "nsHtml5Macros", "nsIContentHandle", "nsHtml5Portability" }; + "nsHtml5Macros", "nsIContentHandle", "nsHtml5Portability", + "nsHtml5ContentCreatorFunction"}; private static final String[] OTHER_DECLATIONS = {}; @@ -232,6 +233,18 @@ public class CppTypes { return "nsIContentHandle*"; } + public String htmlCreatorType() { + return "mozilla::dom::HTMLContentCreatorFunction"; + } + + public String svgCreatorType() { + return "mozilla::dom::SVGContentCreatorFunction"; + } + + public String creatorType() { + return "nsHtml5ContentCreatorFunction"; + } + public String xhtmlNamespaceLiteral() { return "kNameSpaceID_XHTML"; } diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java index 2a37e5ce1..a97a9eba1 100644 --- a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java +++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java @@ -480,7 +480,15 @@ public class CppVisitor extends AnnotationHelperVisitor<LocalSymbolTable> { name = cppTypes.stringType(); } } else if ("T".equals(name) || "Object".equals(name)) { - name = cppTypes.nodeType(); + if (htmlCreator()) { + name = cppTypes.htmlCreatorType(); + } else if (svgCreator()) { + name = cppTypes.svgCreatorType(); + } else if (creator()) { + name = cppTypes.creatorType(); + } else { + name = cppTypes.nodeType(); + } } else if ("TokenHandler".equals(name)) { name = cppTypes.classPrefix() + "TreeBuilder*"; } else if ("EncodingDeclarationHandler".equals(name)) { @@ -1073,6 +1081,9 @@ public class CppVisitor extends AnnotationHelperVisitor<LocalSymbolTable> { if ("DocumentMode".equals(scope.toString())) { // printer.print(cppTypes.documentModeType()); // printer.print("."); + } else if ("creator".equals(scope.toString()) || "this.creator".equals(scope.toString())) { + scope.accept(this, arg); + printer.print("."); } else { scope.accept(this, arg); printer.print("->"); @@ -1324,7 +1335,8 @@ public class CppVisitor extends AnnotationHelperVisitor<LocalSymbolTable> { if (clazzName == null) { scope.accept(this, arg); if ("length".equals(n.getName()) - || "charAt".equals(n.getName())) { + || "charAt".equals(n.getName()) + || "creator".equals(scope.toString())) { printer.print("."); } else { printer.print("->"); |