diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /parser/html | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'parser/html')
99 files changed, 59008 insertions, 0 deletions
diff --git a/parser/html/jArray.h b/parser/html/jArray.h new file mode 100644 index 0000000000..a5429e6fd7 --- /dev/null +++ b/parser/html/jArray.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2008-2015 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. + */ + +#ifndef jArray_h +#define jArray_h + +#include "mozilla/Attributes.h" +#include "mozilla/BinarySearch.h" +#include "nsDebug.h" + +template <class T, class L> +struct staticJArray { + const T* arr; + const L length; + operator T*() { return arr; } + T& operator[](L const index) { + MOZ_ASSERT(index >= 0, "Array access with negative index."); + MOZ_ASSERT(index < length, "Array index out of bounds."); + return ((T*)arr)[index]; + } + L binarySearch(T const elem) { + size_t idx; + bool found = mozilla::BinarySearch(arr, 0, length, elem, &idx); + return found ? idx : -1; + } +}; + +template <class T, class L> +class autoJArray; + +template <class T, class L> +class jArray { + friend class autoJArray<T, L>; + + private: + T* arr; + + public: + L length; + static jArray<T, L> newJArray(L const len) { + MOZ_ASSERT(len >= 0, "Negative length."); + jArray<T, L> newArray = {new T[size_t(len)], len}; + return newArray; + } + static jArray<T, L> newFallibleJArray(L const len) { + MOZ_ASSERT(len >= 0, "Negative length."); + T* a = new (mozilla::fallible) T[size_t(len)]; + jArray<T, L> newArray = {a, a ? len : 0}; + return newArray; + } + operator T*() { return arr; } + T& operator[](L const index) { + MOZ_ASSERT(index >= 0, "Array access with negative index."); + MOZ_ASSERT(index < length, "Array index out of bounds."); + return arr[index]; + } + void operator=(staticJArray<T, L>& other) { + arr = (T*)other.arr; + length = other.length; + } + MOZ_IMPLICIT jArray(decltype(nullptr)) : arr(nullptr), length(0) {} + jArray() : arr(nullptr), length(0) {} + + private: + jArray(T* aArr, L aLength) : arr(aArr), length(aLength) {} +}; + +template <class T, class L> +class autoJArray { + private: + T* arr; + + public: + L length; + autoJArray() : arr(0), length(0) {} + MOZ_IMPLICIT autoJArray(const jArray<T, L>& other) + : arr(other.arr), length(other.length) {} + ~autoJArray() { delete[] arr; } + operator T*() { return arr; } + T& operator[](L const index) { + MOZ_ASSERT(index >= 0, "Array access with negative index."); + MOZ_ASSERT(index < length, "Array index out of bounds."); + return arr[index]; + } + operator jArray<T, L>() { + // WARNING! This makes it possible to goof with buffer ownership! + // This is needed for the getStack and getListOfActiveFormattingElements + // methods to work sensibly. + jArray<T, L> newArray = {arr, length}; + return newArray; + } + void operator=(const jArray<T, L>& other) { + delete[] arr; + arr = other.arr; + length = other.length; + } + void operator=(decltype(nullptr)) { + // Make assigning null to an array in Java delete the buffer in C++ + delete[] arr; + arr = nullptr; + length = 0; + } +}; + +#endif // jArray_h diff --git a/parser/html/java/Makefile b/parser/html/java/Makefile new file mode 100644 index 0000000000..5dd7d6bb0a --- /dev/null +++ b/parser/html/java/Makefile @@ -0,0 +1,52 @@ +# 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/. + +libs:: translator + +translator:: javaparser \ +; mkdir -p htmlparser/bin && \ + find htmlparser/translator-src/nu/validator/htmlparser -name "*.java" | \ + xargs javac -cp javaparser.jar -g -d htmlparser/bin && \ + jar cfm translator.jar manifest.txt -C htmlparser/bin . + +javaparser:: \ +; mkdir -p javaparser/bin && \ + find javaparser/src -name "*.java" | \ + xargs javac -encoding ISO-8859-1 -g -d javaparser/bin && \ + jar cf javaparser.jar -C javaparser/bin . + +sync_javaparser:: \ +; if [ ! -d javaparser/.git ] ; \ + then rm -rf javaparser ; \ + git clone https://github.com/javaparser/javaparser.git ; \ + fi ; \ + cd javaparser ; git checkout javaparser-1.0.6 ; cd .. + +sync_htmlparser:: \ +; if [ -d htmlparser/.hg ] ; \ + then echo "The htmlparser repo has move to GitHub. Please remove the htmlparser directory and resync." ; exit ; \ + elif [ ! -d htmlparser/.git ] ; \ + then rm -rf htmlparser ; \ + git clone https://github.com/validator/htmlparser.git ; \ + cd htmlparser ; git checkout master ; cd .. ; \ + fi + +sync:: sync_javaparser sync_htmlparser + +translate:: translator \ +; mkdir -p ../javasrc ; \ + java -jar translator.jar \ + htmlparser/src/nu/validator/htmlparser/impl \ + .. ../../../xpcom/ds/StaticAtoms.py ../../../xpcom/ds/HTMLAtoms.py + +translate_from_snapshot:: translator \ +; mkdir -p ../javasrc ; \ + java -jar translator.jar \ + ../javasrc \ + .. ../../../xpcom/ds/StaticAtoms.py ../../../xpcom/ds/HTMLAtoms.py + +named_characters:: translator \ +; java -cp translator.jar \ + nu.validator.htmlparser.generator.GenerateNamedCharactersCpp \ + named-character-references.html ../ diff --git a/parser/html/java/README.txt b/parser/html/java/README.txt new file mode 100644 index 0000000000..13eeb9a5cf --- /dev/null +++ b/parser/html/java/README.txt @@ -0,0 +1,86 @@ +If this is your first time building the HTML5 parser, you need to execute the +following commands (from this directory) to bootstrap the translation: + + make sync # fetch remote source files and licenses + make translate # perform the Java-to-C++ translation from the remote + # sources + make named_characters # Generate tables for named character tokenization + +If you make changes to the translator or the javaparser, you can rebuild by +retyping 'make' in this directory. If you make changes to the HTML5 Java +implementation, you can retranslate the Java sources from the htmlparser +repository by retyping 'make translate' in this directory. + +The makefile supports the following targets: + +sync_htmlparser: + Retrieves the HTML parser and Java to C++ translator sources from GitHub. +sync_javaparser: + Retrieves the javaparser sources from GitHub. +sync: + Runs both sync_javaparser and sync_htmlparser. +javaparser: + Builds the javaparser library retrieved earlier by sync_javaparser. +translator: + Runs the javaparser target and then builds the Java to C++ translator from + sources retrieved earlier by sync_htmlparser. +libs: + The default target. Alias for translator +translate: + Runs the translator target and then translates the HTML parser sources + retrieved by sync_htmlparser copying the Java sources to ../javasrc. +translate_from_snapshot: + Runs the translator target and then translates the HTML parser sources + stored in ../javasrc. +named_characters: + Generates data tables for named character tokenization. + +## How to add an attribute + +# starting from the root of a mozilla-central checkout +cd parser/html/java/ +make sync +# now you have a clone of https://github.com/validator/htmlparser/tree/master in parser/html/java/htmlparser/ +cd htmlparser/src/ +$EDITOR nu/validator/htmlparser/impl/AttributeName.java +# Search for the word "uncomment" and uncomment stuff according to the comments that talk about uncommenting +# Duplicate the declaration a normal attribute (nothings special in SVG mode, etc.). Let's use "alt", since it's the first one. +# In the duplicate, replace ALT with the new name in all caps and "alt" with the new name in quotes in lower case. +# Search for "ALT,", duplicate that line and change the duplicate to say the new name in all caps followed by comma. +# Save. +javac nu/validator/htmlparser/impl/AttributeName.java +java nu.validator.htmlparser.impl.AttributeName +# Copy and paste the output into nu/validator/htmlparser/impl/AttributeName.java replacing the text below the comment "START GENERATED CODE" and above the very last "}". +# Recomment the bits that you uncommented earlier. +# Save. +cd ../.. # Back to parser/html/java/ +make translate +cd ../../.. +./mach clang-format + +## How to add an element + +# First, add an entry to parser/htmlparser/nsHTMLTagList.h or dom/svg/SVGTagList.h! +# Then, starting from the root of a mozilla-central checkout +cd parser/html/java/ +make sync +# now you have a clone of https://github.com/validator/htmlparser/tree/master in parser/html/java/htmlparser/ +cd htmlparser/src/ +$EDITOR nu/validator/htmlparser/impl/ElementName.java +# Search for the word "uncomment" and uncomment stuff according to the comments that talk about uncommenting +# Duplicate the declaration a normal element. Let's use "bdo", since it's the first normal one. +# In the duplicate, replace BDO with the new name in all caps and "bdo" with the new name in quotes in lower case (twice). +# Search for "BDO,", duplicate that line and change the duplicate to say the new name in all caps followed by comma. +# Save. +javac nu/validator/htmlparser/impl/ElementName.java +java nu.validator.htmlparser.impl.ElementName ../../../../../parser/htmlparser/nsHTMLTagList.h ../../../../../dom/svg/SVGTagList.h +# Copy and paste the output into nu/validator/htmlparser/impl/ElementName.java replacing the text below the comment "START GENERATED CODE" and above the very last "}". +# Recomment the bits that you uncommented earlier. +# Save. +cd ../.. # Back to parser/html/java/ +make translate +cd ../../.. +./mach clang-format + +Ben Newman (23 September 2009) +Henri Sivonen (10 August 2017, 10 February 2020) diff --git a/parser/html/java/manifest.txt b/parser/html/java/manifest.txt new file mode 100644 index 0000000000..14cd9d0819 --- /dev/null +++ b/parser/html/java/manifest.txt @@ -0,0 +1,2 @@ +Main-Class: nu.validator.htmlparser.cpptranslate.Main +Class-Path: javaparser.jar diff --git a/parser/html/javasrc/AttributeName.java b/parser/html/javasrc/AttributeName.java new file mode 100644 index 0000000000..8014cd8043 --- /dev/null +++ b/parser/html/javasrc/AttributeName.java @@ -0,0 +1,2278 @@ +/* + * Copyright (c) 2008-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. + */ + +package nu.validator.htmlparser.impl; + +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import nu.validator.htmlparser.annotation.Inline; +import nu.validator.htmlparser.annotation.Local; +import nu.validator.htmlparser.annotation.NoLength; +import nu.validator.htmlparser.annotation.NsUri; +import nu.validator.htmlparser.annotation.Prefix; +import nu.validator.htmlparser.annotation.QName; +import nu.validator.htmlparser.annotation.Unsigned; +import nu.validator.htmlparser.common.Interner; + +public final class AttributeName +// Uncomment to regenerate +// implements Comparable<AttributeName> +{ + // [NOCPP[ + + public static final int NCNAME_HTML = 1; + + public static final int NCNAME_FOREIGN = (1 << 1) | (1 << 2); + + public static final int NCNAME_LANG = (1 << 3); + + public static final int IS_XMLNS = (1 << 4); + + public static final int CASE_FOLDED = (1 << 5); + + public static final int BOOLEAN = (1 << 6); + + // ]NOCPP] + + /** + * An array representing no namespace regardless of namespace mode (HTML, + * SVG, MathML, lang-mapping HTML) used. + */ + static final @NoLength @NsUri String[] ALL_NO_NS = { "", "", "", + // [NOCPP[ + "" + // ]NOCPP] + }; + + /** + * An array that has no namespace for the HTML mode but the XMLNS namespace + * for the SVG and MathML modes. + */ + private static final @NoLength @NsUri String[] XMLNS_NS = { "", + "http://www.w3.org/2000/xmlns/", "http://www.w3.org/2000/xmlns/", + // [NOCPP[ + "" + // ]NOCPP] + }; + + /** + * An array that has no namespace for the HTML mode but the XML namespace + * for the SVG and MathML modes. + */ + private static final @NoLength @NsUri String[] XML_NS = { "", + "http://www.w3.org/XML/1998/namespace", + "http://www.w3.org/XML/1998/namespace", + // [NOCPP[ + "" + // ]NOCPP] + }; + + /** + * An array that has no namespace for the HTML mode but the XLink namespace + * for the SVG and MathML modes. + */ + private static final @NoLength @NsUri String[] XLINK_NS = { "", + "http://www.w3.org/1999/xlink", "http://www.w3.org/1999/xlink", + // [NOCPP[ + "" + // ]NOCPP] + }; + + // [NOCPP[ + /** + * An array that has no namespace for the HTML, SVG and MathML modes but has + * the XML namespace for the lang-mapping HTML mode. + */ + private static final @NoLength @NsUri String[] LANG_NS = { "", "", "", + "http://www.w3.org/XML/1998/namespace" }; + + // ]NOCPP] + + /** + * An array for no prefixes in any mode. + */ + static final @NoLength @Prefix String[] ALL_NO_PREFIX = { null, null, null, + // [NOCPP[ + null + // ]NOCPP] + }; + + /** + * An array for no prefixe in the HTML mode and the <code>xmlns</code> + * prefix in the SVG and MathML modes. + */ + private static final @NoLength @Prefix String[] XMLNS_PREFIX = { null, + "xmlns", "xmlns", + // [NOCPP[ + null + // ]NOCPP] + }; + + /** + * An array for no prefixe in the HTML mode and the <code>xlink</code> + * prefix in the SVG and MathML modes. + */ + private static final @NoLength @Prefix String[] XLINK_PREFIX = { null, + "xlink", "xlink", + // [NOCPP[ + null + // ]NOCPP] + }; + + /** + * An array for no prefixe in the HTML mode and the <code>xml</code> prefix + * in the SVG and MathML modes. + */ + private static final @NoLength @Prefix String[] XML_PREFIX = { null, "xml", + "xml", + // [NOCPP[ + null + // ]NOCPP] + }; + + // [NOCPP[ + + private static final @NoLength @Prefix String[] LANG_PREFIX = { null, null, + null, "xml" }; + + private static @QName String[] COMPUTE_QNAME(String[] local, String[] prefix) { + @QName String[] arr = new String[4]; + for (int i = 0; i < arr.length; i++) { + if (prefix[i] == null) { + arr[i] = local[i]; + } else { + arr[i] = (prefix[i] + ':' + local[i]).intern(); + } + } + return arr; + } + + // ]NOCPP] + + /** + * An initialization helper for having a one name in the SVG mode and + * another name in the other modes. + * + * @param name + * the name for the non-SVG modes + * @param camel + * the name for the SVG mode + * @return the initialized name array + */ + private static @NoLength @Local String[] SVG_DIFFERENT(@Local String name, + @Local String camel) { + @NoLength @Local String[] arr = new String[4]; + arr[0] = name; + arr[1] = name; + arr[2] = camel; + // [NOCPP[ + arr[3] = name; + // ]NOCPP] + return arr; + } + + /** + * An initialization helper for having a one name in the MathML mode and + * another name in the other modes. + * + * @param name + * the name for the non-MathML modes + * @param camel + * the name for the MathML mode + * @return the initialized name array + */ + private static @NoLength @Local String[] MATH_DIFFERENT(@Local String name, + @Local String camel) { + @NoLength @Local String[] arr = new String[4]; + arr[0] = name; + arr[1] = camel; + arr[2] = name; + // [NOCPP[ + arr[3] = name; + // ]NOCPP] + return arr; + } + + /** + * An initialization helper for having a different local name in the HTML + * mode and the SVG and MathML modes. + * + * @param name + * the name for the HTML mode + * @param suffix + * the name for the SVG and MathML modes + * @return the initialized name array + */ + private static @NoLength @Local String[] COLONIFIED_LOCAL( + @Local String name, @Local String suffix) { + @NoLength @Local String[] arr = new String[4]; + arr[0] = name; + arr[1] = suffix; + arr[2] = suffix; + // [NOCPP[ + arr[3] = name; + // ]NOCPP] + return arr; + } + + /** + * An initialization helper for having the same local name in all modes. + * + * @param name + * the name + * @return the initialized name array + */ + static @NoLength @Local String[] SAME_LOCAL(@Local String name) { + @NoLength @Local String[] arr = new String[4]; + arr[0] = name; + arr[1] = name; + arr[2] = name; + // [NOCPP[ + arr[3] = name; + // ]NOCPP] + return arr; + } + + @Inline static int levelOrderBinarySearch(int[] data, int key) { + int n = data.length; + int i = 0; + + while (i < n) { + int val = data[i]; + if (val < key) { + i = 2 * i + 2; + } else if (val > key) { + i = 2 * i + 1; + } else { + return i; + } + } + + return -1; + } + + /** + * Returns an attribute name by buffer. + * + * <p> + * C++ ownership: The return value is either released by the caller if the + * attribute is a duplicate or the ownership is transferred to + * HtmlAttributes and released upon clearing or destroying that object. + * + * @param buf + * the buffer + * @param offset + * ignored + * @param length + * length of data + * @param checkNcName + * whether to check ncnameness + * @return an <code>AttributeName</code> corresponding to the argument data + */ + @Inline static AttributeName nameByBuffer(@NoLength char[] buf, + int length, Interner interner) { + // XXX deal with offset + @Unsigned int hash = AttributeName.bufToHash(buf, length); + int[] hashes; + hashes = AttributeName.ATTRIBUTE_HASHES; + int index = levelOrderBinarySearch(hashes, hash); + if (index < 0) { + return null; + } + AttributeName attributeName = AttributeName.ATTRIBUTE_NAMES[index]; + @Local String name = attributeName.getLocal(0); + if (!Portability.localEqualsBuffer(name, buf, length)) { + return null; + } + return attributeName; + } + + /** + * This method has to return a unique positive integer for each well-known + * lower-cased attribute name. + * + * @param buf + * @param len + * @return + */ + @Inline private static @Unsigned int bufToHash(@NoLength char[] buf, int length) { + @Unsigned int len = length; + @Unsigned int first = buf[0]; + first <<= 19; + @Unsigned int second = 1 << 23; + @Unsigned int third = 0; + @Unsigned int fourth = 0; + @Unsigned int fifth = 0; + @Unsigned int sixth = 0; + if (length >= 4) { + second = buf[length - 4]; + second <<= 4; + third = buf[1]; + third <<= 9; + fourth = buf[length - 2]; + fourth <<= 14; + fifth = buf[3]; + fifth <<= 24; + sixth = buf[length - 1]; + sixth <<= 11; + } else if (length == 3) { + second = buf[1]; + second <<= 4; + third = buf[2]; + third <<= 9; + } else if (length == 2) { + second = buf[1]; + second <<= 24; + } + return len + first + second + third + fourth + fifth + sixth; + } + + /** + * The mode value for HTML. + */ + public static final int HTML = 0; + + /** + * The mode value for MathML. + */ + public static final int MATHML = 1; + + /** + * The mode value for SVG. + */ + public static final int SVG = 2; + + // [NOCPP[ + + /** + * The mode value for lang-mapping HTML. + */ + public static final int HTML_LANG = 3; + + // ]NOCPP] + + /** + * The namespaces indexable by mode. + */ + private final @NsUri @NoLength String[] uri; + + /** + * The local names indexable by mode. + */ + private final @Local @NoLength String[] local; + + /** + * The prefixes indexably by mode. + */ + private final @Prefix @NoLength String[] prefix; + + // CPPONLY: private final boolean custom; + + // [NOCPP[ + + private final int flags; + + /** + * The qnames indexable by mode. + */ + private final @QName @NoLength String[] qName; + + // ]NOCPP] + + /** + * The startup-time constructor. + * + * @param uri + * the namespace + * @param local + * the local name + * @param prefix + * the prefix + * @param ncname + * the ncnameness + * @param xmlns + * whether this is an xmlns attribute + */ + private AttributeName(@NsUri @NoLength String[] uri, + @Local @NoLength String[] local, @Prefix @NoLength String[] prefix + // [NOCPP[ + , int flags + // ]NOCPP] + ) { + this.uri = uri; + this.local = local; + this.prefix = prefix; + // [NOCPP[ + this.qName = COMPUTE_QNAME(local, prefix); + this.flags = flags; + // ]NOCPP] + // CPPONLY: this.custom = false; + } + + // CPPONLY: public AttributeName() { + // CPPONLY: this.uri = AttributeName.ALL_NO_NS; + // CPPONLY: this.local = AttributeName.SAME_LOCAL(null); + // CPPONLY: this.prefix = ALL_NO_PREFIX; + // CPPONLY: this.custom = true; + // CPPONLY: } + // CPPONLY: + // CPPONLY: @Inline public boolean isInterned() { + // CPPONLY: return !custom; + // CPPONLY: } + // CPPONLY: + // CPPONLY: @Inline public void setNameForNonInterned(@Local String name) { + // CPPONLY: assert custom; + // CPPONLY: local[0] = name; + // CPPONLY: local[1] = name; + // CPPONLY: local[2] = name; + // CPPONLY: } + + /** + * Creates an <code>AttributeName</code> for a local name. + * + * @param name + * the name + * @param checkNcName + * whether to check ncnameness + * @return an <code>AttributeName</code> + */ + static AttributeName createAttributeName(@Local String name + // [NOCPP[ + , boolean checkNcName + // ]NOCPP] + ) { + // [NOCPP[ + int flags = NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG; + if (name.startsWith("xmlns:")) { + flags = IS_XMLNS; + } else if (checkNcName && !NCName.isNCName(name)) { + flags = 0; + } + // ]NOCPP] + return new AttributeName(AttributeName.ALL_NO_NS, + AttributeName.SAME_LOCAL(name), ALL_NO_PREFIX, flags); + } + + /** + * The C++ destructor. + */ + @SuppressWarnings("unused") private void destructor() { + Portability.deleteArray(local); + } + + // [NOCPP[ + /** + * Creator for use when the XML violation policy requires an attribute name + * to be changed. + * + * @param name + * the name of the attribute to create + */ + static AttributeName create(@Local String name) { + return new AttributeName(AttributeName.ALL_NO_NS, + AttributeName.SAME_LOCAL(name), ALL_NO_PREFIX, + NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + } + + /** + * Queries whether this name is an XML 1.0 4th ed. NCName. + * + * @param mode + * the SVG/MathML/HTML mode + * @return <code>true</code> if this is an NCName in the given mode + */ + public boolean isNcName(int mode) { + return (flags & (1 << mode)) != 0; + } + + /** + * Queries whether this is an <code>xmlns</code> attribute. + * + * @return <code>true</code> if this is an <code>xmlns</code> attribute + */ + public boolean isXmlns() { + return (flags & IS_XMLNS) != 0; + } + + /** + * Queries whether this attribute has a case-folded value in the HTML4 mode + * of the parser. + * + * @return <code>true</code> if the value is case-folded + */ + boolean isCaseFolded() { + return (flags & CASE_FOLDED) != 0; + } + + boolean isBoolean() { + return (flags & BOOLEAN) != 0; + } + + public @QName String getQName(int mode) { + return qName[mode]; + } + + // ]NOCPP] + + public @NsUri String getUri(int mode) { + return uri[mode]; + } + + public @Local String getLocal(int mode) { + return local[mode]; + } + + public @Prefix String getPrefix(int mode) { + return prefix[mode]; + } + + boolean equalsAnother(AttributeName another) { + return this.getLocal(AttributeName.HTML) == another.getLocal(AttributeName.HTML); + } + + // START CODE ONLY USED FOR GENERATING CODE uncomment to regenerate + +// /** +// * @see java.lang.Object#toString() +// */ +// @Override public String toString() { +// return "(" + formatNs() + ", " + formatLocal() + ", " + formatPrefix() +// + ", " + formatFlags() + ")"; +// } +// +// private String formatFlags() { +// StringBuilder builder = new StringBuilder(); +// if ((flags & NCNAME_HTML) != 0) { +// if (builder.length() != 0) { +// builder.append(" | "); +// } +// builder.append("NCNAME_HTML"); +// } +// if ((flags & NCNAME_FOREIGN) != 0) { +// if (builder.length() != 0) { +// builder.append(" | "); +// } +// builder.append("NCNAME_FOREIGN"); +// } +// if ((flags & NCNAME_LANG) != 0) { +// if (builder.length() != 0) { +// builder.append(" | "); +// } +// builder.append("NCNAME_LANG"); +// } +// if (isXmlns()) { +// if (builder.length() != 0) { +// builder.append(" | "); +// } +// builder.append("IS_XMLNS"); +// } +// if (isCaseFolded()) { +// if (builder.length() != 0) { +// builder.append(" | "); +// } +// builder.append("CASE_FOLDED"); +// } +// if (isBoolean()) { +// if (builder.length() != 0) { +// builder.append(" | "); +// } +// builder.append("BOOLEAN"); +// } +// if (builder.length() == 0) { +// return "0"; +// } +// return builder.toString(); +// } +// +// public int compareTo(AttributeName other) { +// int thisHash = this.hash(); +// int otherHash = other.hash(); +// if (thisHash < otherHash) { +// return -1; +// } else if (thisHash == otherHash) { +// return 0; +// } else { +// return 1; +// } +// } +// +// private String formatPrefix() { +// if (prefix[0] == null && prefix[1] == null && prefix[2] == null +// && prefix[3] == null) { +// return "ALL_NO_PREFIX"; +// } else if (prefix[0] == null && prefix[1] == prefix[2] +// && prefix[3] == null) { +// if ("xmlns".equals(prefix[1])) { +// return "XMLNS_PREFIX"; +// } else if ("xml".equals(prefix[1])) { +// return "XML_PREFIX"; +// } else if ("xlink".equals(prefix[1])) { +// return "XLINK_PREFIX"; +// } else { +// throw new IllegalStateException(); +// } +// } else if (prefix[0] == null && prefix[1] == null && prefix[2] == null +// && prefix[3] == "xml") { +// return "LANG_PREFIX"; +// } else { +// throw new IllegalStateException(); +// } +// } +// +// private String formatLocal() { +// if (local[0] == local[1] && local[0] == local[3] +// && local[0] != local[2]) { +// return "SVG_DIFFERENT(\"" + local[0] + "\", \"" + local[2] + "\")"; +// } +// if (local[0] == local[2] && local[0] == local[3] +// && local[0] != local[1]) { +// return "MATH_DIFFERENT(\"" + local[0] + "\", \"" + local[1] + "\")"; +// } +// if (local[0] == local[3] && local[1] == local[2] +// && local[0] != local[1]) { +// return "COLONIFIED_LOCAL(\"" + local[0] + "\", \"" + local[1] +// + "\")"; +// } +// for (int i = 1; i < local.length; i++) { +// if (local[0] != local[i]) { +// throw new IllegalStateException(); +// } +// } +// return "SAME_LOCAL(\"" + local[0] + "\")"; +// } +// +// private String formatNs() { +// if (uri[0] == "" && uri[1] == "" && uri[2] == "" && uri[3] == "") { +// return "ALL_NO_NS"; +// } else if (uri[0] == "" && uri[1] == uri[2] && uri[3] == "") { +// if ("http://www.w3.org/2000/xmlns/".equals(uri[1])) { +// return "XMLNS_NS"; +// } else if ("http://www.w3.org/XML/1998/namespace".equals(uri[1])) { +// return "XML_NS"; +// } else if ("http://www.w3.org/1999/xlink".equals(uri[1])) { +// return "XLINK_NS"; +// } else { +// throw new IllegalStateException(); +// } +// } else if (uri[0] == "" && uri[1] == "" && uri[2] == "" +// && uri[3] == "http://www.w3.org/XML/1998/namespace") { +// return "LANG_NS"; +// } else { +// throw new IllegalStateException(); +// } +// } +// +// private String constName() { +// String name = getLocal(HTML); +// char[] buf = new char[name.length()]; +// for (int i = 0; i < name.length(); i++) { +// char c = name.charAt(i); +// if (c == '-' || c == ':') { +// buf[i] = '_'; +// } else if (c >= 'a' && c <= 'z') { +// buf[i] = (char) (c - 0x20); +// } else { +// buf[i] = c; +// } +// } +// return new String(buf); +// } +// +// private int hash() { +// String name = getLocal(HTML); +// return bufToHash(name.toCharArray(), name.length()); +// } +// +// private static void fillLevelOrderArray(List<AttributeName> sorted, int depth, +// int rootIdx, AttributeName[] levelOrder) { +// if (rootIdx >= levelOrder.length) { +// return; +// } +// +// if (depth > 0) { +// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 1, levelOrder); +// } +// +// if (!sorted.isEmpty()) { +// levelOrder[rootIdx] = sorted.remove(0); +// } +// +// if (depth > 0) { +// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 2, levelOrder); +// } +// } +// +// /** +// * Regenerate self +// * +// * @param args +// */ +// public static void main(String[] args) { +// Arrays.sort(ATTRIBUTE_NAMES); +// for (int i = 0; i < ATTRIBUTE_NAMES.length; i++) { +// int hash = ATTRIBUTE_NAMES[i].hash(); +// if (hash < 0) { +// System.err.println("Negative hash: " + ATTRIBUTE_NAMES[i].local[0]); +// return; +// } +// for (int j = i + 1; j < ATTRIBUTE_NAMES.length; j++) { +// if (hash == ATTRIBUTE_NAMES[j].hash()) { +// System.err.println( +// "Hash collision: " + ATTRIBUTE_NAMES[i].local[0] + ", " +// + ATTRIBUTE_NAMES[j].local[0]); +// return; +// } +// } +// } +// for (int i = 0; i < ATTRIBUTE_NAMES.length; i++) { +// AttributeName att = ATTRIBUTE_NAMES[i]; +// System.out.println("public static final AttributeName " +// + att.constName() + " = new AttributeName" + att.toString() +// + ";"); +// } +// +// LinkedList<AttributeName> sortedNames = new LinkedList<AttributeName>(); +// Collections.addAll(sortedNames, ATTRIBUTE_NAMES); +// AttributeName[] levelOrder = new AttributeName[ATTRIBUTE_NAMES.length]; +// int bstDepth = (int) Math.ceil(Math.log(ATTRIBUTE_NAMES.length) / Math.log(2)); +// fillLevelOrderArray(sortedNames, bstDepth, 0, levelOrder); +// +// System.out.println("private final static @NoLength AttributeName[] ATTRIBUTE_NAMES = {"); +// for (int i = 0; i < levelOrder.length; i++) { +// AttributeName att = levelOrder[i]; +// System.out.println(att.constName() + ","); +// } +// System.out.println("};"); +// System.out.println("private final static int[] ATTRIBUTE_HASHES = {"); +// for (int i = 0; i < levelOrder.length; i++) { +// AttributeName att = levelOrder[i]; +// System.out.println(Integer.toString(att.hash()) + ","); +// } +// System.out.println("};"); +// } + + // START GENERATED CODE + public static final AttributeName ALT = new AttributeName(ALL_NO_NS, SAME_LOCAL("alt"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DIR = new AttributeName(ALL_NO_NS, SAME_LOCAL("dir"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName DUR = new AttributeName(ALL_NO_NS, SAME_LOCAL("dur"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName END = new AttributeName(ALL_NO_NS, SAME_LOCAL("end"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("for"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName IN2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("in2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LOW = new AttributeName(ALL_NO_NS, SAME_LOCAL("low"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("min"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MAX = new AttributeName(ALL_NO_NS, SAME_LOCAL("max"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REL = new AttributeName(ALL_NO_NS, SAME_LOCAL("rel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REV = new AttributeName(ALL_NO_NS, SAME_LOCAL("rev"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SRC = new AttributeName(ALL_NO_NS, SAME_LOCAL("src"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName D = new AttributeName(ALL_NO_NS, SAME_LOCAL("d"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName R = new AttributeName(ALL_NO_NS, SAME_LOCAL("r"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName X = new AttributeName(ALL_NO_NS, SAME_LOCAL("x"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName Y = new AttributeName(ALL_NO_NS, SAME_LOCAL("y"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName Z = new AttributeName(ALL_NO_NS, SAME_LOCAL("z"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName K1 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k1"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName X1 = new AttributeName(ALL_NO_NS, SAME_LOCAL("x1"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName Y1 = new AttributeName(ALL_NO_NS, SAME_LOCAL("y1"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName K2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName X2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("x2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName Y2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("y2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName K3 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k3"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName K4 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k4"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName XML_SPACE = new AttributeName(XML_NS, COLONIFIED_LOCAL("xml:space", "space"), XML_PREFIX, NCNAME_FOREIGN); + public static final AttributeName XML_LANG = new AttributeName(XML_NS, COLONIFIED_LOCAL("xml:lang", "lang"), XML_PREFIX, NCNAME_FOREIGN); + public static final AttributeName ARIA_GRAB = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-grab"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_VALUEMAX = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-valuemax"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_LABELLEDBY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-labelledby"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_DESCRIBEDBY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-describedby"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_DISABLED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-disabled"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_CHECKED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-checked"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_SELECTED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-selected"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_DROPEFFECT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-dropeffect"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_REQUIRED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-required"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_EXPANDED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-expanded"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_PRESSED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-pressed"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_LEVEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-level"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_CHANNEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-channel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_HIDDEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-hidden"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_SECRET = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-secret"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_POSINSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-posinset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_ATOMIC = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-atomic"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_INVALID = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-invalid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_TEMPLATEID = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-templateid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_VALUEMIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-valuemin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_MULTISELECTABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-multiselectable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_CONTROLS = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-controls"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_MULTILINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-multiline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_READONLY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-readonly"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_OWNS = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-owns"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_ACTIVEDESCENDANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-activedescendant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_RELEVANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-relevant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_DATATYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-datatype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_VALUENOW = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-valuenow"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_SORT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-sort"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_AUTOCOMPLETE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-autocomplete"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_FLOWTO = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-flowto"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_BUSY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-busy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_LIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-live"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_HASPOPUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-haspopup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARIA_SETSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-setsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLEAR = new AttributeName(ALL_NO_NS, SAME_LOCAL("clear"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName DISABLED = new AttributeName(ALL_NO_NS, SAME_LOCAL("disabled"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName DEFAULT = new AttributeName(ALL_NO_NS, SAME_LOCAL("default"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName DATA = new AttributeName(ALL_NO_NS, SAME_LOCAL("data"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName EQUALCOLUMNS = new AttributeName(ALL_NO_NS, SAME_LOCAL("equalcolumns"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName EQUALROWS = new AttributeName(ALL_NO_NS, SAME_LOCAL("equalrows"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("hspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ISMAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("ismap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName LOCAL = new AttributeName(ALL_NO_NS, SAME_LOCAL("local"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("lspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MOVABLELIMITS = new AttributeName(ALL_NO_NS, SAME_LOCAL("movablelimits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName NOTATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("notation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDATAAVAILABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondataavailable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONPASTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onpaste"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("rspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ROWALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowalign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ROTATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("rotate"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SEPARATOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("separator"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SEPARATORS = new AttributeName(ALL_NO_NS, SAME_LOCAL("separators"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("vspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName XCHANNELSELECTOR = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("xchannelselector", "xChannelSelector"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName YCHANNELSELECTOR = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("ychannelselector", "yChannelSelector"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ENABLE_BACKGROUND = new AttributeName(ALL_NO_NS, SAME_LOCAL("enable-background"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDBLCLICK = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondblclick"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONABORT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onabort"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CALCMODE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("calcmode", "calcMode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CHECKED = new AttributeName(ALL_NO_NS, SAME_LOCAL("checked"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName FENCE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fence"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONSCROLL = new AttributeName(ALL_NO_NS, SAME_LOCAL("onscroll"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONACTIVATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onactivate"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("spacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SPECULAREXPONENT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("specularexponent", "specularExponent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SPECULARCONSTANT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("specularconstant", "specularConstant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BORDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("border"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ID = new AttributeName(ALL_NO_NS, SAME_LOCAL("id"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName GRADIENTTRANSFORM = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("gradienttransform", "gradientTransform"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName GRADIENTUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("gradientunits", "gradientUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HIDDEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("hidden"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HEADERS = new AttributeName(ALL_NO_NS, SAME_LOCAL("headers"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LOADING = new AttributeName(ALL_NO_NS, SAME_LOCAL("loading"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName READONLY = new AttributeName(ALL_NO_NS, SAME_LOCAL("readonly"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName RENDERING_INTENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("rendering-intent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SEED = new AttributeName(ALL_NO_NS, SAME_LOCAL("seed"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SRCDOC = new AttributeName(ALL_NO_NS, SAME_LOCAL("srcdoc"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STDDEVIATION = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("stddeviation", "stdDeviation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SANDBOX = new AttributeName(ALL_NO_NS, SAME_LOCAL("sandbox"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName WORD_SPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("word-spacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACCENTUNDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("accentunder"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACCEPT_CHARSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("accept-charset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACCESSKEY = new AttributeName(ALL_NO_NS, SAME_LOCAL("accesskey"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACCENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("accent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACCEPT = new AttributeName(ALL_NO_NS, SAME_LOCAL("accept"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BEVELLED = new AttributeName(ALL_NO_NS, SAME_LOCAL("bevelled"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BASEFREQUENCY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("basefrequency", "baseFrequency"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BASELINE_SHIFT = new AttributeName(ALL_NO_NS, SAME_LOCAL("baseline-shift"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BASEPROFILE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("baseprofile", "baseProfile"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BASELINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("baseline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BASE = new AttributeName(ALL_NO_NS, SAME_LOCAL("base"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("code"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CODETYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("codetype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CODEBASE = new AttributeName(ALL_NO_NS, SAME_LOCAL("codebase"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CITE = new AttributeName(ALL_NO_NS, SAME_LOCAL("cite"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DEFER = new AttributeName(ALL_NO_NS, SAME_LOCAL("defer"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName DATETIME = new AttributeName(ALL_NO_NS, SAME_LOCAL("datetime"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DIRECTION = new AttributeName(ALL_NO_NS, SAME_LOCAL("direction"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName EDGEMODE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("edgemode", "edgeMode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName EDGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("edge"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ENTERKEYHINT = new AttributeName(ALL_NO_NS, SAME_LOCAL("enterkeyhint"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("face"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName INDEX = new AttributeName(ALL_NO_NS, SAME_LOCAL("index"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName INTERCEPT = new AttributeName(ALL_NO_NS, SAME_LOCAL("intercept"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName INTEGRITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("integrity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LINEBREAK = new AttributeName(ALL_NO_NS, SAME_LOCAL("linebreak"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LABEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("label"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LINETHICKNESS = new AttributeName(ALL_NO_NS, SAME_LOCAL("linethickness"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("mode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName NAME = new AttributeName(ALL_NO_NS, SAME_LOCAL("name"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName NORESIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("noresize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName ONBEFOREUNLOAD = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforeunload"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONREPEAT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onrepeat"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OBJECT = new AttributeName(ALL_NO_NS, SAME_LOCAL("object"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONSELECT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onselect"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ORDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("order"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OTHER = new AttributeName(ALL_NO_NS, SAME_LOCAL("other"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONRESET = new AttributeName(ALL_NO_NS, SAME_LOCAL("onreset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONREADYSTATECHANGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onreadystatechange"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMESSAGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmessage"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONBEGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbegin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONBEFOREPRINT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforeprint"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ORIENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("orient"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ORIENTATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("orientation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONBEFORECOPY = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforecopy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONSELECTSTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("onselectstart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONBEFOREPASTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforepaste"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONKEYPRESS = new AttributeName(ALL_NO_NS, SAME_LOCAL("onkeypress"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONKEYUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("onkeyup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONBEFORECUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforecut"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONKEYDOWN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onkeydown"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONRESIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onresize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REPEAT = new AttributeName(ALL_NO_NS, SAME_LOCAL("repeat"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REFERRERPOLICY = new AttributeName(ALL_NO_NS, SAME_LOCAL("referrerpolicy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RULES = new AttributeName(ALL_NO_NS, SAME_LOCAL("rules"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName ROLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("role"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REPEATCOUNT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("repeatcount", "repeatCount"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REPEATDUR = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("repeatdur", "repeatDur"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SELECTED = new AttributeName(ALL_NO_NS, SAME_LOCAL("selected"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName SIZES = new AttributeName(ALL_NO_NS, SAME_LOCAL("sizes"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SUPERSCRIPTSHIFT = new AttributeName(ALL_NO_NS, SAME_LOCAL("superscriptshift"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STRETCHY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stretchy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCHEME = new AttributeName(ALL_NO_NS, SAME_LOCAL("scheme"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SPREADMETHOD = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("spreadmethod", "spreadMethod"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SELECTION = new AttributeName(ALL_NO_NS, SAME_LOCAL("selection"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("size"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("type"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName DIFFUSECONSTANT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("diffuseconstant", "diffuseConstant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HREF = new AttributeName(ALL_NO_NS, SAME_LOCAL("href"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HREFLANG = new AttributeName(ALL_NO_NS, SAME_LOCAL("hreflang"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONAFTERPRINT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onafterprint"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PROFILE = new AttributeName(ALL_NO_NS, SAME_LOCAL("profile"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SURFACESCALE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("surfacescale", "surfaceScale"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName XREF = new AttributeName(ALL_NO_NS, SAME_LOCAL("xref"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("align"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName ALIGNMENT_BASELINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("alignment-baseline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ALIGNMENTSCOPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("alignmentscope"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DRAGGABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("draggable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("height"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName IMAGESIZES = new AttributeName(ALL_NO_NS, SAME_LOCAL("imagesizes"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName IMAGESRCSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("imagesrcset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName IMAGE_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("image-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LANGUAGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("language"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LANG = new AttributeName(LANG_NS, SAME_LOCAL("lang"), LANG_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LARGEOP = new AttributeName(ALL_NO_NS, SAME_LOCAL("largeop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LONGDESC = new AttributeName(ALL_NO_NS, SAME_LOCAL("longdesc"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LENGTHADJUST = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("lengthadjust", "lengthAdjust"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARGINHEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("marginheight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARGINWIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("marginwidth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ORIGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("origin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PING = new AttributeName(ALL_NO_NS, SAME_LOCAL("ping"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TARGET = new AttributeName(ALL_NO_NS, SAME_LOCAL("target"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TARGETX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("targetx", "targetX"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TARGETY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("targety", "targetY"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ARCHIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("archive"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HIGH = new AttributeName(ALL_NO_NS, SAME_LOCAL("high"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LIGHTING_COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("lighting-color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MATHBACKGROUND = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathbackground"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName METHOD = new AttributeName(ALL_NO_NS, SAME_LOCAL("method"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName MATHVARIANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathvariant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MATHCOLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathcolor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MATHSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName NOSHADE = new AttributeName(ALL_NO_NS, SAME_LOCAL("noshade"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName ONCHANGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onchange"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PATHLENGTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pathlength", "pathLength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PATH = new AttributeName(ALL_NO_NS, SAME_LOCAL("path"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ALTIMG = new AttributeName(ALL_NO_NS, SAME_LOCAL("altimg"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACTIONTYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("actiontype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACTION = new AttributeName(ALL_NO_NS, SAME_LOCAL("action"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACTIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("active"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName ADDITIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("additive"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BEGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("begin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DOMINANT_BASELINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("dominant-baseline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DIVISOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("divisor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DEFINITIONURL = new AttributeName(ALL_NO_NS, MATH_DIFFERENT("definitionurl", "definitionURL"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LIMITINGCONEANGLE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("limitingconeangle", "limitingConeAngle"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MEDIA = new AttributeName(ALL_NO_NS, SAME_LOCAL("media"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MANIFEST = new AttributeName(ALL_NO_NS, SAME_LOCAL("manifest"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONFINISH = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfinish"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OPTIMUM = new AttributeName(ALL_NO_NS, SAME_LOCAL("optimum"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RADIOGROUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("radiogroup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RADIUS = new AttributeName(ALL_NO_NS, SAME_LOCAL("radius"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCRIPTLEVEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("scriptlevel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCRIPTSIZEMULTIPLIER = new AttributeName(ALL_NO_NS, SAME_LOCAL("scriptsizemultiplier"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCRIPTMINSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("scriptminsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TABINDEX = new AttributeName(ALL_NO_NS, SAME_LOCAL("tabindex"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("valign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName VISIBILITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("visibility"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BACKGROUND = new AttributeName(ALL_NO_NS, SAME_LOCAL("background"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LINK = new AttributeName(ALL_NO_NS, SAME_LOCAL("link"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARKER_MID = new AttributeName(ALL_NO_NS, SAME_LOCAL("marker-mid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARKERHEIGHT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("markerheight", "markerHeight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARKER_END = new AttributeName(ALL_NO_NS, SAME_LOCAL("marker-end"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MASK = new AttributeName(ALL_NO_NS, SAME_LOCAL("mask"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARKER_START = new AttributeName(ALL_NO_NS, SAME_LOCAL("marker-start"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARKERWIDTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("markerwidth", "markerWidth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MASKUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("maskunits", "maskUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MARKERUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("markerunits", "markerUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MASKCONTENTUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("maskcontentunits", "maskContentUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName AMPLITUDE = new AttributeName(ALL_NO_NS, SAME_LOCAL("amplitude"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CELLSPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("cellspacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CELLPADDING = new AttributeName(ALL_NO_NS, SAME_LOCAL("cellpadding"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DECLARE = new AttributeName(ALL_NO_NS, SAME_LOCAL("declare"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName FILL_RULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fill-rule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FILL = new AttributeName(ALL_NO_NS, SAME_LOCAL("fill"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FILL_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("fill-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MAXLENGTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("maxlength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONCLICK = new AttributeName(ALL_NO_NS, SAME_LOCAL("onclick"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONBLUR = new AttributeName(ALL_NO_NS, SAME_LOCAL("onblur"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REPLACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("replace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName ROWLINES = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowlines"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCALE = new AttributeName(ALL_NO_NS, SAME_LOCAL("scale"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("style"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TABLEVALUES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("tablevalues", "tableValues"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TITLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("title"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName AZIMUTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("azimuth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FORMAT = new AttributeName(ALL_NO_NS, SAME_LOCAL("format"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FRAMEBORDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("frameborder"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FRAME = new AttributeName(ALL_NO_NS, SAME_LOCAL("frame"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName FRAMESPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("framespacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FROM = new AttributeName(ALL_NO_NS, SAME_LOCAL("from"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FORM = new AttributeName(ALL_NO_NS, SAME_LOCAL("form"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PROMPT = new AttributeName(ALL_NO_NS, SAME_LOCAL("prompt"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PRIMITIVEUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("primitiveunits", "primitiveUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SYMMETRIC = new AttributeName(ALL_NO_NS, SAME_LOCAL("symmetric"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SUMMARY = new AttributeName(ALL_NO_NS, SAME_LOCAL("summary"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName USEMAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("usemap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ZOOMANDPAN = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("zoomandpan", "zoomAndPan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ASYNC = new AttributeName(ALL_NO_NS, SAME_LOCAL("async"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName ALINK = new AttributeName(ALL_NO_NS, SAME_LOCAL("alink"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName IN = new AttributeName(ALL_NO_NS, SAME_LOCAL("in"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ICON = new AttributeName(ALL_NO_NS, SAME_LOCAL("icon"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName KERNELMATRIX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("kernelmatrix", "kernelMatrix"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName KERNING = new AttributeName(ALL_NO_NS, SAME_LOCAL("kerning"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName KERNELUNITLENGTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("kernelunitlength", "kernelUnitLength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONUNLOAD = new AttributeName(ALL_NO_NS, SAME_LOCAL("onunload"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OPEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("open"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONINVALID = new AttributeName(ALL_NO_NS, SAME_LOCAL("oninvalid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONEND = new AttributeName(ALL_NO_NS, SAME_LOCAL("onend"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONINPUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("oninput"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName POINTER_EVENTS = new AttributeName(ALL_NO_NS, SAME_LOCAL("pointer-events"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName POINTS = new AttributeName(ALL_NO_NS, SAME_LOCAL("points"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName POINTSATX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pointsatx", "pointsAtX"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName POINTSATY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pointsaty", "pointsAtY"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName POINTSATZ = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pointsatz", "pointsAtZ"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("span"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STANDBY = new AttributeName(ALL_NO_NS, SAME_LOCAL("standby"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TRANSFORM_ORIGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("transform-origin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TRANSFORM = new AttributeName(ALL_NO_NS, SAME_LOCAL("transform"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VLINK = new AttributeName(ALL_NO_NS, SAME_LOCAL("vlink"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName WHEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("when"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName XLINK_HREF = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:href", "href"), XLINK_PREFIX, NCNAME_FOREIGN); + public static final AttributeName XLINK_TITLE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:title", "title"), XLINK_PREFIX, NCNAME_FOREIGN); + public static final AttributeName XLINK_ROLE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:role", "role"), XLINK_PREFIX, NCNAME_FOREIGN); + public static final AttributeName XLINK_ARCROLE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:arcrole", "arcrole"), XLINK_PREFIX, NCNAME_FOREIGN); + public static final AttributeName XMLNS_XLINK = new AttributeName(XMLNS_NS, COLONIFIED_LOCAL("xmlns:xlink", "xlink"), XMLNS_PREFIX, IS_XMLNS); + public static final AttributeName XMLNS = new AttributeName(XMLNS_NS, SAME_LOCAL("xmlns"), ALL_NO_PREFIX, IS_XMLNS); + public static final AttributeName XLINK_TYPE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:type", "type"), XLINK_PREFIX, NCNAME_FOREIGN); + public static final AttributeName XLINK_SHOW = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:show", "show"), XLINK_PREFIX, NCNAME_FOREIGN); + public static final AttributeName XLINK_ACTUATE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:actuate", "actuate"), XLINK_PREFIX, NCNAME_FOREIGN); + public static final AttributeName AUTOPLAY = new AttributeName(ALL_NO_NS, SAME_LOCAL("autoplay"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName AUTOCOMPLETE = new AttributeName(ALL_NO_NS, SAME_LOCAL("autocomplete"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName AUTOFOCUS = new AttributeName(ALL_NO_NS, SAME_LOCAL("autofocus"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName AUTOCAPITALIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("autocapitalize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BGCOLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("bgcolor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLOR_PROFILE = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-profile"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLOR_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLOR_INTERPOLATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-interpolation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLOR_INTERPOLATION_FILTERS = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-interpolation-filters"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ENCODING = new AttributeName(ALL_NO_NS, SAME_LOCAL("encoding"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName EXPONENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("exponent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FLOOD_COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("flood-color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FLOOD_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("flood-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LQUOTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("lquote"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName NUMOCTAVES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("numoctaves", "numOctaves"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName NOMODULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("nomodule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName ONLOAD = new AttributeName(ALL_NO_NS, SAME_LOCAL("onload"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSEWHEEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmousewheel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSEENTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseenter"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSEOVER = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseover"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONFOCUSIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfocusin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONCONTEXTMENU = new AttributeName(ALL_NO_NS, SAME_LOCAL("oncontextmenu"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONZOOM = new AttributeName(ALL_NO_NS, SAME_LOCAL("onzoom"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONCOPY = new AttributeName(ALL_NO_NS, SAME_LOCAL("oncopy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSELEAVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseleave"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSEMOVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmousemove"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSEUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONFOCUS = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfocus"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSEOUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseout"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONFOCUSOUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfocusout"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONMOUSEDOWN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmousedown"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TO = new AttributeName(ALL_NO_NS, SAME_LOCAL("to"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RQUOTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("rquote"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STROKE_LINECAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-linecap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STROKE_DASHARRAY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-dasharray"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STROKE_DASHOFFSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-dashoffset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STROKE_LINEJOIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-linejoin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STROKE_MITERLIMIT = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-miterlimit"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STROKE = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCROLLING = new AttributeName(ALL_NO_NS, SAME_LOCAL("scrolling"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName STROKE_WIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-width"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STROKE_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COMPACT = new AttributeName(ALL_NO_NS, SAME_LOCAL("compact"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName CLIP = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLIP_RULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip-rule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLIP_PATH = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip-path"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLIPPATHUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("clippathunits", "clipPathUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DISPLAY = new AttributeName(ALL_NO_NS, SAME_LOCAL("display"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DISPLAYSTYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("displaystyle"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName GLYPH_ORIENTATION_VERTICAL = new AttributeName(ALL_NO_NS, SAME_LOCAL("glyph-orientation-vertical"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName GLYPH_ORIENTATION_HORIZONTAL = new AttributeName(ALL_NO_NS, SAME_LOCAL("glyph-orientation-horizontal"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName GLYPHREF = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("glyphref", "glyphRef"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName HTTP_EQUIV = new AttributeName(ALL_NO_NS, SAME_LOCAL("http-equiv"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName KEYPOINTS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("keypoints", "keyPoints"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LOOP = new AttributeName(ALL_NO_NS, SAME_LOCAL("loop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PROPERTY = new AttributeName(ALL_NO_NS, SAME_LOCAL("property"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCOPED = new AttributeName(ALL_NO_NS, SAME_LOCAL("scoped"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STEP = new AttributeName(ALL_NO_NS, SAME_LOCAL("step"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName SHAPE_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("shape-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SCOPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("scope"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName SHAPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("shape"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName SLOPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("slope"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STOP_COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("stop-color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STOP_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stop-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TEMPLATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("template"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName WRAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("wrap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ABBR = new AttributeName(ALL_NO_NS, SAME_LOCAL("abbr"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ATTRIBUTENAME = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("attributename", "attributeName"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ATTRIBUTETYPE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("attributetype", "attributeType"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CHAR = new AttributeName(ALL_NO_NS, SAME_LOCAL("char"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COORDS = new AttributeName(ALL_NO_NS, SAME_LOCAL("coords"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CHAROFF = new AttributeName(ALL_NO_NS, SAME_LOCAL("charoff"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CHARSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("charset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName NOWRAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("nowrap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName NOHREF = new AttributeName(ALL_NO_NS, SAME_LOCAL("nohref"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName ONDRAG = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondrag"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDRAGENTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragenter"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDRAGOVER = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragover"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDRAGEND = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragend"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDROP = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondrop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDRAGDROP = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragdrop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONERROR = new AttributeName(ALL_NO_NS, SAME_LOCAL("onerror"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OPERATOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("operator"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OVERFLOW = new AttributeName(ALL_NO_NS, SAME_LOCAL("overflow"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDRAGSTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragstart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONDRAGLEAVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragleave"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STARTOFFSET = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("startoffset", "startOffset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName START = new AttributeName(ALL_NO_NS, SAME_LOCAL("start"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName AS = new AttributeName(ALL_NO_NS, SAME_LOCAL("as"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName AXIS = new AttributeName(ALL_NO_NS, SAME_LOCAL("axis"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BIAS = new AttributeName(ALL_NO_NS, SAME_LOCAL("bias"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLSPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("colspan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLASSID = new AttributeName(ALL_NO_NS, SAME_LOCAL("classid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CROSSORIGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("crossorigin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLS = new AttributeName(ALL_NO_NS, SAME_LOCAL("cols"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CURSOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("cursor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLOSURE = new AttributeName(ALL_NO_NS, SAME_LOCAL("closure"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLOSE = new AttributeName(ALL_NO_NS, SAME_LOCAL("close"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CLASS = new AttributeName(ALL_NO_NS, SAME_LOCAL("class"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName IS = new AttributeName(ALL_NO_NS, SAME_LOCAL("is"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName KEYSYSTEM = new AttributeName(ALL_NO_NS, SAME_LOCAL("keysystem"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName KEYSPLINES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("keysplines", "keySplines"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LOWSRC = new AttributeName(ALL_NO_NS, SAME_LOCAL("lowsrc"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MAXSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("maxsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MINSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("minsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName OFFSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("offset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PRESERVEALPHA = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("preservealpha", "preserveAlpha"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PRESERVEASPECTRATIO = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("preserveaspectratio", "preserveAspectRatio"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ROWSPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowspan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ROWSPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowspacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ROWS = new AttributeName(ALL_NO_NS, SAME_LOCAL("rows"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SRCSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("srcset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SUBSCRIPTSHIFT = new AttributeName(ALL_NO_NS, SAME_LOCAL("subscriptshift"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VERSION = new AttributeName(ALL_NO_NS, SAME_LOCAL("version"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ALTTEXT = new AttributeName(ALL_NO_NS, SAME_LOCAL("alttext"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CONTENTEDITABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("contenteditable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CONTROLS = new AttributeName(ALL_NO_NS, SAME_LOCAL("controls"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CONTENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("content"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CONTEXTMENU = new AttributeName(ALL_NO_NS, SAME_LOCAL("contextmenu"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DEPTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("depth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ENCTYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("enctype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName FONT_STRETCH = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-stretch"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FILTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("filter"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONTWEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontweight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONT_WEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-weight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONTSTYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontstyle"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONT_STYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-style"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONTFAMILY = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontfamily"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONT_FAMILY = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-family"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONT_VARIANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-variant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONT_SIZE_ADJUST = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-size-adjust"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FILTERUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("filterunits", "filterUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONTSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FONT_SIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-size"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName KEYTIMES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("keytimes", "keyTimes"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LETTER_SPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("letter-spacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName LIST = new AttributeName(ALL_NO_NS, SAME_LOCAL("list"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName MULTIPLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("multiple"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName RT = new AttributeName(ALL_NO_NS, SAME_LOCAL("rt"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONSTOP = new AttributeName(ALL_NO_NS, SAME_LOCAL("onstop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONSTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("onstart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName POSTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("poster"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PATTERNTRANSFORM = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("patterntransform", "patternTransform"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PATTERN = new AttributeName(ALL_NO_NS, SAME_LOCAL("pattern"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PATTERNUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("patternunits", "patternUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName PATTERNCONTENTUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("patterncontentunits", "patternContentUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RESTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("restart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName STITCHTILES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("stitchtiles", "stitchTiles"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName SYSTEMLANGUAGE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("systemlanguage", "systemLanguage"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TEXT_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("text-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TEXT_DECORATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("text-decoration"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TEXT_ANCHOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("text-anchor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TEXTLENGTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("textlength", "textLength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName TEXT = new AttributeName(ALL_NO_NS, SAME_LOCAL("text"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName WRITING_MODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("writing-mode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName WIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("width"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ACCUMULATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("accumulate"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLUMNSPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnspan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLUMNLINES = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnlines"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLUMNALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnalign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLUMNSPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnspacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName COLUMNWIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnwidth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName GROUPALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("groupalign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName INPUTMODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("inputmode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONSUBMIT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onsubmit"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ONCUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("oncut"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REQUIRED = new AttributeName(ALL_NO_NS, SAME_LOCAL("required"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN); + public static final AttributeName REQUIREDFEATURES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("requiredfeatures", "requiredFeatures"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RESULT = new AttributeName(ALL_NO_NS, SAME_LOCAL("result"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REQUIREDEXTENSIONS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("requiredextensions", "requiredExtensions"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VALUES = new AttributeName(ALL_NO_NS, SAME_LOCAL("values"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VALUETYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("valuetype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED); + public static final AttributeName VALUE = new AttributeName(ALL_NO_NS, SAME_LOCAL("value"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName ELEVATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("elevation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VIEWTARGET = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("viewtarget", "viewTarget"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName VIEWBOX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("viewbox", "viewBox"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CX = new AttributeName(ALL_NO_NS, SAME_LOCAL("cx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DX = new AttributeName(ALL_NO_NS, SAME_LOCAL("dx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FX = new AttributeName(ALL_NO_NS, SAME_LOCAL("fx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RX = new AttributeName(ALL_NO_NS, SAME_LOCAL("rx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REFX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("refx", "refX"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName BY = new AttributeName(ALL_NO_NS, SAME_LOCAL("by"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName CY = new AttributeName(ALL_NO_NS, SAME_LOCAL("cy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName DY = new AttributeName(ALL_NO_NS, SAME_LOCAL("dy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName FY = new AttributeName(ALL_NO_NS, SAME_LOCAL("fy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName RY = new AttributeName(ALL_NO_NS, SAME_LOCAL("ry"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + public static final AttributeName REFY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("refy", "refY"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG); + private final static @NoLength AttributeName[] ATTRIBUTE_NAMES = { + FILL, + DATETIME, + CHAROFF, + CLEAR, + IMAGESRCSET, + COLOR, + LETTER_SPACING, + ARIA_DISABLED, + SPECULAREXPONENT, + ONKEYUP, + DOMINANT_BASELINE, + OPEN, + SCROLLING, + MAXSIZE, + REQUIREDFEATURES, + Y, + ARIA_MULTISELECTABLE, + ROTATE, + ACCENTUNDER, + ONREPEAT, + SELECTION, + LIGHTING_COLOR, + BACKGROUND, + FROM, + XLINK_TITLE, + ONCOPY, + PROPERTY, + START, + DEPTH, + TEXT_ANCHOR, + RX, + MIN, + K3, + ARIA_CHANNEL, + ARIA_VALUENOW, + LOCAL, + ONABORT, + LOADING, + BASEPROFILE, + INTEGRITY, + ONBEGIN, + REPEATCOUNT, + SURFACESCALE, + MARGINWIDTH, + PATHLENGTH, + RADIOGROUP, + MASKUNITS, + STYLE, + ASYNC, + POINTSATZ, + AUTOPLAY, + NOMODULE, + TO, + DISPLAY, + STOP_OPACITY, + ONDROP, + CURSOR, + SRCSET, + FONTFAMILY, + PATTERN, + COLUMNALIGN, + VIEWBOX, + DY, + END, + SRC, + Y1, + ARIA_GRAB, + ARIA_REQUIRED, + ARIA_ATOMIC, + ARIA_OWNS, + ARIA_BUSY, + EQUALCOLUMNS, + ONDATAAVAILABLE, + XCHANNELSELECTOR, + ONSCROLL, + GRADIENTTRANSFORM, + SRCDOC, + ACCEPT, + CODETYPE, + ENTERKEYHINT, + MODE, + OTHER, + ONBEFORECOPY, + REPEAT, + SUPERSCRIPTSHIFT, + HREF, + ALIGNMENTSCOPE, + LARGEOP, + TARGETX, + MATHCOLOR, + ACTION, + MEDIA, + SCRIPTMINSIZE, + MARKER_END, + CELLSPACING, + ONBLUR, + FORMAT, + SYMMETRIC, + KERNELMATRIX, + POINTER_EVENTS, + TRANSFORM, + XMLNS, + BGCOLOR, + FLOOD_COLOR, + ONMOUSEOVER, + ONFOCUS, + STROKE_DASHOFFSET, + CLIP, + GLYPHREF, + SCOPE, + ATTRIBUTENAME, + ONDRAG, + OVERFLOW, + COLSPAN, + IS, + PRESERVEASPECTRATIO, + CONTENTEDITABLE, + FONTWEIGHT, + FILTERUNITS, + ONSTOP, + STITCHTILES, + WIDTH, + INPUTMODE, + VALUETYPE, + DX, + BY, + RY, + DIR, + IN2, + REL, + R, + K1, + X2, + XML_SPACE, + ARIA_LABELLEDBY, + ARIA_SELECTED, + ARIA_PRESSED, + ARIA_SECRET, + ARIA_TEMPLATEID, + ARIA_MULTILINE, + ARIA_RELEVANT, + ARIA_AUTOCOMPLETE, + ARIA_HASPOPUP, + DEFAULT, + HSPACE, + MOVABLELIMITS, + RSPACE, + SEPARATORS, + ENABLE_BACKGROUND, + CHECKED, + OPACITY, + BORDER, + HIDDEN, + RENDERING_INTENT, + SANDBOX, + ACCESSKEY, + BASEFREQUENCY, + BASE, + CITE, + EDGEMODE, + INDEX, + LABEL, + NORESIZE, + ONSELECT, + ONREADYSTATECHANGE, + ORIENT, + ONBEFOREPASTE, + ONKEYDOWN, + RULES, + SELECTED, + SCHEME, + TYPE, + ONAFTERPRINT, + ALIGN, + HEIGHT, + LANGUAGE, + LENGTHADJUST, + PING, + ARCHIVE, + METHOD, + NOSHADE, + ALTIMG, + ADDITIVE, + DEFINITIONURL, + ONFINISH, + SCRIPTLEVEL, + VALIGN, + MARKER_MID, + MARKER_START, + MASKCONTENTUNITS, + DECLARE, + MAXLENGTH, + ROWLINES, + TITLE, + FRAME, + PROMPT, + USEMAP, + IN, + KERNELUNITLENGTH, + ONEND, + POINTSATX, + STANDBY, + WHEN, + XLINK_ARCROLE, + XLINK_SHOW, + AUTOFOCUS, + COLOR_RENDERING, + ENCODING, + LQUOTE, + ONMOUSEWHEEL, + ONCONTEXTMENU, + ONMOUSEMOVE, + ONFOCUSOUT, + STROKE_LINECAP, + STROKE_MITERLIMIT, + STROKE_OPACITY, + CLIP_PATH, + GLYPH_ORIENTATION_VERTICAL, + KEYPOINTS, + STEP, + SLOPE, + WRAP, + CHAR, + NOWRAP, + ONDRAGOVER, + ONERROR, + ONDRAGLEAVE, + AXIS, + CROSSORIGIN, + CLOSE, + KEYSPLINES, + OFFSET, + ROWSPACING, + VERSION, + CONTENT, + FONT_STRETCH, + FONTSTYLE, + FONT_VARIANT, + FONT_SIZE, + MULTIPLE, + POSTER, + PATTERNCONTENTUNITS, + TEXT_RENDERING, + TEXT, + COLUMNSPAN, + COLUMNWIDTH, + ONCUT, + REQUIREDEXTENSIONS, + ELEVATION, + CX, + FX, + REFX, + CY, + FY, + REFY, + ALT, + DUR, + FOR, + LOW, + MAX, + REV, + D, + X, + Z, + X1, + K2, + Y2, + K4, + XML_LANG, + ARIA_VALUEMAX, + ARIA_DESCRIBEDBY, + ARIA_CHECKED, + ARIA_DROPEFFECT, + ARIA_EXPANDED, + ARIA_LEVEL, + ARIA_HIDDEN, + ARIA_POSINSET, + ARIA_INVALID, + ARIA_VALUEMIN, + ARIA_CONTROLS, + ARIA_READONLY, + ARIA_ACTIVEDESCENDANT, + ARIA_DATATYPE, + ARIA_SORT, + ARIA_FLOWTO, + ARIA_LIVE, + ARIA_SETSIZE, + DISABLED, + DATA, + EQUALROWS, + ISMAP, + LSPACE, + NOTATION, + ONPASTE, + ROWALIGN, + SEPARATOR, + VSPACE, + YCHANNELSELECTOR, + ONDBLCLICK, + CALCMODE, + FENCE, + ONACTIVATE, + SPACING, + SPECULARCONSTANT, + ID, + GRADIENTUNITS, + HEADERS, + READONLY, + SEED, + STDDEVIATION, + WORD_SPACING, + ACCEPT_CHARSET, + ACCENT, + BEVELLED, + BASELINE_SHIFT, + BASELINE, + CODE, + CODEBASE, + DEFER, + DIRECTION, + EDGE, + FACE, + INTERCEPT, + LINEBREAK, + LINETHICKNESS, + NAME, + ONBEFOREUNLOAD, + OBJECT, + ORDER, + ONRESET, + ONMESSAGE, + ONBEFOREPRINT, + ORIENTATION, + ONSELECTSTART, + ONKEYPRESS, + ONBEFORECUT, + ONRESIZE, + REFERRERPOLICY, + ROLE, + REPEATDUR, + SIZES, + STRETCHY, + SPREADMETHOD, + SIZE, + DIFFUSECONSTANT, + HREFLANG, + PROFILE, + XREF, + ALIGNMENT_BASELINE, + DRAGGABLE, + IMAGESIZES, + IMAGE_RENDERING, + LANG, + LONGDESC, + MARGINHEIGHT, + ORIGIN, + TARGET, + TARGETY, + HIGH, + MATHBACKGROUND, + MATHVARIANT, + MATHSIZE, + ONCHANGE, + PATH, + ACTIONTYPE, + ACTIVE, + BEGIN, + DIVISOR, + LIMITINGCONEANGLE, + MANIFEST, + OPTIMUM, + RADIUS, + SCRIPTSIZEMULTIPLIER, + TABINDEX, + VISIBILITY, + LINK, + MARKERHEIGHT, + MASK, + MARKERWIDTH, + MARKERUNITS, + AMPLITUDE, + CELLPADDING, + FILL_RULE, + FILL_OPACITY, + ONCLICK, + REPLACE, + SCALE, + TABLEVALUES, + AZIMUTH, + FRAMEBORDER, + FRAMESPACING, + FORM, + PRIMITIVEUNITS, + SUMMARY, + ZOOMANDPAN, + ALINK, + ICON, + KERNING, + ONUNLOAD, + ONINVALID, + ONINPUT, + POINTS, + POINTSATY, + SPAN, + TRANSFORM_ORIGIN, + VLINK, + XLINK_HREF, + XLINK_ROLE, + XMLNS_XLINK, + XLINK_TYPE, + XLINK_ACTUATE, + AUTOCOMPLETE, + AUTOCAPITALIZE, + COLOR_PROFILE, + COLOR_INTERPOLATION, + COLOR_INTERPOLATION_FILTERS, + EXPONENT, + FLOOD_OPACITY, + NUMOCTAVES, + ONLOAD, + ONMOUSEENTER, + ONFOCUSIN, + ONZOOM, + ONMOUSELEAVE, + ONMOUSEUP, + ONMOUSEOUT, + ONMOUSEDOWN, + RQUOTE, + STROKE_DASHARRAY, + STROKE_LINEJOIN, + STROKE, + STROKE_WIDTH, + COMPACT, + CLIP_RULE, + CLIPPATHUNITS, + DISPLAYSTYLE, + GLYPH_ORIENTATION_HORIZONTAL, + HTTP_EQUIV, + LOOP, + SCOPED, + SHAPE_RENDERING, + SHAPE, + STOP_COLOR, + TEMPLATE, + ABBR, + ATTRIBUTETYPE, + COORDS, + CHARSET, + NOHREF, + ONDRAGENTER, + ONDRAGEND, + ONDRAGDROP, + OPERATOR, + ONDRAGSTART, + STARTOFFSET, + AS, + BIAS, + CLASSID, + COLS, + CLOSURE, + CLASS, + KEYSYSTEM, + LOWSRC, + MINSIZE, + PRESERVEALPHA, + ROWSPAN, + ROWS, + SUBSCRIPTSHIFT, + ALTTEXT, + CONTROLS, + CONTEXTMENU, + ENCTYPE, + FILTER, + FONT_WEIGHT, + FONT_STYLE, + FONT_FAMILY, + FONT_SIZE_ADJUST, + FONTSIZE, + KEYTIMES, + LIST, + RT, + ONSTART, + PATTERNTRANSFORM, + PATTERNUNITS, + RESTART, + SYSTEMLANGUAGE, + TEXT_DECORATION, + TEXTLENGTH, + WRITING_MODE, + ACCUMULATE, + COLUMNLINES, + COLUMNSPACING, + GROUPALIGN, + ONSUBMIT, + REQUIRED, + RESULT, + VALUES, + VALUE, + VIEWTARGET, + }; + private final static int[] ATTRIBUTE_HASHES = { + 1867462756, + 1748971848, + 1966442279, + 1681174213, + 1785053243, + 1916286197, + 2004846654, + 1680165421, + 1723336432, + 1754899031, + 1816104145, + 1905628916, + 1924629705, + 1988784439, + 2024647008, + 71827457, + 1680282148, + 1689324870, + 1747295467, + 1754579720, + 1756889417, + 1803561214, + 1848600826, + 1884295780, + 1910441627, + 1922607670, + 1939976792, + 1975062341, + 2000752725, + 2009079867, + 2073034754, + 57205395, + 911736834, + 1680181996, + 1680368221, + 1685882101, + 1704526375, + 1736416327, + 1747906667, + 1751755561, + 1754698327, + 1756360955, + 1773606972, + 1787365531, + 1805715690, + 1823574314, + 1854497001, + 1874270021, + 1898415413, + 1906423097, + 1915025672, + 1921977416, + 1923088386, + 1933369607, + 1941550652, + 1972904518, + 1983398182, + 1991625270, + 2001710298, + 2007021895, + 2016810187, + 2060474743, + 2082471938, + 53006051, + 60345635, + 885522434, + 1680095865, + 1680165533, + 1680229115, + 1680343801, + 1680437801, + 1682440540, + 1687620127, + 1692408896, + 1721189160, + 1733874289, + 1740096054, + 1747479606, + 1748503880, + 1749549708, + 1753550036, + 1754644293, + 1754835516, + 1756147974, + 1756762256, + 1767725700, + 1781007934, + 1786775671, + 1791068279, + 1804081401, + 1814560070, + 1820727381, + 1824159037, + 1854366938, + 1865910331, + 1872343590, + 1884079398, + 1890996553, + 1903612236, + 1906408542, + 1908462185, + 1910503637, + 1915757815, + 1917857531, + 1922413307, + 1922677495, + 1924517489, + 1932959284, + 1934970504, + 1941435445, + 1965512429, + 1972656710, + 1972922984, + 1983157559, + 1984430082, + 1990107683, + 2000096287, + 2001634458, + 2001826027, + 2006459190, + 2008401563, + 2010716309, + 2019887833, + 2026893641, + 2065694722, + 2081423362, + 2089811970, + 52488851, + 55077603, + 59825747, + 68157441, + 878182402, + 901775362, + 1037879561, + 1680159327, + 1680165437, + 1680165692, + 1680198203, + 1680231247, + 1680315086, + 1680345965, + 1680413393, + 1680452349, + 1681879063, + 1683805446, + 1686731997, + 1689048326, + 1689839946, + 1699185409, + 1714763319, + 1721347639, + 1731048742, + 1734182982, + 1739583824, + 1740130375, + 1747309881, + 1747800157, + 1748021284, + 1748566068, + 1749350104, + 1751507685, + 1753049109, + 1754434872, + 1754612424, + 1754647074, + 1754794646, + 1754860061, + 1754927689, + 1756219733, + 1756704824, + 1756836998, + 1757421892, + 1771569964, + 1780879045, + 1784574102, + 1786622296, + 1786851500, + 1788842244, + 1797886599, + 1804054854, + 1804405895, + 1814517574, + 1814656840, + 1816178925, + 1821958888, + 1823829083, + 1825437894, + 1854285018, + 1854466380, + 1854497008, + 1866496199, + 1871251689, + 1873656984, + 1874788501, + 1884246821, + 1889569526, + 1891937366, + 1900544002, + 1903759600, + 1905754853, + 1906419001, + 1907701479, + 1909819252, + 1910441773, + 1910527802, + 1915341049, + 1916247343, + 1917295176, + 1921061206, + 1922400908, + 1922566877, + 1922665179, + 1922679610, + 1924443742, + 1924583073, + 1924773438, + 1933123337, + 1934917290, + 1937336473, + 1941286708, + 1941440197, + 1943317364, + 1966384692, + 1972151670, + 1972744954, + 1972908839, + 1972996699, + 1982254612, + 1983290011, + 1983432389, + 1987422362, + 1989522022, + 1991220282, + 1993343287, + 2000160071, + 2001527900, + 2001669449, + 2001732764, + 2001898809, + 2005342360, + 2006824246, + 2007064819, + 2009041198, + 2009231684, + 2016711994, + 2017010843, + 2023342821, + 2024794274, + 2034765641, + 2065170434, + 2066743298, + 2075005220, + 2081947650, + 2083520514, + 2091784484, + 50917059, + 52489043, + 53537523, + 56685811, + 57210387, + 59830867, + 60817409, + 71303169, + 72351745, + 884998146, + 894959618, + 902299650, + 928514050, + 1038063816, + 1680140893, + 1680159328, + 1680165436, + 1680165487, + 1680165613, + 1680181850, + 1680185931, + 1680198381, + 1680230940, + 1680251485, + 1680311085, + 1680323325, + 1680345685, + 1680347981, + 1680411449, + 1680433915, + 1680446153, + 1680511804, + 1681733672, + 1681969220, + 1682587945, + 1684319541, + 1685902598, + 1687164232, + 1687751191, + 1689130184, + 1689788441, + 1691145478, + 1692933184, + 1704262346, + 1714745560, + 1716303957, + 1721305962, + 1723309623, + 1723336528, + 1732771842, + 1733919469, + 1734404167, + 1739561208, + 1739927860, + 1740119884, + 1742183484, + 1747299630, + 1747446838, + 1747792072, + 1747839118, + 1747939528, + 1748306996, + 1748552744, + 1748869205, + 1749027145, + 1749399124, + 1749856356, + 1751679545, + 1752985897, + 1753297133, + 1754214628, + 1754546894, + 1754606246, + 1754643237, + 1754645079, + 1754647353, + 1754792749, + 1754798923, + 1754858317, + 1754872618, + 1754907227, + 1754958648, + 1756190926, + 1756302628, + 1756471625, + 1756737685, + 1756804936, + 1756874572, + 1757053236, + 1765800271, + 1767875272, + 1772032615, + 1776114564, + 1780975314, + 1782518297, + 1785051290, + 1785174319, + 1786740932, + 1786821704, + 1787193500, + 1788254870, + 1790814502, + 1791070327, + 1801312388, + 1804036350, + 1804069019, + 1804235064, + 1804978712, + 1805715716, + 1814558026, + 1814656326, + 1814986837, + 1816144023, + 1820262641, + 1820928104, + 1822002839, + 1823580230, + 1823841492, + 1824377064, + 1825677514, + 1853862084, + 1854302364, + 1854464212, + 1854474395, + 1854497003, + 1864698185, + 1865910347, + 1867448617, + 1867620412, + 1872034503, + 1873590471, + 1874261045, + 1874698443, + 1881750231, + 1884142379, + 1884267068, + 1884343396, + 1889633006, + 1891186903, + 1894552650, + 1898428101, + 1902640276, + 1903659239, + 1905541832, + 1905672729, + 1905902311, + 1906408598, + 1906421049, + 1907660596, + 1908316832, + 1909438149, + 1910328970, + 1910441770, + 1910487243, + 1910507338, + 1910572893, + 1915295948, + 1915394254, + 1916210285, + 1916278099, + 1916337499, + 1917327080, + 1917953597, + 1921894426, + 1922319046, + 1922413292, + 1922470745, + 1922567078, + 1922665052, + 1922671417, + 1922679386, + 1922699851, + 1924206934, + 1924462384, + 1924570799, + 1924585254, + 1924738716, + 1932870919, + 1932986153, + 1933145837, + 1933508940, + 1934917372, + 1935597338, + 1937777860, + 1941253366, + 1941409583, + 1941438085, + 1941454586, + 1942026440, + 1965349396, + 1965561677, + 1966439670, + 1966454567, + 1972196486, + 1972744939, + 1972863609, + 1972904522, + 1972909592, + 1972962123, + 1974849131, + 1980235778, + 1982640164, + 1983266615, + 1983347764, + 1983416119, + 1983461061, + 1987410233, + 1988132214, + 1988788535, + 1990062797, + 1991021879, + 1991392548, + 1991643278, + 1999273799, + 2000125224, + 2000162011, + 2001210183, + 2001578182, + 2001634459, + 2001669450, + 2001710299, + 2001814704, + 2001898808, + 2004199576, + 2004957380, + 2005925890, + 2006516551, + 2007019632, + 2007064812, + 2008084807, + 2008408414, + 2009071951, + 2009141482, + 2010452700, + 2015950026, + 2016787611, + 2016910397, + 2018908874, + 2023146024, + 2024616088, + 2024763702, + 2026741958, + 2026975253, + 2060302634, + }; +} diff --git a/parser/html/javasrc/ElementName.java b/parser/html/javasrc/ElementName.java new file mode 100644 index 0000000000..9ee2ad0152 --- /dev/null +++ b/parser/html/javasrc/ElementName.java @@ -0,0 +1,1896 @@ +/* + * Copyright (c) 2008-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. + */ + +package nu.validator.htmlparser.impl; + +// 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; +import nu.validator.htmlparser.annotation.NoLength; +import nu.validator.htmlparser.annotation.Unsigned; +import nu.validator.htmlparser.common.Interner; + +public final class ElementName + // uncomment when regenerating self +// implements Comparable<ElementName> +{ + + /** + * The mask for extracting the dispatch group. + */ + public static final int GROUP_MASK = 127; + + /** + * 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. + */ + public static final int SPECIAL = (1 << 29); + + /** + * The element is foster-parenting. This bit should be pre-set on elements + * that are foster-parenting as HTML. + */ + 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. + */ + public static final int SCOPING = (1 << 27); + + /** + * The element is scoping as SVG. + */ + public static final int SCOPING_AS_SVG = (1 << 26); + + /** + * The element is scoping as MathML. + */ + public static final int SCOPING_AS_MATHML = (1 << 25); + + /** + * The element is an HTML integration point. + */ + public static final int HTML_INTEGRATION_POINT = (1 << 24); + + /** + * The element has an optional end tag. + */ + public static final int OPTIONAL_END_TAG = (1 << 23); + + private @Local String name; + + 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. + */ + public final int flags; + + @Inline public @Local String getName() { + return name; + } + + @Inline public @Local String getCamelCaseName() { + 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; + } + + @Inline public int getGroup() { + return flags & ElementName.GROUP_MASK; + } + + @Inline public boolean isInterned() { + return (flags & ElementName.NOT_INTERNED) == 0; + } + + @Inline static int levelOrderBinarySearch(int[] data, int key) { + int n = data.length; + int i = 0; + + while (i < n) { + int val = data[i]; + if (val < key) { + i = 2 * i + 2; + } else if (val > key) { + i = 2 * i + 1; + } else { + return i; + } + } + + return -1; + } + + @Inline static ElementName elementNameByBuffer(@NoLength char[] buf, + int length, Interner interner) { + @Unsigned int hash = ElementName.bufToHash(buf, length); + int[] hashes; + hashes = ElementName.ELEMENT_HASHES; + int index = levelOrderBinarySearch(hashes, hash); + if (index < 0) { + return null; + } else { + ElementName elementName = ElementName.ELEMENT_NAMES[index]; + @Local String name = elementName.name; + if (!Portability.localEqualsBuffer(name, buf, length)) { + return null; + } + return elementName; + } + } + + /** + * This method has to return a unique positive integer for each well-known + * lower-cased element name. + * + * @param buf + * @param len + * @return + */ + @Inline private static @Unsigned int bufToHash(@NoLength char[] buf, + int length) { + @Unsigned int len = length; + @Unsigned int first = buf[0]; + first <<= 19; + @Unsigned int second = 1 << 23; + @Unsigned int third = 0; + @Unsigned int fourth = 0; + @Unsigned int fifth = 0; + if (length >= 4) { + second = buf[length - 4]; + second <<= 4; + third = buf[length - 3]; + third <<= 9; + fourth = buf[length - 2]; + fourth <<= 14; + fifth = buf[length - 1]; + fifth <<= 24; + } else if (length == 3) { + second = buf[1]; + second <<= 4; + third = buf[2]; + third <<= 9; + } else if (length == 2) { + second = buf[1]; + second <<= 24; + } + return len + first + second + third + fourth + fifth; + } + + 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; + } + + public void destructor() { + // The translator adds refcount debug code here. + } + + @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: @Inline public boolean isCustom() { + // CPPONLY: return this.htmlCreator == NS_NewCustomElement; + // CPPONLY: } + + 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 + "\", \n// CPP" +// + "ONLY: " + htmlCreator(name) + ",\n// CPP" + "ONLY: " +// + svgCreator(camelCaseName) + ", \n" + decomposedFlags() + ")"; +// } +// +// private String decomposedFlags() { +// StringBuilder buf = new StringBuilder("TreeBuilder."); +// buf.append(treeBuilderGroupToName()); +// if ((flags & SPECIAL) != 0) { +// buf.append(" | SPECIAL"); +// } +// if ((flags & FOSTER_PARENTING) != 0) { +// buf.append(" | FOSTER_PARENTING"); +// } +// if ((flags & SCOPING) != 0) { +// buf.append(" | SCOPING"); +// } +// if ((flags & SCOPING_AS_MATHML) != 0) { +// buf.append(" | SCOPING_AS_MATHML"); +// } +// if ((flags & SCOPING_AS_SVG) != 0) { +// buf.append(" | SCOPING_AS_SVG"); +// } +// if ((flags & OPTIONAL_END_TAG) != 0) { +// buf.append(" | OPTIONAL_END_TAG"); +// } +// return buf.toString(); +// } +// +// private String constName() { +// char[] buf = new char[name.length()]; +// for (int i = 0; i < name.length(); i++) { +// char c = name.charAt(i); +// if (c == '-') { +// if (!"annotation-xml".equals(name)) { +// throw new RuntimeException( +// "Non-annotation-xml element name with hyphen: " +// + name); +// } +// buf[i] = '_'; +// } else if (c >= '0' && c <= '9') { +// buf[i] = c; +// } else { +// buf[i] = (char) (c - 0x20); +// } +// } +// return new String(buf); +// } +// +// private int hash() { +// return bufToHash(name.toCharArray(), name.length()); +// } +// +// public int compareTo(ElementName other) { +// int thisHash = this.hash(); +// int otherHash = other.hash(); +// if (thisHash < otherHash) { +// return -1; +// } else if (thisHash == otherHash) { +// return 0; +// } else { +// return 1; +// } +// } +// +// private String treeBuilderGroupToName() { +// switch (getGroup()) { +// case TreeBuilder.OTHER: +// return "OTHER"; +// case TreeBuilder.A: +// return "A"; +// case TreeBuilder.BASE: +// return "BASE"; +// case TreeBuilder.BODY: +// return "BODY"; +// case TreeBuilder.BR: +// return "BR"; +// case TreeBuilder.BUTTON: +// return "BUTTON"; +// case TreeBuilder.CAPTION: +// return "CAPTION"; +// case TreeBuilder.COL: +// return "COL"; +// case TreeBuilder.COLGROUP: +// return "COLGROUP"; +// case TreeBuilder.FONT: +// return "FONT"; +// case TreeBuilder.FORM: +// return "FORM"; +// case TreeBuilder.FRAME: +// return "FRAME"; +// case TreeBuilder.FRAMESET: +// return "FRAMESET"; +// case TreeBuilder.IMAGE: +// return "IMAGE"; +// case TreeBuilder.INPUT: +// return "INPUT"; +// case TreeBuilder.LI: +// return "LI"; +// case TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND: +// return "LINK_OR_BASEFONT_OR_BGSOUND"; +// case TreeBuilder.MATH: +// return "MATH"; +// case TreeBuilder.META: +// return "META"; +// case TreeBuilder.SVG: +// return "SVG"; +// case TreeBuilder.HEAD: +// return "HEAD"; +// case TreeBuilder.HR: +// return "HR"; +// case TreeBuilder.HTML: +// return "HTML"; +// case TreeBuilder.KEYGEN: +// return "KEYGEN"; +// case TreeBuilder.NOBR: +// return "NOBR"; +// case TreeBuilder.NOFRAMES: +// return "NOFRAMES"; +// case TreeBuilder.NOSCRIPT: +// return "NOSCRIPT"; +// case TreeBuilder.OPTGROUP: +// return "OPTGROUP"; +// case TreeBuilder.OPTION: +// return "OPTION"; +// case TreeBuilder.P: +// return "P"; +// case TreeBuilder.PLAINTEXT: +// return "PLAINTEXT"; +// case TreeBuilder.SCRIPT: +// return "SCRIPT"; +// case TreeBuilder.SELECT: +// return "SELECT"; +// case TreeBuilder.STYLE: +// return "STYLE"; +// case TreeBuilder.TABLE: +// return "TABLE"; +// case TreeBuilder.TEXTAREA: +// return "TEXTAREA"; +// case TreeBuilder.TITLE: +// return "TITLE"; +// case TreeBuilder.TEMPLATE: +// return "TEMPLATE"; +// case TreeBuilder.TR: +// return "TR"; +// case TreeBuilder.XMP: +// return "XMP"; +// case TreeBuilder.TBODY_OR_THEAD_OR_TFOOT: +// return "TBODY_OR_THEAD_OR_TFOOT"; +// case TreeBuilder.TD_OR_TH: +// return "TD_OR_TH"; +// case TreeBuilder.DD_OR_DT: +// return "DD_OR_DT"; +// case TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: +// return "H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6"; +// case TreeBuilder.OBJECT: +// return "OBJECT"; +// case TreeBuilder.OUTPUT: +// return "OUTPUT"; +// case TreeBuilder.MARQUEE_OR_APPLET: +// return "MARQUEE_OR_APPLET"; +// case TreeBuilder.PRE_OR_LISTING: +// return "PRE_OR_LISTING"; +// case TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: +// return "B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U"; +// case TreeBuilder.UL_OR_OL_OR_DL: +// return "UL_OR_OL_OR_DL"; +// case TreeBuilder.IFRAME: +// return "IFRAME"; +// case TreeBuilder.NOEMBED: +// return "NOEMBED"; +// case TreeBuilder.EMBED: +// return "EMBED"; +// case TreeBuilder.IMG: +// return "IMG"; +// case TreeBuilder.AREA_OR_WBR: +// return "AREA_OR_WBR"; +// case TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: +// return "DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU"; +// case TreeBuilder.FIELDSET: +// return "FIELDSET"; +// case TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: +// return "ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY"; +// case TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR: +// return "RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR"; +// case TreeBuilder.RB_OR_RTC: +// return "RB_OR_RTC"; +// case TreeBuilder.RT_OR_RP: +// return "RT_OR_RP"; +// case TreeBuilder.PARAM_OR_SOURCE_OR_TRACK: +// return "PARAM_OR_SOURCE_OR_TRACK"; +// case TreeBuilder.MGLYPH_OR_MALIGNMARK: +// return "MGLYPH_OR_MALIGNMARK"; +// case TreeBuilder.MI_MO_MN_MS_MTEXT: +// return "MI_MO_MN_MS_MTEXT"; +// case TreeBuilder.ANNOTATION_XML: +// return "ANNOTATION_XML"; +// case TreeBuilder.FOREIGNOBJECT_OR_DESC: +// return "FOREIGNOBJECT_OR_DESC"; +// } +// return null; +// } +// +// private static void fillLevelOrderArray(List<ElementName> sorted, int depth, +// int rootIdx, ElementName[] levelOrder) { +// if (rootIdx >= levelOrder.length) { +// return; +// } +// +// if (depth > 0) { +// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 1, levelOrder); +// } +// +// if (!sorted.isEmpty()) { +// levelOrder[rootIdx] = sorted.remove(0); +// } +// +// if (depth > 0) { +// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 2, levelOrder); +// } +// } +// +// /** +// * Regenerate self +// * +// * 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(); +// if (hash < 0) { +// System.err.println("Negative hash: " + ELEMENT_NAMES[i].name); +// return; +// } +// 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); +// return; +// } +// } +// } +// for (int i = 0; i < ELEMENT_NAMES.length; i++) { +// ElementName el = ELEMENT_NAMES[i]; +// 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)); +// fillLevelOrderArray(sortedNames, bstDepth, 0, levelOrder); +// +// 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() + ","); +// } +// System.out.println("};"); +// System.out.println("private final static int[] ELEMENT_HASHES = {"); +// for (int i = 0; i < levelOrder.length; i++) { +// ElementName el = levelOrder[i]; +// 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()); +// } +// } + + // START GENERATED CODE +public static final ElementName BIG = new ElementName("big", "big", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName BDI = new ElementName("bdi", "bdi", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName BDO = new ElementName("bdo", "bdo", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName COL = new ElementName("col", "col", +// CPPONLY: NS_NewHTMLTableColElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.COL | SPECIAL); +public static final ElementName DEL = new ElementName("del", "del", +// CPPONLY: NS_NewHTMLModElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName DFN = new ElementName("dfn", "dfn", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName DIR = new ElementName("dir", "dir", +// CPPONLY: NS_NewHTMLSharedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName DIV = new ElementName("div", "div", +// CPPONLY: NS_NewHTMLDivElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); +public static final ElementName IMG = new ElementName("img", "img", +// CPPONLY: NS_NewHTMLImageElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.IMG | SPECIAL); +public static final ElementName INS = new ElementName("ins", "ins", +// CPPONLY: NS_NewHTMLModElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName KBD = new ElementName("kbd", "kbd", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName MAP = new ElementName("map", "map", +// CPPONLY: NS_NewHTMLMapElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName NAV = new ElementName("nav", "nav", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName PRE = new ElementName("pre", "pre", +// CPPONLY: NS_NewHTMLPreElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.PRE_OR_LISTING | SPECIAL); +public static final ElementName A = new ElementName("a", "a", +// CPPONLY: NS_NewHTMLAnchorElement, +// CPPONLY: NS_NewSVGAElement, +TreeBuilder.A); +public static final ElementName B = new ElementName("b", "b", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName RTC = new ElementName("rtc", "rtc", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RB_OR_RTC | OPTIONAL_END_TAG); +public static final ElementName SUB = new ElementName("sub", "sub", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); +public static final ElementName SVG = new ElementName("svg", "svg", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGSVGElement, +TreeBuilder.SVG); +public static final ElementName SUP = new ElementName("sup", "sup", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); +public static final ElementName SET = new ElementName("set", "set", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGSetElement, +TreeBuilder.OTHER); +public static final ElementName USE = new ElementName("use", "use", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUseElement, +TreeBuilder.OTHER); +public static final ElementName VAR = new ElementName("var", "var", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); +public static final ElementName G = new ElementName("g", "g", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGGElement, +TreeBuilder.OTHER); +public static final ElementName WBR = new ElementName("wbr", "wbr", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.AREA_OR_WBR | SPECIAL); +public static final ElementName XMP = new ElementName("xmp", "xmp", +// CPPONLY: NS_NewHTMLPreElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.XMP | SPECIAL); +public static final ElementName I = new ElementName("i", "i", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName P = new ElementName("p", "p", +// CPPONLY: NS_NewHTMLParagraphElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.P | SPECIAL | OPTIONAL_END_TAG); +public static final ElementName Q = new ElementName("q", "q", +// CPPONLY: NS_NewHTMLSharedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName S = new ElementName("s", "s", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName U = new ElementName("u", "u", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName H1 = new ElementName("h1", "h1", +// CPPONLY: NS_NewHTMLHeadingElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); +public static final ElementName H2 = new ElementName("h2", "h2", +// CPPONLY: NS_NewHTMLHeadingElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); +public static final ElementName H3 = new ElementName("h3", "h3", +// CPPONLY: NS_NewHTMLHeadingElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); +public static final ElementName H4 = new ElementName("h4", "h4", +// CPPONLY: NS_NewHTMLHeadingElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); +public static final ElementName H5 = new ElementName("h5", "h5", +// CPPONLY: NS_NewHTMLHeadingElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); +public static final ElementName H6 = new ElementName("h6", "h6", +// CPPONLY: NS_NewHTMLHeadingElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); +public static final ElementName AREA = new ElementName("area", "area", +// CPPONLY: NS_NewHTMLAreaElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.AREA_OR_WBR | SPECIAL); +public static final ElementName DATA = new ElementName("data", "data", +// CPPONLY: NS_NewHTMLDataElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName FEFUNCA = new ElementName("fefunca", "feFuncA", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEFuncAElement, +TreeBuilder.OTHER); +public static final ElementName METADATA = new ElementName("metadata", "metadata", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGMetadataElement, +TreeBuilder.OTHER); +public static final ElementName META = new ElementName("meta", "meta", +// CPPONLY: NS_NewHTMLMetaElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.META | SPECIAL); +public static final ElementName TEXTAREA = new ElementName("textarea", "textarea", +// CPPONLY: NS_NewHTMLTextAreaElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TEXTAREA | SPECIAL); +public static final ElementName FEFUNCB = new ElementName("fefuncb", "feFuncB", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEFuncBElement, +TreeBuilder.OTHER); +public static final ElementName RB = new ElementName("rb", "rb", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RB_OR_RTC | OPTIONAL_END_TAG); +public static final ElementName DESC = new ElementName("desc", "desc", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGDescElement, +TreeBuilder.FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG); +public static final ElementName DD = new ElementName("dd", "dd", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.DD_OR_DT | SPECIAL | OPTIONAL_END_TAG); +public static final ElementName BGSOUND = new ElementName("bgsound", "bgsound", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL); +public static final ElementName EMBED = new ElementName("embed", "embed", +// CPPONLY: NS_NewHTMLEmbedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.EMBED | SPECIAL); +public static final ElementName FEBLEND = new ElementName("feblend", "feBlend", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEBlendElement, +TreeBuilder.OTHER); +public static final ElementName FEFLOOD = new ElementName("feflood", "feFlood", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEFloodElement, +TreeBuilder.OTHER); +public static final ElementName HEAD = new ElementName("head", "head", +// CPPONLY: NS_NewHTMLSharedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.HEAD | SPECIAL | OPTIONAL_END_TAG); +public static final ElementName LEGEND = new ElementName("legend", "legend", +// CPPONLY: NS_NewHTMLLegendElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName NOEMBED = new ElementName("noembed", "noembed", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.NOEMBED | SPECIAL); +public static final ElementName TD = new ElementName("td", "td", +// CPPONLY: NS_NewHTMLTableCellElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG); +public static final ElementName THEAD = new ElementName("thead", "thead", +// CPPONLY: NS_NewHTMLTableSectionElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG); +public static final ElementName ASIDE = new ElementName("aside", "aside", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName ARTICLE = new ElementName("article", "article", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName ANIMATE = new ElementName("animate", "animate", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGAnimateElement, +TreeBuilder.OTHER); +public static final ElementName BASE = new ElementName("base", "base", +// CPPONLY: NS_NewHTMLSharedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.BASE | SPECIAL); +public static final ElementName BLOCKQUOTE = new ElementName("blockquote", "blockquote", +// CPPONLY: NS_NewHTMLSharedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); +public static final ElementName CODE = new ElementName("code", "code", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName CIRCLE = new ElementName("circle", "circle", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGCircleElement, +TreeBuilder.OTHER); +public static final ElementName CITE = new ElementName("cite", "cite", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName ELLIPSE = new ElementName("ellipse", "ellipse", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGEllipseElement, +TreeBuilder.OTHER); +public static final ElementName FETURBULENCE = new ElementName("feturbulence", "feTurbulence", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFETurbulenceElement, +TreeBuilder.OTHER); +public static final ElementName FEMERGENODE = new ElementName("femergenode", "feMergeNode", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEMergeNodeElement, +TreeBuilder.OTHER); +public static final ElementName FEIMAGE = new ElementName("feimage", "feImage", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEImageElement, +TreeBuilder.OTHER); +public static final ElementName FEMERGE = new ElementName("femerge", "feMerge", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEMergeElement, +TreeBuilder.OTHER); +public static final ElementName FETILE = new ElementName("fetile", "feTile", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFETileElement, +TreeBuilder.OTHER); +public static final ElementName FRAME = new ElementName("frame", "frame", +// CPPONLY: NS_NewHTMLFrameElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.FRAME | SPECIAL); +public static final ElementName FIGURE = new ElementName("figure", "figure", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName FECOMPOSITE = new ElementName("fecomposite", "feComposite", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFECompositeElement, +TreeBuilder.OTHER); +public static final ElementName IMAGE = new ElementName("image", "image", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGImageElement, +TreeBuilder.IMAGE); +public static final ElementName IFRAME = new ElementName("iframe", "iframe", +// CPPONLY: NS_NewHTMLIFrameElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.IFRAME | SPECIAL); +public static final ElementName LINE = new ElementName("line", "line", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGLineElement, +TreeBuilder.OTHER); +public static final ElementName MARQUEE = new ElementName("marquee", "marquee", +// CPPONLY: NS_NewHTMLMarqueeElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MARQUEE_OR_APPLET | SPECIAL | SCOPING); +public static final ElementName POLYLINE = new ElementName("polyline", "polyline", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGPolylineElement, +TreeBuilder.OTHER); +public static final ElementName PICTURE = new ElementName("picture", "picture", +// CPPONLY: NS_NewHTMLPictureElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName SOURCE = new ElementName("source", "source", +// CPPONLY: NS_NewHTMLSourceElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.PARAM_OR_SOURCE_OR_TRACK); +public static final ElementName STRIKE = new ElementName("strike", "strike", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName STYLE = new ElementName("style", "style", +// CPPONLY: NS_NewHTMLStyleElement, +// CPPONLY: NS_NewSVGStyleElement, +TreeBuilder.STYLE | SPECIAL); +public static final ElementName TABLE = new ElementName("table", "table", +// CPPONLY: NS_NewHTMLTableElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TABLE | SPECIAL | FOSTER_PARENTING | SCOPING); +public static final ElementName TITLE = new ElementName("title", "title", +// CPPONLY: NS_NewHTMLTitleElement, +// CPPONLY: NS_NewSVGTitleElement, +TreeBuilder.TITLE | SPECIAL | SCOPING_AS_SVG); +public static final ElementName TIME = new ElementName("time", "time", +// CPPONLY: NS_NewHTMLTimeElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName TEMPLATE = new ElementName("template", "template", +// CPPONLY: NS_NewHTMLTemplateElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TEMPLATE | SPECIAL | SCOPING); +public static final ElementName ALTGLYPHDEF = new ElementName("altglyphdef", "altGlyphDef", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName GLYPHREF = new ElementName("glyphref", "glyphRef", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName DIALOG = new ElementName("dialog", "dialog", +// CPPONLY: NS_NewHTMLDialogElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName FEFUNCG = new ElementName("fefuncg", "feFuncG", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEFuncGElement, +TreeBuilder.OTHER); +public static final ElementName FEDIFFUSELIGHTING = new ElementName("fediffuselighting", "feDiffuseLighting", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEDiffuseLightingElement, +TreeBuilder.OTHER); +public static final ElementName FESPECULARLIGHTING = new ElementName("fespecularlighting", "feSpecularLighting", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFESpecularLightingElement, +TreeBuilder.OTHER); +public static final ElementName LISTING = new ElementName("listing", "listing", +// CPPONLY: NS_NewHTMLPreElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.PRE_OR_LISTING | SPECIAL); +public static final ElementName STRONG = new ElementName("strong", "strong", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName ALTGLYPH = new ElementName("altglyph", "altGlyph", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName CLIPPATH = new ElementName("clippath", "clipPath", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGClipPathElement, +TreeBuilder.OTHER); +public static final ElementName MGLYPH = new ElementName("mglyph", "mglyph", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MGLYPH_OR_MALIGNMARK); +public static final ElementName MATH = new ElementName("math", "math", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MATH); +public static final ElementName MPATH = new ElementName("mpath", "mpath", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGMPathElement, +TreeBuilder.OTHER); +public static final ElementName PATH = new ElementName("path", "path", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGPathElement, +TreeBuilder.OTHER); +public static final ElementName TH = new ElementName("th", "th", +// CPPONLY: NS_NewHTMLTableCellElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG); +public static final ElementName SWITCH = new ElementName("switch", "switch", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGSwitchElement, +TreeBuilder.OTHER); +public static final ElementName TEXTPATH = new ElementName("textpath", "textPath", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGTextPathElement, +TreeBuilder.OTHER); +public static final ElementName LI = new ElementName("li", "li", +// CPPONLY: NS_NewHTMLLIElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.LI | SPECIAL | OPTIONAL_END_TAG); +public static final ElementName MI = new ElementName("mi", "mi", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); +public static final ElementName LINK = new ElementName("link", "link", +// CPPONLY: NS_NewHTMLLinkElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL); +public static final ElementName MARK = new ElementName("mark", "mark", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName MALIGNMARK = new ElementName("malignmark", "malignmark", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MGLYPH_OR_MALIGNMARK); +public static final ElementName MASK = new ElementName("mask", "mask", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGMaskElement, +TreeBuilder.OTHER); +public static final ElementName TRACK = new ElementName("track", "track", +// CPPONLY: NS_NewHTMLTrackElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.PARAM_OR_SOURCE_OR_TRACK | SPECIAL); +public static final ElementName DL = new ElementName("dl", "dl", +// CPPONLY: NS_NewHTMLSharedListElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.UL_OR_OL_OR_DL | SPECIAL); +public static final ElementName HTML = new ElementName("html", "html", +// CPPONLY: NS_NewHTMLSharedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.HTML | SPECIAL | SCOPING | OPTIONAL_END_TAG); +public static final ElementName OL = new ElementName("ol", "ol", +// CPPONLY: NS_NewHTMLSharedListElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.UL_OR_OL_OR_DL | SPECIAL); +public static final ElementName LABEL = new ElementName("label", "label", +// CPPONLY: NS_NewHTMLLabelElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName UL = new ElementName("ul", "ul", +// CPPONLY: NS_NewHTMLSharedListElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.UL_OR_OL_OR_DL | SPECIAL); +public static final ElementName SMALL = new ElementName("small", "small", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName SYMBOL = new ElementName("symbol", "symbol", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGSymbolElement, +TreeBuilder.OTHER); +public static final ElementName ALTGLYPHITEM = new ElementName("altglyphitem", "altGlyphItem", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName ANIMATETRANSFORM = new ElementName("animatetransform", "animateTransform", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGAnimateTransformElement, +TreeBuilder.OTHER); +public static final ElementName ACRONYM = new ElementName("acronym", "acronym", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName EM = new ElementName("em", "em", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName FORM = new ElementName("form", "form", +// CPPONLY: NS_NewHTMLFormElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.FORM | SPECIAL); +public static final ElementName PARAM = new ElementName("param", "param", +// CPPONLY: NS_NewHTMLSharedElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.PARAM_OR_SOURCE_OR_TRACK | SPECIAL); +public static final ElementName ANIMATEMOTION = new ElementName("animatemotion", "animateMotion", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGAnimateMotionElement, +TreeBuilder.OTHER); +public static final ElementName BUTTON = new ElementName("button", "button", +// CPPONLY: NS_NewHTMLButtonElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.BUTTON | SPECIAL); +public static final ElementName CAPTION = new ElementName("caption", "caption", +// CPPONLY: NS_NewHTMLTableCaptionElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.CAPTION | SPECIAL | SCOPING); +public static final ElementName FIGCAPTION = new ElementName("figcaption", "figcaption", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName MN = new ElementName("mn", "mn", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); +public static final ElementName KEYGEN = new ElementName("keygen", "keygen", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.KEYGEN | SPECIAL); +public static final ElementName MAIN = new ElementName("main", "main", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName OPTION = new ElementName("option", "option", +// CPPONLY: NS_NewHTMLOptionElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OPTION | OPTIONAL_END_TAG); +public static final ElementName POLYGON = new ElementName("polygon", "polygon", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGPolygonElement, +TreeBuilder.OTHER); +public static final ElementName PATTERN = new ElementName("pattern", "pattern", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGPatternElement, +TreeBuilder.OTHER); +public static final ElementName SPAN = new ElementName("span", "span", +// CPPONLY: NS_NewHTMLSpanElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); +public static final ElementName SECTION = new ElementName("section", "section", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName TSPAN = new ElementName("tspan", "tspan", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGTSpanElement, +TreeBuilder.OTHER); +public static final ElementName AUDIO = new ElementName("audio", "audio", +// CPPONLY: NS_NewHTMLAudioElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName MO = new ElementName("mo", "mo", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); +public static final ElementName VIDEO = new ElementName("video", "video", +// CPPONLY: NS_NewHTMLVideoElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName COLGROUP = new ElementName("colgroup", "colgroup", +// CPPONLY: NS_NewHTMLTableColElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.COLGROUP | SPECIAL | OPTIONAL_END_TAG); +public static final ElementName FEDISPLACEMENTMAP = new ElementName("fedisplacementmap", "feDisplacementMap", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEDisplacementMapElement, +TreeBuilder.OTHER); +public static final ElementName HGROUP = new ElementName("hgroup", "hgroup", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName RP = new ElementName("rp", "rp", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RT_OR_RP | OPTIONAL_END_TAG); +public static final ElementName OPTGROUP = new ElementName("optgroup", "optgroup", +// CPPONLY: NS_NewHTMLOptGroupElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OPTGROUP | OPTIONAL_END_TAG); +public static final ElementName SAMP = new ElementName("samp", "samp", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName STOP = new ElementName("stop", "stop", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGStopElement, +TreeBuilder.OTHER); +public static final ElementName BR = new ElementName("br", "br", +// CPPONLY: NS_NewHTMLBRElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.BR | SPECIAL); +public static final ElementName ABBR = new ElementName("abbr", "abbr", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName ANIMATECOLOR = new ElementName("animatecolor", "animateColor", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName CENTER = new ElementName("center", "center", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); +public static final ElementName HR = new ElementName("hr", "hr", +// CPPONLY: NS_NewHTMLHRElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.HR | SPECIAL); +public static final ElementName FEFUNCR = new ElementName("fefuncr", "feFuncR", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEFuncRElement, +TreeBuilder.OTHER); +public static final ElementName FECOMPONENTTRANSFER = new ElementName("fecomponenttransfer", "feComponentTransfer", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEComponentTransferElement, +TreeBuilder.OTHER); +public static final ElementName FILTER = new ElementName("filter", "filter", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFilterElement, +TreeBuilder.OTHER); +public static final ElementName FOOTER = new ElementName("footer", "footer", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName FEGAUSSIANBLUR = new ElementName("fegaussianblur", "feGaussianBlur", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEGaussianBlurElement, +TreeBuilder.OTHER); +public static final ElementName HEADER = new ElementName("header", "header", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName MARKER = new ElementName("marker", "marker", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGMarkerElement, +TreeBuilder.OTHER); +public static final ElementName METER = new ElementName("meter", "meter", +// CPPONLY: NS_NewHTMLMeterElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName NOBR = new ElementName("nobr", "nobr", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.NOBR); +public static final ElementName TR = new ElementName("tr", "tr", +// CPPONLY: NS_NewHTMLTableRowElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TR | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG); +public static final ElementName ADDRESS = new ElementName("address", "address", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName CANVAS = new ElementName("canvas", "canvas", +// CPPONLY: NS_NewHTMLCanvasElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName DEFS = new ElementName("defs", "defs", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGDefsElement, +TreeBuilder.OTHER); +public static final ElementName DETAILS = new ElementName("details", "details", +// CPPONLY: NS_NewHTMLDetailsElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName MS = new ElementName("ms", "ms", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); +public static final ElementName NOFRAMES = new ElementName("noframes", "noframes", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.NOFRAMES | SPECIAL); +public static final ElementName PROGRESS = new ElementName("progress", "progress", +// CPPONLY: NS_NewHTMLProgressElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName DT = new ElementName("dt", "dt", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.DD_OR_DT | SPECIAL | OPTIONAL_END_TAG); +public static final ElementName APPLET = new ElementName("applet", "applet", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MARQUEE_OR_APPLET | SPECIAL | SCOPING); +public static final ElementName BASEFONT = new ElementName("basefont", "basefont", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL); +public static final ElementName DATALIST = new ElementName("datalist", "datalist", +// CPPONLY: NS_NewHTMLDataListElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName FOREIGNOBJECT = new ElementName("foreignobject", "foreignObject", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGForeignObjectElement, +TreeBuilder.FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG); +public static final ElementName FIELDSET = new ElementName("fieldset", "fieldset", +// CPPONLY: NS_NewHTMLFieldSetElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.FIELDSET | SPECIAL); +public static final ElementName FRAMESET = new ElementName("frameset", "frameset", +// CPPONLY: NS_NewHTMLFrameSetElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.FRAMESET | SPECIAL); +public static final ElementName FEOFFSET = new ElementName("feoffset", "feOffset", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEOffsetElement, +TreeBuilder.OTHER); +public static final ElementName FESPOTLIGHT = new ElementName("fespotlight", "feSpotLight", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFESpotLightElement, +TreeBuilder.OTHER); +public static final ElementName FEPOINTLIGHT = new ElementName("fepointlight", "fePointLight", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEPointLightElement, +TreeBuilder.OTHER); +public static final ElementName FEDISTANTLIGHT = new ElementName("fedistantlight", "feDistantLight", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEDistantLightElement, +TreeBuilder.OTHER); +public static final ElementName FONT = new ElementName("font", "font", +// CPPONLY: NS_NewHTMLFontElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.FONT); +public static final ElementName INPUT = new ElementName("input", "input", +// CPPONLY: NS_NewHTMLInputElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.INPUT | SPECIAL); +public static final ElementName LINEARGRADIENT = new ElementName("lineargradient", "linearGradient", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGLinearGradientElement, +TreeBuilder.OTHER); +public static final ElementName MTEXT = new ElementName("mtext", "mtext", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); +public static final ElementName NOSCRIPT = new ElementName("noscript", "noscript", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.NOSCRIPT | SPECIAL); +public static final ElementName RT = new ElementName("rt", "rt", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RT_OR_RP | OPTIONAL_END_TAG); +public static final ElementName OBJECT = new ElementName("object", "object", +// CPPONLY: NS_NewHTMLObjectElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OBJECT | SPECIAL | SCOPING); +public static final ElementName OUTPUT = new ElementName("output", "output", +// CPPONLY: NS_NewHTMLOutputElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OUTPUT); +public static final ElementName PLAINTEXT = new ElementName("plaintext", "plaintext", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.PLAINTEXT | SPECIAL); +public static final ElementName TT = new ElementName("tt", "tt", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); +public static final ElementName RECT = new ElementName("rect", "rect", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGRectElement, +TreeBuilder.OTHER); +public static final ElementName RADIALGRADIENT = new ElementName("radialgradient", "radialGradient", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGRadialGradientElement, +TreeBuilder.OTHER); +public static final ElementName SELECT = new ElementName("select", "select", +// CPPONLY: NS_NewHTMLSelectElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.SELECT | SPECIAL); +public static final ElementName SLOT = new ElementName("slot", "slot", +// CPPONLY: NS_NewHTMLSlotElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.OTHER); +public static final ElementName SCRIPT = new ElementName("script", "script", +// CPPONLY: NS_NewHTMLScriptElement, +// CPPONLY: NS_NewSVGScriptElement, +TreeBuilder.SCRIPT | SPECIAL); +public static final ElementName TFOOT = new ElementName("tfoot", "tfoot", +// CPPONLY: NS_NewHTMLTableSectionElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG); +public static final ElementName TEXT = new ElementName("text", "text", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGTextElement, +TreeBuilder.OTHER); +public static final ElementName MENU = new ElementName("menu", "menu", +// CPPONLY: NS_NewHTMLMenuElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); +public static final ElementName FEDROPSHADOW = new ElementName("fedropshadow", "feDropShadow", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEDropShadowElement, +TreeBuilder.OTHER); +public static final ElementName VIEW = new ElementName("view", "view", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGViewElement, +TreeBuilder.OTHER); +public static final ElementName FECOLORMATRIX = new ElementName("fecolormatrix", "feColorMatrix", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEColorMatrixElement, +TreeBuilder.OTHER); +public static final ElementName FECONVOLVEMATRIX = new ElementName("feconvolvematrix", "feConvolveMatrix", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEConvolveMatrixElement, +TreeBuilder.OTHER); +public static final ElementName BODY = new ElementName("body", "body", +// CPPONLY: NS_NewHTMLBodyElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.BODY | SPECIAL | OPTIONAL_END_TAG); +public static final ElementName FEMORPHOLOGY = new ElementName("femorphology", "feMorphology", +// CPPONLY: NS_NewHTMLUnknownElement, +// CPPONLY: NS_NewSVGFEMorphologyElement, +TreeBuilder.OTHER); +public static final ElementName RUBY = new ElementName("ruby", "ruby", +// CPPONLY: NS_NewHTMLElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); +public static final ElementName SUMMARY = new ElementName("summary", "summary", +// CPPONLY: NS_NewHTMLSummaryElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL); +public static final ElementName TBODY = new ElementName("tbody", "tbody", +// CPPONLY: NS_NewHTMLTableSectionElement, +// CPPONLY: NS_NewSVGUnknownElement, +TreeBuilder.TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG); +private final static @NoLength ElementName[] ELEMENT_NAMES = { +MN, +CITE, +FRAMESET, +H1, +CLIPPATH, +METER, +RADIALGRADIENT, +B, +BGSOUND, +SOURCE, +HTML, +OPTGROUP, +NOFRAMES, +MTEXT, +VIEW, +DIV, +G, +FEFUNCA, +THEAD, +FIGURE, +GLYPHREF, +LI, +ACRONYM, +TSPAN, +FEFUNCR, +CANVAS, +BASEFONT, +FEDISTANTLIGHT, +OUTPUT, +TFOOT, +FEMORPHOLOGY, +COL, +MAP, +SUP, +P, +H5, +FEFUNCB, +HEAD, +BASE, +FEIMAGE, +LINE, +TITLE, +FESPECULARLIGHTING, +PATH, +MALIGNMARK, +SMALL, +ANIMATEMOTION, +POLYGON, +COLGROUP, +ABBR, +FEGAUSSIANBLUR, +TR, +DETAILS, +DT, +FOREIGNOBJECT, +FESPOTLIGHT, +INPUT, +RT, +TT, +SLOT, +MENU, +FECONVOLVEMATRIX, +SUMMARY, +BDI, +DFN, +INS, +PRE, +SUB, +USE, +XMP, +S, +H3, +AREA, +META, +DESC, +FEBLEND, +NOEMBED, +ARTICLE, +CODE, +FETURBULENCE, +FETILE, +IMAGE, +POLYLINE, +STYLE, +TEMPLATE, +FEFUNCG, +STRONG, +MATH, +SWITCH, +LINK, +TRACK, +LABEL, +ALTGLYPHITEM, +FORM, +CAPTION, +MAIN, +SPAN, +MO, +HGROUP, +STOP, +CENTER, +FILTER, +MARKER, +NOBR, +ADDRESS, +DEFS, +MS, +PROGRESS, +APPLET, +DATALIST, +FIELDSET, +FEOFFSET, +FEPOINTLIGHT, +FONT, +LINEARGRADIENT, +NOSCRIPT, +OBJECT, +PLAINTEXT, +RECT, +SELECT, +SCRIPT, +TEXT, +FEDROPSHADOW, +FECOLORMATRIX, +BODY, +RUBY, +TBODY, +BIG, +BDO, +DEL, +DIR, +IMG, +KBD, +NAV, +A, +RTC, +SVG, +SET, +VAR, +WBR, +I, +Q, +U, +H2, +H4, +H6, +DATA, +METADATA, +TEXTAREA, +RB, +DD, +EMBED, +FEFLOOD, +LEGEND, +TD, +ASIDE, +ANIMATE, +BLOCKQUOTE, +CIRCLE, +ELLIPSE, +FEMERGENODE, +FEMERGE, +FRAME, +FECOMPOSITE, +IFRAME, +MARQUEE, +PICTURE, +STRIKE, +TABLE, +TIME, +ALTGLYPHDEF, +DIALOG, +FEDIFFUSELIGHTING, +LISTING, +ALTGLYPH, +MGLYPH, +MPATH, +TH, +TEXTPATH, +MI, +MARK, +MASK, +DL, +OL, +UL, +SYMBOL, +ANIMATETRANSFORM, +EM, +PARAM, +BUTTON, +FIGCAPTION, +KEYGEN, +OPTION, +PATTERN, +SECTION, +AUDIO, +VIDEO, +FEDISPLACEMENTMAP, +RP, +SAMP, +BR, +ANIMATECOLOR, +HR, +FECOMPONENTTRANSFER, +FOOTER, +HEADER, +}; +private final static int[] ELEMENT_HASHES = { +1902641154, +1748359220, +2001349720, +876609538, +1798686984, +1971465813, +2007781534, +59768833, +1730965751, +1756474198, +1868312196, +1939219752, +1988763672, +2005324101, +2060065124, +52490899, +62390273, +1682547543, +1740181637, +1749905526, +1766992520, +1818230786, +1881613047, +1907959605, +1967760215, +1982935782, +1999397992, +2001392798, +2006329158, +2008851557, +2085266636, +51961587, +57206291, +60352339, +67108865, +943718402, +1699324759, +1733890180, +1747814436, +1749715159, +1752979652, +1757146773, +1783388498, +1805502724, +1854228698, +1874053333, +1898223949, +1906087319, +1932928296, +1965115924, +1968053806, +1973420034, +1983633431, +1998585858, +2001309869, +2001392795, +2003183333, +2005925890, +2006974466, +2008325940, +2021937364, +2068523856, +2092255447, +51435587, +52486755, +55110883, +58773795, +60345171, +61395251, +62973651, +68681729, +910163970, +1679960596, +1686491348, +1715310660, +1733054663, +1737099991, +1747176599, +1748100148, +1749656156, +1749801286, +1751288021, +1755076808, +1756625221, +1757268168, +1783210839, +1790207270, +1803929812, +1806806678, +1853642948, +1857653029, +1870268949, +1881288348, +1884120164, +1899272519, +1904412884, +1907435316, +1919418370, +1935549734, +1941221172, +1966223078, +1967795910, +1971461414, +1971938532, +1982173479, +1983533124, +1986527234, +1990037800, +1998724870, +2000525512, +2001349704, +2001349736, +2001392796, +2001495140, +2004635806, +2005719336, +2006028454, +2006896969, +2007601444, +2008125638, +2008340774, +2008994116, +2051837468, +2068523853, +2083120164, +2091479332, +2092557349, +51434643, +51438659, +52485715, +52488851, +55104723, +56151587, +57733651, +59244545, +59821379, +60347747, +60354131, +61925907, +62450211, +63438849, +67633153, +69730305, +893386754, +926941186, +960495618, +1681770564, +1686489160, +1689922072, +1703936002, +1730150402, +1732381397, +1733076167, +1736200310, +1738539010, +1747048757, +1747306711, +1747838298, +1748225318, +1749395095, +1749673195, +1749723735, +1749813541, +1749932347, +1751386406, +1753362711, +1755148615, +1756600614, +1757137429, +1757157700, +1763839627, +1782357526, +1783388497, +1786534215, +1797585096, +1803876550, +1803929861, +1805647874, +1807599880, +1818755074, +1854228692, +1854245076, +1864368130, +1870135298, +1873281026, +1874102998, +1881498736, +1881669634, +1889085973, +1898753862, +1900845386, +1903302038, +1905563974, +1906135367, +1907661127, +1914900309, +1925844629, +1934172497, +1938817026, +1941178676, +1963982850, +1965334268, +1967128578, +1967788867, +1967795958, +1968836118, +}; +} diff --git a/parser/html/javasrc/Portability.java b/parser/html/javasrc/Portability.java new file mode 100644 index 0000000000..1d65894a86 --- /dev/null +++ b/parser/html/javasrc/Portability.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2008-2015 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. + */ + +package nu.validator.htmlparser.impl; + +import org.xml.sax.SAXException; + +import nu.validator.htmlparser.annotation.Literal; +import nu.validator.htmlparser.annotation.Local; +import nu.validator.htmlparser.annotation.NoLength; +import nu.validator.htmlparser.common.Interner; + +public final class Portability { + + public static int checkedAdd(int a, int b) throws SAXException { + // This can't be translated code, because in C++ signed integer overflow is UB, so the below code would be wrong. + assert a >= 0; + assert b >= 0; + int sum = a + b; + if (sum < a || sum < b) { + throw new SAXException("Integer overflow"); + } + return sum; + } + + // Allocating methods + + /** + * Allocates a new local name object. In C++, the refcount must be set up in such a way that + * calling <code>releaseLocal</code> on the return value balances the refcount set by this method. + */ + public static @Local String newLocalNameFromBuffer(@NoLength char[] buf, int length, Interner interner) { + return new String(buf, 0, length).intern(); + } + + public static String newStringFromBuffer(@NoLength char[] buf, int offset, int length + // CPPONLY: , TreeBuilder treeBuilder, boolean maybeAtomize + ) { + return new String(buf, offset, length); + } + + public static String newEmptyString() { + return ""; + } + + public static String newStringFromLiteral(@Literal String literal) { + return literal; + } + + public static String newStringFromString(String string) { + return string; + } + + // XXX get rid of this + public static char[] newCharArrayFromLocal(@Local String local) { + return local.toCharArray(); + } + + public static char[] newCharArrayFromString(String string) { + return string.toCharArray(); + } + + // Deallocation methods + + public static void releaseString(String str) { + // No-op in Java + } + + // Comparison methods + + public static boolean localEqualsBuffer(@Local String local, @NoLength char[] buf, int length) { + if (local.length() != length) { + return false; + } + for (int i = 0; i < length; i++) { + if (local.charAt(i) != buf[i]) { + return false; + } + } + return true; + } + + public static boolean lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(@Literal String lowerCaseLiteral, + String string) { + if (string == null) { + return false; + } + if (lowerCaseLiteral.length() > string.length()) { + return false; + } + for (int i = 0; i < lowerCaseLiteral.length(); i++) { + char c0 = lowerCaseLiteral.charAt(i); + char c1 = string.charAt(i); + if (c1 >= 'A' && c1 <= 'Z') { + c1 += 0x20; + } + if (c0 != c1) { + return false; + } + } + return true; + } + + public static boolean lowerCaseLiteralEqualsIgnoreAsciiCaseString(@Literal String lowerCaseLiteral, + String string) { + if (string == null) { + return false; + } + if (lowerCaseLiteral.length() != string.length()) { + return false; + } + for (int i = 0; i < lowerCaseLiteral.length(); i++) { + char c0 = lowerCaseLiteral.charAt(i); + char c1 = string.charAt(i); + if (c1 >= 'A' && c1 <= 'Z') { + c1 += 0x20; + } + if (c0 != c1) { + return false; + } + } + return true; + } + + public static boolean literalEqualsString(@Literal String literal, String string) { + return literal.equals(string); + } + + public static boolean stringEqualsString(String one, String other) { + return one.equals(other); + } + + public static void delete(Object o) { + + } + + public static void deleteArray(Object o) { + + } +} diff --git a/parser/html/javasrc/README.txt b/parser/html/javasrc/README.txt new file mode 100644 index 0000000000..4555969cad --- /dev/null +++ b/parser/html/javasrc/README.txt @@ -0,0 +1,6 @@ +The .java files in this directory were placed here by the Java-to-C++ +translator that lives in parser/html/java/translator. Together they represent +a snapshot of the Java code that was translated to produce the corresponding +.h and .cpp files in the parent directory. Changing these .java files is not +worthwhile, as they will just be overwritten by the next translation. See +parser/html/java/README.txt for information about performing the translation. diff --git a/parser/html/javasrc/StackNode.java b/parser/html/javasrc/StackNode.java new file mode 100644 index 0000000000..cfd570724e --- /dev/null +++ b/parser/html/javasrc/StackNode.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2007-2011 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. + */ + +package nu.validator.htmlparser.impl; + +import nu.validator.htmlparser.annotation.Inline; +import nu.validator.htmlparser.annotation.Local; +import nu.validator.htmlparser.annotation.NsUri; + +final class StackNode<T> { + // Index where this stack node is stored in the tree builder's list of stack nodes. + // A value of -1 indicates that the stack node is not owned by a tree builder and + // must delete itself when its refcount reaches 0. + final int idxInTreeBuilder; + + int flags; + + @Local String name; + + @Local String popName; + + @NsUri String ns; + + T node; + + // Only used on the list of formatting elements + HtmlAttributes attributes; + + private int refcount = 0; + + /* + * Only valid for formatting elements + */ + // CPPONLY: private @HtmlCreator Object htmlCreator; + + // [NOCPP[ + + private TaintableLocatorImpl locator; + + public TaintableLocatorImpl getLocator() { + return locator; + } + + // ]NOCPP] + + @Inline public int getFlags() { + return flags; + } + + public int getGroup() { + return flags & ElementName.GROUP_MASK; + } + + public boolean isScoping() { + return (flags & ElementName.SCOPING) != 0; + } + + public boolean isSpecial() { + return (flags & ElementName.SPECIAL) != 0; + } + + public boolean isFosterParenting() { + return (flags & ElementName.FOSTER_PARENTING) != 0; + } + + public boolean isHtmlIntegrationPoint() { + return (flags & ElementName.HTML_INTEGRATION_POINT) != 0; + } + + // [NOCPP[ + + public boolean isOptionalEndTag() { + return (flags & ElementName.OPTIONAL_END_TAG) != 0; + } + + // ]NOCPP] + + StackNode(int idxInTreeBuilder) { + this.idxInTreeBuilder = idxInTreeBuilder; + this.flags = 0; + this.name = null; + this.popName = null; + // CPPONLY: this.ns = 0; + this.node = null; + this.attributes = null; + this.refcount = 0; + // CPPONLY: this.htmlCreator = null; + } + + // CPPONLY: public @HtmlCreator Object getHtmlCreator() { + // CPPONLY: return htmlCreator; + // CPPONLY: } + + /** + * Setter for copying. This doesn't take another <code>StackNode</code> + * because in C++ the caller is responsible for reobtaining the local names + * from another interner. + * + * @param flags + * @param ns + * @param name + * @param node + * @param popName + * @param attributes + */ + void setValues(int flags, @NsUri String ns, @Local String name, T node, + @Local String popName, HtmlAttributes attributes, + // CPPONLY: @HtmlCreator Object htmlCreator + // [NOCPP[ + TaintableLocatorImpl locator + // ]NOCPP] + ) { + assert isUnused(); + this.flags = flags; + this.name = name; + this.popName = popName; + this.ns = ns; + 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] + } + + /** + * Short hand for well-known HTML elements. + * + * @param elementName + * @param node + */ + void setValues(ElementName elementName, T node + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + assert isUnused(); + this.flags = elementName.getFlags(); + this.name = elementName.getName(); + this.popName = elementName.getName(); + this.ns = "http://www.w3.org/1999/xhtml"; + this.node = node; + 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] + } + + /** + * Setter for HTML formatting elements. + * + * @param elementName + * @param node + * @param attributes + */ + void setValues(ElementName elementName, T node, HtmlAttributes attributes + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + assert isUnused(); + this.flags = elementName.getFlags(); + this.name = elementName.getName(); + this.popName = elementName.getName(); + this.ns = "http://www.w3.org/1999/xhtml"; + this.node = node; + 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] + } + + /** + * The common-case HTML setter. + * + * @param elementName + * @param node + * @param popName + */ + void setValues(ElementName elementName, T node, @Local String popName + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + assert isUnused(); + this.flags = elementName.getFlags(); + this.name = elementName.getName(); + this.popName = popName; + this.ns = "http://www.w3.org/1999/xhtml"; + 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] + } + + /** + * Setter for SVG elements. Note that the order of the arguments is + * what distinguishes this from the HTML setter. This is ugly, but + * AFAICT the least disruptive way to make this work with Java's generics + * and without unnecessary branches. :-( + * + * @param elementName + * @param popName + * @param node + */ + void setValues(ElementName elementName, @Local String popName, T node + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + assert isUnused(); + this.flags = prepareSvgFlags(elementName.getFlags()); + this.name = elementName.getName(); + this.popName = popName; + this.ns = "http://www.w3.org/2000/svg"; + 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] + } + + /** + * Setter for MathML. + * + * @param elementName + * @param node + * @param popName + * @param markAsIntegrationPoint + */ + void setValues(ElementName elementName, T node, @Local String popName, + boolean markAsIntegrationPoint + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + assert isUnused(); + this.flags = prepareMathFlags(elementName.getFlags(), + markAsIntegrationPoint); + this.name = elementName.getName(); + this.popName = popName; + this.ns = "http://www.w3.org/1998/Math/MathML"; + 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] + } + + private static int prepareSvgFlags(int flags) { + flags &= ~(ElementName.FOSTER_PARENTING | ElementName.SCOPING + | ElementName.SPECIAL | ElementName.OPTIONAL_END_TAG); + if ((flags & ElementName.SCOPING_AS_SVG) != 0) { + flags |= (ElementName.SCOPING | ElementName.SPECIAL | ElementName.HTML_INTEGRATION_POINT); + } + return flags; + } + + private static int prepareMathFlags(int flags, + boolean markAsIntegrationPoint) { + flags &= ~(ElementName.FOSTER_PARENTING | ElementName.SCOPING + | ElementName.SPECIAL | ElementName.OPTIONAL_END_TAG); + if ((flags & ElementName.SCOPING_AS_MATHML) != 0) { + flags |= (ElementName.SCOPING | ElementName.SPECIAL); + } + if (markAsIntegrationPoint) { + flags |= ElementName.HTML_INTEGRATION_POINT; + } + return flags; + } + + @SuppressWarnings("unused") private void destructor() { + // The translator adds refcount debug code here. + } + + public void dropAttributes() { + attributes = null; + } + + // [NOCPP[ + /** + * @see java.lang.Object#toString() + */ + @Override public @Local String toString() { + return name; + } + + // ]NOCPP] + + public void retain() { + refcount++; + } + + public void release(TreeBuilder<T> owningTreeBuilder) { + refcount--; + assert refcount >= 0; + if (refcount == 0) { + Portability.delete(attributes); + if (idxInTreeBuilder >= 0) { + owningTreeBuilder.notifyUnusedStackNode(idxInTreeBuilder); + } else { + assert owningTreeBuilder == null; + Portability.delete(this); + } + } + } + + boolean isUnused() { + return refcount == 0; + } +} diff --git a/parser/html/javasrc/StateSnapshot.java b/parser/html/javasrc/StateSnapshot.java new file mode 100644 index 0000000000..cba711f714 --- /dev/null +++ b/parser/html/javasrc/StateSnapshot.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +package nu.validator.htmlparser.impl; + +import nu.validator.htmlparser.annotation.Auto; + + +public class StateSnapshot<T> implements TreeBuilderState<T> { + + private final @Auto StackNode<T>[] stack; + + private final @Auto StackNode<T>[] listOfActiveFormattingElements; + + private final @Auto int[] templateModeStack; + + private final T formPointer; + + private final T headPointer; + + private final int mode; + + private final int originalMode; + + private final boolean framesetOk; + + private final boolean needToDropLF; + + private final boolean quirks; + + /** + * @param stack + * @param listOfActiveFormattingElements + * @param templateModeStack + * @param formPointer + * @param headPointer + * @param deepTreeSurrogateParent + * @param mode + * @param originalMode + * @param framesetOk + * @param needToDropLF + * @param quirks + */ + StateSnapshot(StackNode<T>[] stack, + StackNode<T>[] listOfActiveFormattingElements, int[] templateModeStack, T formPointer, + T headPointer, int mode, int originalMode, + boolean framesetOk, boolean needToDropLF, boolean quirks) { + this.stack = stack; + this.listOfActiveFormattingElements = listOfActiveFormattingElements; + this.templateModeStack = templateModeStack; + this.formPointer = formPointer; + this.headPointer = headPointer; + this.mode = mode; + this.originalMode = originalMode; + this.framesetOk = framesetOk; + this.needToDropLF = needToDropLF; + this.quirks = quirks; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getStack() + */ + @Override + public StackNode<T>[] getStack() { + return stack; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStack() + */ + @Override + public int[] getTemplateModeStack() { + return templateModeStack; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElements() + */ + @Override + public StackNode<T>[] getListOfActiveFormattingElements() { + return listOfActiveFormattingElements; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getFormPointer() + */ + @Override + public T getFormPointer() { + return formPointer; + } + + /** + * Returns the headPointer. + * + * @return the headPointer + */ + @Override + public T getHeadPointer() { + return headPointer; + } + + /** + * Returns the mode. + * + * @return the mode + */ + @Override + public int getMode() { + return mode; + } + + /** + * Returns the originalMode. + * + * @return the originalMode + */ + @Override + public int getOriginalMode() { + return originalMode; + } + + /** + * Returns the framesetOk. + * + * @return the framesetOk + */ + @Override + public boolean isFramesetOk() { + return framesetOk; + } + + /** + * Returns the needToDropLF. + * + * @return the needToDropLF + */ + @Override + public boolean isNeedToDropLF() { + return needToDropLF; + } + + /** + * Returns the quirks. + * + * @return the quirks + */ + @Override + public boolean isQuirks() { + return quirks; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElementsLength() + */ + @Override + public int getListOfActiveFormattingElementsLength() { + return listOfActiveFormattingElements.length; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getStackLength() + */ + @Override + public int getStackLength() { + return stack.length; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStackLength() + */ + @Override + public int getTemplateModeStackLength() { + return templateModeStack.length; + } + + @SuppressWarnings("unused") private void destructor() { + for (int i = 0; i < stack.length; i++) { + stack[i].release(null); + } + for (int i = 0; i < listOfActiveFormattingElements.length; i++) { + if (listOfActiveFormattingElements[i] != null) { + listOfActiveFormattingElements[i].release(null); + } + } + } +} diff --git a/parser/html/javasrc/Tokenizer.java b/parser/html/javasrc/Tokenizer.java new file mode 100644 index 0000000000..a8047c7a71 --- /dev/null +++ b/parser/html/javasrc/Tokenizer.java @@ -0,0 +1,7636 @@ +/* + * Copyright (c) 2005-2007 Henri Sivonen + * Copyright (c) 2007-2017 Mozilla Foundation + * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla + * Foundation, and Opera Software ASA. + * + * 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. + */ + +/* + * The comments following this one that use the same comment syntax as this + * comment are quotes from the WHATWG HTML 5 spec as of 2 June 2007 + * amended as of June 18 2008 and May 31 2010. + * That document came with this statement: + * "© Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and + * Opera Software ASA. You are granted a license to use, reproduce and + * create derivative works of this document." + */ + +package nu.validator.htmlparser.impl; + +import org.xml.sax.ErrorHandler; +import org.xml.sax.Locator; +import org.xml.sax.ext.Locator2; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import nu.validator.htmlparser.annotation.Auto; +import nu.validator.htmlparser.annotation.CharacterName; +import nu.validator.htmlparser.annotation.Const; +import nu.validator.htmlparser.annotation.Inline; +import nu.validator.htmlparser.annotation.Local; +import nu.validator.htmlparser.annotation.NoLength; +import nu.validator.htmlparser.common.EncodingDeclarationHandler; +import nu.validator.htmlparser.common.Interner; +import nu.validator.htmlparser.common.TokenHandler; +import nu.validator.htmlparser.common.XmlViolationPolicy; + +/** + * An implementation of + * https://html.spec.whatwg.org/multipage/syntax.html#tokenization + * + * This class implements the <code>Locator</code> interface. This is not an + * incidental implementation detail: Users of this class are encouraged to make + * use of the <code>Locator</code> nature. + * + * By default, the tokenizer may report data that XML 1.0 bans. The tokenizer + * can be configured to treat these conditions as fatal or to coerce the infoset + * to something that XML 1.0 allows. + * + * @version $Id$ + * @author hsivonen + */ +public class Tokenizer implements Locator, Locator2 { + + private static final int DATA_AND_RCDATA_MASK = ~1; + + public static final int DATA = 0; + + public static final int RCDATA = 1; + + public static final int SCRIPT_DATA = 2; + + public static final int RAWTEXT = 3; + + public static final int SCRIPT_DATA_ESCAPED = 4; + + public static final int ATTRIBUTE_VALUE_DOUBLE_QUOTED = 5; + + public static final int ATTRIBUTE_VALUE_SINGLE_QUOTED = 6; + + public static final int ATTRIBUTE_VALUE_UNQUOTED = 7; + + public static final int PLAINTEXT = 8; + + public static final int TAG_OPEN = 9; + + public static final int CLOSE_TAG_OPEN = 10; + + public static final int TAG_NAME = 11; + + public static final int BEFORE_ATTRIBUTE_NAME = 12; + + public static final int ATTRIBUTE_NAME = 13; + + public static final int AFTER_ATTRIBUTE_NAME = 14; + + public static final int BEFORE_ATTRIBUTE_VALUE = 15; + + public static final int AFTER_ATTRIBUTE_VALUE_QUOTED = 16; + + public static final int BOGUS_COMMENT = 17; + + public static final int MARKUP_DECLARATION_OPEN = 18; + + public static final int DOCTYPE = 19; + + public static final int BEFORE_DOCTYPE_NAME = 20; + + public static final int DOCTYPE_NAME = 21; + + public static final int AFTER_DOCTYPE_NAME = 22; + + public static final int BEFORE_DOCTYPE_PUBLIC_IDENTIFIER = 23; + + public static final int DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED = 24; + + public static final int DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED = 25; + + public static final int AFTER_DOCTYPE_PUBLIC_IDENTIFIER = 26; + + public static final int BEFORE_DOCTYPE_SYSTEM_IDENTIFIER = 27; + + public static final int DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED = 28; + + public static final int DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED = 29; + + public static final int AFTER_DOCTYPE_SYSTEM_IDENTIFIER = 30; + + public static final int BOGUS_DOCTYPE = 31; + + public static final int COMMENT_START = 32; + + public static final int COMMENT_START_DASH = 33; + + public static final int COMMENT = 34; + + public static final int COMMENT_END_DASH = 35; + + public static final int COMMENT_END = 36; + + public static final int COMMENT_END_BANG = 37; + + public static final int NON_DATA_END_TAG_NAME = 38; + + public static final int MARKUP_DECLARATION_HYPHEN = 39; + + public static final int MARKUP_DECLARATION_OCTYPE = 40; + + public static final int DOCTYPE_UBLIC = 41; + + public static final int DOCTYPE_YSTEM = 42; + + public static final int AFTER_DOCTYPE_PUBLIC_KEYWORD = 43; + + public static final int BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS = 44; + + public static final int AFTER_DOCTYPE_SYSTEM_KEYWORD = 45; + + public static final int CONSUME_CHARACTER_REFERENCE = 46; + + public static final int CONSUME_NCR = 47; + + public static final int CHARACTER_REFERENCE_TAIL = 48; + + public static final int HEX_NCR_LOOP = 49; + + public static final int DECIMAL_NRC_LOOP = 50; + + public static final int HANDLE_NCR_VALUE = 51; + + public static final int HANDLE_NCR_VALUE_RECONSUME = 52; + + public static final int CHARACTER_REFERENCE_HILO_LOOKUP = 53; + + public static final int SELF_CLOSING_START_TAG = 54; + + public static final int CDATA_START = 55; + + public static final int CDATA_SECTION = 56; + + public static final int CDATA_RSQB = 57; + + public static final int CDATA_RSQB_RSQB = 58; + + public static final int SCRIPT_DATA_LESS_THAN_SIGN = 59; + + public static final int SCRIPT_DATA_ESCAPE_START = 60; + + public static final int SCRIPT_DATA_ESCAPE_START_DASH = 61; + + public static final int SCRIPT_DATA_ESCAPED_DASH = 62; + + public static final int SCRIPT_DATA_ESCAPED_DASH_DASH = 63; + + public static final int BOGUS_COMMENT_HYPHEN = 64; + + public static final int RAWTEXT_RCDATA_LESS_THAN_SIGN = 65; + + public static final int SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN = 66; + + public static final int SCRIPT_DATA_DOUBLE_ESCAPE_START = 67; + + public static final int SCRIPT_DATA_DOUBLE_ESCAPED = 68; + + public static final int SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN = 69; + + public static final int SCRIPT_DATA_DOUBLE_ESCAPED_DASH = 70; + + public static final int SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH = 71; + + public static final int SCRIPT_DATA_DOUBLE_ESCAPE_END = 72; + + public static final int PROCESSING_INSTRUCTION = 73; + + public static final int PROCESSING_INSTRUCTION_QUESTION_MARK = 74; + + public static final int COMMENT_LESSTHAN = 76; + + public static final int COMMENT_LESSTHAN_BANG = 77; + + public static final int COMMENT_LESSTHAN_BANG_DASH = 78; + + public static final int COMMENT_LESSTHAN_BANG_DASH_DASH = 79; + + /** + * Magic value for UTF-16 operations. + */ + private static final int LEAD_OFFSET = (0xD800 - (0x10000 >> 10)); + + /** + * UTF-16 code unit array containing less than and greater than for emitting + * those characters on certain parse errors. + */ + private static final @NoLength char[] LT_GT = { '<', '>' }; + + /** + * UTF-16 code unit array containing less than and solidus for emitting + * those characters on certain parse errors. + */ + private static final @NoLength char[] LT_SOLIDUS = { '<', '/' }; + + /** + * UTF-16 code unit array containing ]] for emitting those characters on + * state transitions. + */ + private static final @NoLength char[] RSQB_RSQB = { ']', ']' }; + + /** + * Array version of U+FFFD. + */ + private static final @NoLength char[] REPLACEMENT_CHARACTER = { '\uFFFD' }; + + // [NOCPP[ + + /** + * Array version of space. + */ + private static final @NoLength char[] SPACE = { ' ' }; + + // ]NOCPP] + + /** + * Array version of line feed. + */ + private static final @NoLength char[] LF = { '\n' }; + + /** + * "CDATA[" as <code>char[]</code> + */ + private static final @NoLength char[] CDATA_LSQB = { 'C', 'D', 'A', 'T', + 'A', '[' }; + + /** + * "octype" as <code>char[]</code> + */ + private static final @NoLength char[] OCTYPE = { 'o', 'c', 't', 'y', 'p', + 'e' }; + + /** + * "ublic" as <code>char[]</code> + */ + private static final @NoLength char[] UBLIC = { 'u', 'b', 'l', 'i', 'c' }; + + /** + * "ystem" as <code>char[]</code> + */ + private static final @NoLength char[] YSTEM = { 'y', 's', 't', 'e', 'm' }; + + private static final char[] TITLE_ARR = { 't', 'i', 't', 'l', 'e' }; + + private static final char[] SCRIPT_ARR = { 's', 'c', 'r', 'i', 'p', 't' }; + + private static final char[] STYLE_ARR = { 's', 't', 'y', 'l', 'e' }; + + private static final char[] PLAINTEXT_ARR = { 'p', 'l', 'a', 'i', 'n', 't', + 'e', 'x', 't' }; + + private static final char[] XMP_ARR = { 'x', 'm', 'p' }; + + private static final char[] TEXTAREA_ARR = { 't', 'e', 'x', 't', 'a', 'r', + 'e', 'a' }; + + private static final char[] IFRAME_ARR = { 'i', 'f', 'r', 'a', 'm', 'e' }; + + private static final char[] NOEMBED_ARR = { 'n', 'o', 'e', 'm', 'b', 'e', + 'd' }; + + private static final char[] NOSCRIPT_ARR = { 'n', 'o', 's', 'c', 'r', 'i', + 'p', 't' }; + + private static final char[] NOFRAMES_ARR = { 'n', 'o', 'f', 'r', 'a', 'm', + 'e', 's' }; + + /** + * The token handler. + */ + protected final TokenHandler tokenHandler; + + protected EncodingDeclarationHandler encodingDeclarationHandler; + + // [NOCPP[ + + /** + * The error handler. + */ + protected ErrorHandler errorHandler; + + // ]NOCPP] + + /** + * Whether the previous char read was CR. + */ + protected boolean lastCR; + + protected int stateSave; + + private int returnStateSave; + + protected int index; + + private boolean forceQuirks; + + private char additional; + + private int entCol; + + private int firstCharKey; + + private int lo; + + private int hi; + + private int candidate; + + private int charRefBufMark; + + protected int value; + + private boolean seenDigits; + + private boolean suspendAfterCurrentNonTextToken; + + protected int cstart; + + /** + * The SAX public id for the resource being tokenized. (Only passed to back + * as part of locator data.) + */ + private String publicId; + + /** + * The SAX system id for the resource being tokenized. (Only passed to back + * as part of locator data.) + */ + private String systemId; + + /** + * Buffer for bufferable things other than those that fit the description + * of <code>charRefBuf</code>. + */ + private @Auto char[] strBuf; + + /** + * Number of significant <code>char</code>s in <code>strBuf</code>. + */ + private int strBufLen; + + /** + * Buffer for characters that might form a character reference but may + * end up not forming one. + */ + private final @Auto char[] charRefBuf; + + /** + * Number of significant <code>char</code>s in <code>charRefBuf</code>. + */ + private int charRefBufLen; + + /** + * Buffer for expanding NCRs falling into the Basic Multilingual Plane. + */ + private final @Auto char[] bmpChar; + + /** + * Buffer for expanding astral NCRs. + */ + private final @Auto char[] astralChar; + + /** + * The element whose end tag closes the current CDATA or RCDATA element. + */ + protected ElementName endTagExpectation = null; + + private char[] endTagExpectationAsArray; // not @Auto! + + /** + * <code>true</code> if tokenizing an end tag + */ + protected boolean endTag; + + /** + * <code>true</code> iff the current element/attribute name contains + * a hyphen. + */ + private boolean containsHyphen; + + /** + * The current tag token name. One of + * 1) null, + * 2) non-owning reference to nonInternedTagName + * 3) non-owning reference to a pre-interned ElementName + */ + private ElementName tagName = null; + + /** + * The recycled ElementName instance for the non-pre-interned cases. + */ + private ElementName nonInternedTagName = null; + + /** + * The current attribute name. + */ + protected AttributeName attributeName = null; + + // CPPONLY: private AttributeName nonInternedAttributeName = null; + + // [NOCPP[ + + /** + * Whether comment tokens are emitted. + */ + private boolean wantsComments = false; + + /** + * Whether the stream is past the first 1024 bytes. + */ + private boolean metaBoundaryPassed; + + // ]NOCPP] + + /** + * The name of the current doctype token. + */ + private @Local String doctypeName; + + /** + * The public id of the current doctype token. + */ + private String publicIdentifier; + + /** + * The system id of the current doctype token. + */ + private String systemIdentifier; + + /** + * The attribute holder. + */ + private HtmlAttributes attributes; + + // [NOCPP[ + + /** + * The policy for vertical tab and form feed. + */ + private XmlViolationPolicy contentSpacePolicy = XmlViolationPolicy.ALTER_INFOSET; + + /** + * The policy for comments. + */ + private XmlViolationPolicy commentPolicy = XmlViolationPolicy.ALTER_INFOSET; + + private XmlViolationPolicy xmlnsPolicy = XmlViolationPolicy.ALTER_INFOSET; + + private XmlViolationPolicy namePolicy = XmlViolationPolicy.ALTER_INFOSET; + + private int mappingLangToXmlLang; + + // ]NOCPP] + + private final boolean newAttributesEachTime; + + private boolean shouldSuspend; + + protected boolean confident; + + private int line; + + /* + * The line number of the current attribute. First set to the line of the + * attribute name and if there is a value, set to the line the value + * started on. + */ + // CPPONLY: private int attributeLine; + + private Interner interner; + + // CPPONLY: private boolean viewingXmlSource; + + // [NOCPP[ + + protected LocatorImpl ampersandLocation; + + public Tokenizer(TokenHandler tokenHandler, boolean newAttributesEachTime) { + this.tokenHandler = tokenHandler; + this.encodingDeclarationHandler = null; + this.lastCR = false; + this.stateSave = 0; + this.returnStateSave = 0; + this.index = 0; + this.forceQuirks = false; + this.additional = '\u0000'; + this.entCol = 0; + this.firstCharKey = 0; + this.lo = 0; + this.hi = 0; + this.candidate = 0; + this.charRefBufMark = 0; + this.value = 0; + this.seenDigits = false; + this.suspendAfterCurrentNonTextToken = false; + this.cstart = 0; + this.strBufLen = 0; + this.newAttributesEachTime = newAttributesEachTime; + // ∳ is the longest valid char ref and + // the semicolon never gets appended to the buffer. + this.charRefBuf = new char[32]; + this.charRefBufLen = 0; + this.bmpChar = new char[1]; + this.astralChar = new char[2]; + this.endTagExpectation = null; + this.endTagExpectationAsArray = null; + this.endTag = false; + this.containsHyphen = false; + this.tagName = null; + this.nonInternedTagName = new ElementName(); + this.attributeName = null; + // CPPONLY: this.nonInternedAttributeName = new AttributeName(); + this.doctypeName = null; + this.publicIdentifier = null; + this.systemIdentifier = null; + this.attributes = null; + this.shouldSuspend = false; + this.confident = false; + this.line = 0; + // CPPONLY: this.attributeLine = 0; + this.interner = null; + } + + // ]NOCPP] + + /** + * The constructor. + * + * @param tokenHandler + * the handler for receiving tokens + */ + public Tokenizer(TokenHandler tokenHandler + // CPPONLY: , boolean viewingXmlSource + ) { + this.tokenHandler = tokenHandler; + this.encodingDeclarationHandler = null; + // [NOCPP[ + this.newAttributesEachTime = false; + // ]NOCPP] + this.lastCR = false; + this.stateSave = 0; + this.returnStateSave = 0; + this.index = 0; + this.forceQuirks = false; + this.additional = '\u0000'; + this.entCol = 0; + this.firstCharKey = 0; + this.lo = 0; + this.hi = 0; + this.candidate = 0; + this.charRefBufMark = 0; + this.value = 0; + this.seenDigits = false; + this.suspendAfterCurrentNonTextToken = false; + this.cstart = 0; + this.strBufLen = 0; + // ∳ is the longest valid char ref and + // the semicolon never gets appended to the buffer. + this.charRefBuf = new char[32]; + this.charRefBufLen = 0; + this.bmpChar = new char[1]; + this.astralChar = new char[2]; + this.endTagExpectation = null; + this.endTagExpectationAsArray = null; + this.endTag = false; + this.containsHyphen = false; + this.tagName = null; + this.nonInternedTagName = new ElementName(); + this.attributeName = null; + // CPPONLY: this.nonInternedAttributeName = new AttributeName(); + this.doctypeName = null; + this.publicIdentifier = null; + this.systemIdentifier = null; + // [NOCPP[ + this.attributes = null; + // ]NOCPP] + // CPPONLY: this.attributes = tokenHandler.HasBuilder() ? new HtmlAttributes(mappingLangToXmlLang) : null; + // CPPONLY: this.newAttributesEachTime = !tokenHandler.HasBuilder(); + this.shouldSuspend = false; + this.confident = false; + this.line = 0; + // CPPONLY: this.attributeLine = 0; + this.interner = null; + // CPPONLY: this.viewingXmlSource = viewingXmlSource; + } + + public void setInterner(Interner interner) { + this.interner = interner; + } + + public void initLocation(String newPublicId, String newSystemId) { + this.systemId = newSystemId; + this.publicId = newPublicId; + + } + + // CPPONLY: boolean isViewingXmlSource() { + // CPPONLY: return viewingXmlSource; + // CPPONLY: } + + // [NOCPP[ + + /** + * Returns the mappingLangToXmlLang. + * + * @return the mappingLangToXmlLang + */ + public boolean isMappingLangToXmlLang() { + return mappingLangToXmlLang == AttributeName.HTML_LANG; + } + + /** + * Sets the mappingLangToXmlLang. + * + * @param mappingLangToXmlLang + * the mappingLangToXmlLang to set + */ + public void setMappingLangToXmlLang(boolean mappingLangToXmlLang) { + this.mappingLangToXmlLang = mappingLangToXmlLang ? AttributeName.HTML_LANG + : AttributeName.HTML; + } + + /** + * Sets the error handler. + * + * @see org.xml.sax.XMLReader#setErrorHandler(org.xml.sax.ErrorHandler) + */ + public void setErrorHandler(ErrorHandler eh) { + this.errorHandler = eh; + } + + public ErrorHandler getErrorHandler() { + return this.errorHandler; + } + + /** + * Sets the commentPolicy. + * + * @param commentPolicy + * the commentPolicy to set + */ + public void setCommentPolicy(XmlViolationPolicy commentPolicy) { + this.commentPolicy = commentPolicy; + } + + /** + * Sets the contentNonXmlCharPolicy. + * + * @param contentNonXmlCharPolicy + * the contentNonXmlCharPolicy to set + */ + public void setContentNonXmlCharPolicy( + XmlViolationPolicy contentNonXmlCharPolicy) { + if (contentNonXmlCharPolicy != XmlViolationPolicy.ALLOW) { + throw new IllegalArgumentException( + "Must use ErrorReportingTokenizer to set contentNonXmlCharPolicy to non-ALLOW."); + } + } + + /** + * Sets the contentSpacePolicy. + * + * @param contentSpacePolicy + * the contentSpacePolicy to set + */ + public void setContentSpacePolicy(XmlViolationPolicy contentSpacePolicy) { + this.contentSpacePolicy = contentSpacePolicy; + } + + /** + * Sets the xmlnsPolicy. + * + * @param xmlnsPolicy + * the xmlnsPolicy to set + */ + public void setXmlnsPolicy(XmlViolationPolicy xmlnsPolicy) { + if (xmlnsPolicy == XmlViolationPolicy.FATAL) { + throw new IllegalArgumentException("Can't use FATAL here."); + } + this.xmlnsPolicy = xmlnsPolicy; + } + + public void setNamePolicy(XmlViolationPolicy namePolicy) { + this.namePolicy = namePolicy; + } + + // ]NOCPP] + + // For the token handler to call + + /** + * Sets the tokenizer state and the associated element name. This should + * only ever used to put the tokenizer into one of the states that have + * a special end tag expectation. + * + * @param specialTokenizerState + * the tokenizer state to set + */ + public void setState(int specialTokenizerState) { + this.stateSave = specialTokenizerState; + this.endTagExpectation = null; + this.endTagExpectationAsArray = null; + } + + // [NOCPP[ + + /** + * Sets the tokenizer state and the associated element name. This should + * only ever used to put the tokenizer into one of the states that have + * a special end tag expectation. For use from the tokenizer test harness. + * + * @param specialTokenizerState + * the tokenizer state to set + * @param endTagExpectation + * the expected end tag for transitioning back to normal + */ + public void setStateAndEndTagExpectation(int specialTokenizerState, + @Local String endTagExpectation) { + this.stateSave = specialTokenizerState; + if (specialTokenizerState == Tokenizer.DATA) { + return; + } + @Auto char[] asArray = Portability.newCharArrayFromLocal(endTagExpectation); + this.endTagExpectation = ElementName.elementNameByBuffer(asArray, + asArray.length, interner); + assert this.endTagExpectation != null; + endTagExpectationToArray(); + } + + // ]NOCPP] + + /** + * Sets the tokenizer state and the associated element name. This should + * only ever used to put the tokenizer into one of the states that have + * a special end tag expectation. + * + * @param specialTokenizerState + * the tokenizer state to set + * @param endTagExpectation + * the expected end tag for transitioning back to normal + */ + public void setStateAndEndTagExpectation(int specialTokenizerState, + ElementName endTagExpectation) { + this.stateSave = specialTokenizerState; + this.endTagExpectation = endTagExpectation; + endTagExpectationToArray(); + } + + private void endTagExpectationToArray() { + switch (endTagExpectation.getGroup()) { + case TreeBuilder.TITLE: + endTagExpectationAsArray = TITLE_ARR; + return; + case TreeBuilder.SCRIPT: + endTagExpectationAsArray = SCRIPT_ARR; + return; + case TreeBuilder.STYLE: + endTagExpectationAsArray = STYLE_ARR; + return; + case TreeBuilder.PLAINTEXT: + endTagExpectationAsArray = PLAINTEXT_ARR; + return; + case TreeBuilder.XMP: + endTagExpectationAsArray = XMP_ARR; + return; + case TreeBuilder.TEXTAREA: + endTagExpectationAsArray = TEXTAREA_ARR; + return; + case TreeBuilder.IFRAME: + endTagExpectationAsArray = IFRAME_ARR; + return; + case TreeBuilder.NOEMBED: + endTagExpectationAsArray = NOEMBED_ARR; + return; + case TreeBuilder.NOSCRIPT: + endTagExpectationAsArray = NOSCRIPT_ARR; + return; + case TreeBuilder.NOFRAMES: + endTagExpectationAsArray = NOFRAMES_ARR; + return; + default: + assert false: "Bad end tag expectation."; + return; + } + } + + /** + * For C++ use only. + */ + public void setLineNumber(int line) { + // CPPONLY: this.attributeLine = line; // XXX is this needed? + this.line = line; + } + + // start Locator impl + + /** + * @see org.xml.sax.Locator#getLineNumber() + */ + @Inline public int getLineNumber() { + return line; + } + + // [NOCPP[ + + /** + * @see org.xml.sax.Locator#getColumnNumber() + */ + @Inline public int getColumnNumber() { + return -1; + } + + /** + * @see org.xml.sax.Locator#getPublicId() + */ + public String getPublicId() { + return publicId; + } + + /** + * @see org.xml.sax.Locator#getSystemId() + */ + public String getSystemId() { + return systemId; + } + + /** + * @see org.xml.sax.ext.Locator2#getXMLVersion() + */ + public String getXMLVersion() { + return "1.0"; + } + + /** + * @see org.xml.sax.ext.Locator2#getXMLVersion() + */ + public String getEncoding() { + try { + return encodingDeclarationHandler == null ? null : encodingDeclarationHandler.getCharacterEncoding(); + } catch (SAXException e) { + return null; + } + } + + // end Locator impl + + // end public API + + public void notifyAboutMetaBoundary() { + metaBoundaryPassed = true; + } + + // ]NOCPP] + + HtmlAttributes emptyAttributes() { + // [NOCPP[ + if (newAttributesEachTime) { + return new HtmlAttributes(mappingLangToXmlLang); + } else { + // ]NOCPP] + return HtmlAttributes.EMPTY_ATTRIBUTES; + // [NOCPP[ + } + // ]NOCPP] + } + + @Inline private void appendCharRefBuf(char c) { + // CPPONLY: assert charRefBufLen < charRefBuf.length: + // CPPONLY: "RELEASE: Attempted to overrun charRefBuf!"; + charRefBuf[charRefBufLen++] = c; + } + + private void emitOrAppendCharRefBuf(int returnState) throws SAXException { + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + appendCharRefBufToStrBuf(); + } else { + if (charRefBufLen > 0) { + tokenHandler.characters(charRefBuf, 0, charRefBufLen); + charRefBufLen = 0; + } + } + } + + @Inline private void clearStrBufAfterUse() { + strBufLen = 0; + } + + @Inline private void clearStrBufBeforeUse() { + assert strBufLen == 0: "strBufLen not reset after previous use!"; + strBufLen = 0; // no-op in the absence of bugs + } + + @Inline private void clearStrBufAfterOneHyphen() { + assert strBufLen == 1: "strBufLen length not one!"; + assert strBuf[0] == '-': "strBuf does not start with a hyphen!"; + strBufLen = 0; + } + + /** + * Appends to the buffer. + * + * @param c + * the UTF-16 code unit to append + */ + @Inline private void appendStrBuf(char c) { + // CPPONLY: assert strBufLen < strBuf.length: "Previous buffer length insufficient."; + // CPPONLY: if (strBufLen == strBuf.length) { + // CPPONLY: if (!EnsureBufferSpace(1)) { + // CPPONLY: assert false: "RELEASE: Unable to recover from buffer reallocation failure"; + // CPPONLY: } // TODO: Add telemetry when outer if fires but inner does not + // CPPONLY: } + strBuf[strBufLen++] = c; + } + + /** + * The buffer as a String. Currently only used for error reporting. + * + * <p> + * C++ memory note: The return value must be released. + * + * @return the buffer as a string + */ + protected String strBufToString() { + String str = Portability.newStringFromBuffer(strBuf, 0, strBufLen + // CPPONLY: , tokenHandler, !newAttributesEachTime && attributeName == AttributeName.CLASS + ); + clearStrBufAfterUse(); + return str; + } + + /** + * Returns the buffer as a local name. The return value is released in + * emitDoctypeToken(). + * + * @return the buffer as local name + */ + private void strBufToDoctypeName() { + doctypeName = Portability.newLocalNameFromBuffer(strBuf, strBufLen, interner); + clearStrBufAfterUse(); + } + + /** + * Emits the buffer as character tokens. + * + * @throws SAXException + * if the token handler threw + */ + private void emitStrBuf() throws SAXException { + if (strBufLen > 0) { + tokenHandler.characters(strBuf, 0, strBufLen); + clearStrBufAfterUse(); + } + } + + @Inline private void appendSecondHyphenToBogusComment() throws SAXException { + // [NOCPP[ + switch (commentPolicy) { + case ALTER_INFOSET: + appendStrBuf(' '); + // CPPONLY: MOZ_FALLTHROUGH; + case ALLOW: + warn("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment."); + // ]NOCPP] + appendStrBuf('-'); + // [NOCPP[ + break; + case FATAL: + fatal("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment."); + break; + } + // ]NOCPP] + } + + // [NOCPP[ + private void maybeAppendSpaceToBogusComment() throws SAXException { + switch (commentPolicy) { + case ALTER_INFOSET: + appendStrBuf(' '); + // CPPONLY: MOZ_FALLTHROUGH; + case ALLOW: + warn("The document is not mappable to XML 1.0 due to a trailing hyphen in a comment."); + break; + case FATAL: + fatal("The document is not mappable to XML 1.0 due to a trailing hyphen in a comment."); + break; + } + } + + // ]NOCPP] + + @Inline private void adjustDoubleHyphenAndAppendToStrBufAndErr(char c, boolean reportedConsecutiveHyphens) + throws SAXException { + // [NOCPP[ + switch (commentPolicy) { + case ALTER_INFOSET: + strBufLen--; + // WARNING!!! This expands the worst case of the buffer length + // given the length of input! + appendStrBuf(' '); + appendStrBuf('-'); + // CPPONLY: MOZ_FALLTHROUGH; + case ALLOW: + if (!reportedConsecutiveHyphens) { + warn("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment."); + } + // ]NOCPP] + appendStrBuf(c); + // [NOCPP[ + break; + case FATAL: + fatal("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment."); + break; + } + // ]NOCPP] + } + + private void appendStrBuf(@NoLength char[] buffer, int offset, int length) throws SAXException { + int newLen = Portability.checkedAdd(strBufLen, length); + // CPPONLY: assert newLen <= strBuf.length: "Previous buffer length insufficient."; + // CPPONLY: if (strBuf.length < newLen) { + // CPPONLY: if (!EnsureBufferSpace(length)) { + // CPPONLY: assert false: "RELEASE: Unable to recover from buffer reallocation failure"; + // CPPONLY: } // TODO: Add telemetry when outer if fires but inner does not + // CPPONLY: } + System.arraycopy(buffer, offset, strBuf, strBufLen, length); + strBufLen = newLen; + } + + /** + * Append the contents of the char reference buffer to the main one. + */ + @Inline private void appendCharRefBufToStrBuf() throws SAXException { + appendStrBuf(charRefBuf, 0, charRefBufLen); + charRefBufLen = 0; + } + + /** + * Emits the current comment token. + * + * NOTE: The method may set <code>shouldSuspend</code>, so the caller + * must have this pattern after the state's <code>transition</code> call: + * + * <pre> + * if (shouldSuspend) { + * break stateloop; + * } + * continue stateloop; + * </pre> + * + * @param pos + * TODO + * + * @throws SAXException + */ + private void emitComment(int provisionalHyphens, int pos) + throws SAXException { + // CPPONLY: RememberGt(pos); + // [NOCPP[ + if (wantsComments) { + // ]NOCPP] + tokenHandler.comment(strBuf, 0, strBufLen + - provisionalHyphens); + // [NOCPP[ + } + // ]NOCPP] + clearStrBufAfterUse(); + cstart = pos + 1; + suspendIfRequestedAfterCurrentNonTextToken(); + } + + /** + * Flushes coalesced character tokens. + * + * @param buf + * TODO + * @param pos + * TODO + * + * @throws SAXException + */ + protected void flushChars(@NoLength char[] buf, int pos) + throws SAXException { + if (pos > cstart) { + tokenHandler.characters(buf, cstart, pos - cstart); + } + cstart = Integer.MAX_VALUE; + } + + /** + * Reports an condition that would make the infoset incompatible with XML + * 1.0 as fatal. + * + * @param message + * the message + * @throws SAXException + * @throws SAXParseException + */ + public void fatal(String message) throws SAXException { + SAXParseException spe = new SAXParseException(message, this); + if (errorHandler != null) { + errorHandler.fatalError(spe); + } + throw spe; + } + + /** + * Reports a Parse Error. + * + * @param message + * the message + * @throws SAXException + */ + public void err(String message) throws SAXException { + if (errorHandler == null) { + return; + } + SAXParseException spe = new SAXParseException(message, this); + errorHandler.error(spe); + } + + public void errTreeBuilder(String message) throws SAXException { + ErrorHandler eh = null; + if (tokenHandler instanceof TreeBuilder<?>) { + TreeBuilder<?> treeBuilder = (TreeBuilder<?>) tokenHandler; + eh = treeBuilder.getErrorHandler(); + } + if (eh == null) { + eh = errorHandler; + } + if (eh == null) { + return; + } + SAXParseException spe = new SAXParseException(message, this); + eh.error(spe); + } + + /** + * Reports a warning + * + * @param message + * the message + * @throws SAXException + */ + public void warn(String message) throws SAXException { + if (errorHandler == null) { + return; + } + SAXParseException spe = new SAXParseException(message, this); + errorHandler.warning(spe); + } + + private void strBufToElementNameString() { + if (containsHyphen) { + // We've got a custom element or annotation-xml. + @Local String annotationName = ElementName.ANNOTATION_XML.getName(); + if (Portability.localEqualsBuffer(annotationName, strBuf, strBufLen)) { + tagName = ElementName.ANNOTATION_XML; + } else { + nonInternedTagName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, strBufLen, + interner) + // CPPONLY: , true + ); + tagName = nonInternedTagName; + } + } else { + tagName = ElementName.elementNameByBuffer(strBuf, strBufLen, interner); + if (tagName == null) { + nonInternedTagName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, strBufLen, + interner) + // CPPONLY: , false + ); + tagName = nonInternedTagName; + } + } + containsHyphen = false; + clearStrBufAfterUse(); + } + + /** + * Emits a tag token. + * + * NOTE: The method may set <code>shouldSuspend</code>, so the caller + * must have this pattern after the state's <code>transition</code> call: + * <pre> + * if (shouldSuspend) { + * break stateloop; + * } + * continue stateloop; + * </pre> + * + * @param selfClosing + * @param pos + * @return + * @throws SAXException + */ + private int emitCurrentTagToken(boolean selfClosing, int pos) + throws SAXException { + // CPPONLY: RememberGt(pos); + cstart = pos + 1; + maybeErrSlashInEndTag(selfClosing); + stateSave = Tokenizer.DATA; + HtmlAttributes attrs = (attributes == null ? HtmlAttributes.EMPTY_ATTRIBUTES + : attributes); + if (endTag) { + /* + * When an end tag token is emitted, the content model flag must be + * switched to the PCDATA state. + */ + maybeErrAttributesOnEndTag(attrs); + // CPPONLY: if (!viewingXmlSource) { + tokenHandler.endTag(tagName); + // CPPONLY: } + // CPPONLY: if (newAttributesEachTime) { + // CPPONLY: Portability.delete(attributes); + // CPPONLY: attributes = null; + // CPPONLY: } + } else { + // CPPONLY: if (viewingXmlSource) { + // CPPONLY: assert newAttributesEachTime; + // CPPONLY: Portability.delete(attributes); + // CPPONLY: attributes = null; + // CPPONLY: } else { + tokenHandler.startTag(tagName, attrs, selfClosing); + // CPPONLY: } + } + tagName = null; + if (newAttributesEachTime) { + attributes = null; + } else { + attributes.clear(mappingLangToXmlLang); + } + /* + * The token handler may have called setStateAndEndTagExpectation + * and changed stateSave since the start of this method. + */ + suspendIfRequestedAfterCurrentNonTextToken(); + return stateSave; + } + + private void attributeNameComplete() throws SAXException { + attributeName = AttributeName.nameByBuffer(strBuf, strBufLen, interner); + if (attributeName == null) { + // [NOCPP[ + attributeName = AttributeName.createAttributeName( + Portability.newLocalNameFromBuffer(strBuf, strBufLen, + interner), + namePolicy != XmlViolationPolicy.ALLOW); + // ]NOCPP] + // CPPONLY: nonInternedAttributeName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, strBufLen, interner)); + // CPPONLY: attributeName = nonInternedAttributeName; + } + clearStrBufAfterUse(); + + if (attributes == null) { + attributes = new HtmlAttributes(mappingLangToXmlLang); + } + + /* + * When the user agent leaves the attribute name state (and before + * emitting the tag token, if appropriate), the complete attribute's + * name must be compared to the other attributes on the same token; if + * there is already an attribute on the token with the exact same name, + * then this is a parse error and the new attribute must be dropped, + * along with the value that gets associated with it (if any). + */ + if (attributes.contains(attributeName)) { + errDuplicateAttribute(); + attributeName = null; + } + } + + private void addAttributeWithoutValue() throws SAXException { + noteAttributeWithoutValue(); + + // [NOCPP[ + if (metaBoundaryPassed && AttributeName.CHARSET == attributeName + && ElementName.META == tagName) { + err("A \u201Ccharset\u201D attribute on a \u201Cmeta\u201D element found after the first 1024 bytes."); + } + // ]NOCPP] + if (attributeName != null) { + // [NOCPP[ + if (AttributeName.SRC == attributeName + || AttributeName.HREF == attributeName) { + warn("Attribute \u201C" + + attributeName.getLocal(AttributeName.HTML) + + "\u201D without an explicit value seen. The attribute may be dropped by IE7."); + } + // ]NOCPP] + attributes.addAttribute(attributeName, + Portability.newEmptyString() + // [NOCPP[ + , xmlnsPolicy + // ]NOCPP] + // CPPONLY: , attributeLine + ); + attributeName = null; + } else { + clearStrBufAfterUse(); + } + } + + private void addAttributeWithValue() throws SAXException { + // [NOCPP[ + if (metaBoundaryPassed && ElementName.META == tagName + && AttributeName.CHARSET == attributeName) { + err("A \u201Ccharset\u201D attribute on a \u201Cmeta\u201D element found after the first 1024 bytes."); + } + // ]NOCPP] + if (attributeName != null) { + String val = strBufToString(); // Ownership transferred to + // HtmlAttributes + // CPPONLY: if (mViewSource) { + // CPPONLY: mViewSource.MaybeLinkifyAttributeValue(attributeName, val); + // CPPONLY: } + attributes.addAttribute(attributeName, val + // [NOCPP[ + , xmlnsPolicy + // ]NOCPP] + // CPPONLY: , attributeLine + ); + attributeName = null; + } else { + // We have a duplicate attribute. Explicitly discard its value. + clearStrBufAfterUse(); + } + } + + // [NOCPP[ + + protected void startErrorReporting() throws SAXException { + + } + + // ]NOCPP] + + public void start() throws SAXException { + initializeWithoutStarting(); + tokenHandler.startTokenization(this); + // CPPONLY: line = 0; + // CPPONLY: col = 1; + // CPPONLY: nextCharOnNewLine = true; + // [NOCPP[ + startErrorReporting(); + // ]NOCPP] + } + + public boolean tokenizeBuffer(UTF16Buffer buffer) throws SAXException { + int state = stateSave; + int returnState = returnStateSave; + char c = '\u0000'; + shouldSuspend = false; + lastCR = false; + + int start = buffer.getStart(); + int end = buffer.getEnd(); + + // In C++, the caller of tokenizeBuffer needs to do this explicitly. + // [NOCPP[ + ensureBufferSpace(end - start); + // ]NOCPP] + + /** + * The index of the last <code>char</code> read from <code>buf</code>. + */ + int pos = start - 1; + + /** + * The index of the first <code>char</code> in <code>buf</code> that is + * part of a coalesced run of character tokens or + * <code>Integer.MAX_VALUE</code> if there is not a current run being + * coalesced. + */ + switch (state) { + case DATA: + case RCDATA: + case SCRIPT_DATA: + case PLAINTEXT: + case RAWTEXT: + case CDATA_SECTION: + case SCRIPT_DATA_ESCAPED: + case SCRIPT_DATA_ESCAPE_START: + case SCRIPT_DATA_ESCAPE_START_DASH: + case SCRIPT_DATA_ESCAPED_DASH: + case SCRIPT_DATA_ESCAPED_DASH_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPE_START: + case SCRIPT_DATA_DOUBLE_ESCAPED: + case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPE_END: + cstart = start; + break; + default: + cstart = Integer.MAX_VALUE; + break; + } + + /** + * The number of <code>char</code>s in <code>buf</code> that have + * meaning. (The rest of the array is garbage and should not be + * examined.) + */ + // CPPONLY: if (mViewSource) { + // CPPONLY: mViewSource.SetBuffer(buffer); + // CPPONLY: pos = stateLoop(state, c, pos, buffer.getBuffer(), false, returnState, buffer.getEnd()); + // CPPONLY: mViewSource.DropBuffer((pos == buffer.getEnd()) ? pos : pos + 1); + // CPPONLY: } else { + // CPPONLY: pos = stateLoop(state, c, pos, buffer.getBuffer(), false, returnState, buffer.getEnd()); + // CPPONLY: } + // [NOCPP[ + pos = stateLoop(state, c, pos, buffer.getBuffer(), false, returnState, + end); + // ]NOCPP] + if (pos == end) { + // exiting due to end of buffer + buffer.setStart(pos); + } else { + buffer.setStart(pos + 1); + } + return lastCR; + } + + // [NOCPP[ + private void ensureBufferSpace(int inputLength) throws SAXException { + // Add 2 to account for emissions of LT_GT, LT_SOLIDUS and RSQB_RSQB. + // Adding to the general worst case instead of only the + // TreeBuilder-exposed worst case to avoid re-introducing a bug when + // unifying the tokenizer and tree builder buffers in the future. + int worstCase = strBufLen + inputLength + charRefBufLen + 2; + tokenHandler.ensureBufferSpace(worstCase); + if (commentPolicy == XmlViolationPolicy.ALTER_INFOSET) { + // When altering infoset, if the comment contents are consecutive + // hyphens, each hyphen generates a space, too. These buffer + // contents never get emitted as characters() to the tokenHandler, + // which is why this calculation happens after the call to + // ensureBufferSpace on tokenHandler. + worstCase *= 2; + } + if (strBuf == null) { + // Add an arbitrary small value to avoid immediate reallocation + // once there are a few characters in the buffer. + strBuf = new char[worstCase + 128]; + } else if (worstCase > strBuf.length) { + // HotSpot reportedly allocates memory with 8-byte accuracy, so + // there's no point in trying to do math here to avoid slop. + // Maybe we should add some small constant to worstCase here + // but not doing that without profiling. In C++ with jemalloc, + // the corresponding method should do math to round up here + // to avoid slop. + char[] newBuf = new char[Math.max(worstCase, (strBuf.length*5)/4)]; + System.arraycopy(strBuf, 0, newBuf, 0, strBufLen); + strBuf = newBuf; + } + } + // ]NOCPP] + + @SuppressWarnings("unused") private int stateLoop(int state, char c, + int pos, @NoLength char[] buf, boolean reconsume, int returnState, + int endPos) throws SAXException { + boolean reportedConsecutiveHyphens = false; + /* + * Idioms used in this code: + * + * + * Consuming the next input character + * + * To consume the next input character, the code does this: if (++pos == + * endPos) { break stateloop; } c = checkChar(buf, pos); + * + * + * Staying in a state + * + * When there's a state that the tokenizer may stay in over multiple + * input characters, the state has a wrapper |for(;;)| loop and staying + * in the state continues the loop. + * + * + * Switching to another state + * + * To switch to another state, the code sets the state variable to the + * magic number of the new state. Then it either continues stateloop or + * breaks out of the state's own wrapper loop if the target state is + * right after the current state in source order. (This is a partial + * workaround for Java's lack of goto.) + * + * + * Reconsume support + * + * The spec sometimes says that an input character is reconsumed in + * another state. If a state can ever be entered so that an input + * character can be reconsumed in it, the state's code starts with an + * |if (reconsume)| that sets reconsume to false and skips over the + * normal code for consuming a new character. + * + * To reconsume the current character in another state, the code sets + * |reconsume| to true and then switches to the other state. + * + * + * Emitting character tokens + * + * This method emits character tokens lazily. Whenever a new range of + * character tokens starts, the field cstart must be set to the start + * index of the range. The flushChars() method must be called at the end + * of a range to flush it. + * + * + * U+0000 handling + * + * The various states have to handle the replacement of U+0000 with + * U+FFFD. However, if U+0000 would be reconsumed in another state, the + * replacement doesn't need to happen, because it's handled by the + * reconsuming state. + * + * + * LF handling + * + * Every state needs to increment the line number upon LF unless the LF + * gets reconsumed by another state which increments the line number. + * + * + * CR handling + * + * Every state needs to handle CR unless the CR gets reconsumed and is + * handled by the reconsuming state. The CR needs to be handled as if it + * were and LF, the lastCR field must be set to true and then this + * method must return. The IO driver will then swallow the next + * character if it is an LF to coalesce CRLF. + */ + stateloop: for (;;) { + switch (state) { + case DATA: + dataloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + switch (c) { + case '&': + /* + * U+0026 AMPERSAND (&) Switch to the character + * reference in data state. + */ + flushChars(buf, pos); + assert charRefBufLen == 0: "charRefBufLen not reset after previous use!"; + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\u0000'); + returnState = state; + state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos); + continue stateloop; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Switch to the tag + * open state. + */ + flushChars(buf, pos); + + state = transition(state, Tokenizer.TAG_OPEN, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break dataloop; + case '\u0000': + maybeEmitReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the input character as a + * character token. + * + * Stay in the data state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case TAG_OPEN: + tagopenloop: for (;;) { + /* + * The behavior of this state depends on the content + * model flag. + */ + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * If the content model flag is set to the PCDATA state + * Consume the next input character: + */ + if (c >= 'A' && c <= 'Z') { + /* + * U+0041 LATIN CAPITAL LETTER A through to U+005A + * LATIN CAPITAL LETTER Z Create a new start tag + * token, + */ + endTag = false; + /* + * set its tag name to the lowercase version of the + * input character (add 0x0020 to the character's + * code point), + */ + clearStrBufBeforeUse(); + appendStrBuf((char) (c + 0x20)); + containsHyphen = false; + /* then switch to the tag name state. */ + state = transition(state, Tokenizer.TAG_NAME, reconsume, pos); + /* + * (Don't emit the token yet; further details will + * be filled in before it is emitted.) + */ + // `break` optimizes; `continue stateloop;` would be valid + break tagopenloop; + } else if (c >= 'a' && c <= 'z') { + /* + * U+0061 LATIN SMALL LETTER A through to U+007A + * LATIN SMALL LETTER Z Create a new start tag + * token, + */ + endTag = false; + /* + * set its tag name to the input character, + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + containsHyphen = false; + /* then switch to the tag name state. */ + state = transition(state, Tokenizer.TAG_NAME, reconsume, pos); + /* + * (Don't emit the token yet; further details will + * be filled in before it is emitted.) + */ + // `break` optimizes; `continue stateloop;` would be valid + break tagopenloop; + } + switch (c) { + case '!': + /* + * U+0021 EXCLAMATION MARK (!) Switch to the + * markup declaration open state. + */ + state = transition(state, Tokenizer.MARKUP_DECLARATION_OPEN, reconsume, pos); + continue stateloop; + case '/': + /* + * U+002F SOLIDUS (/) Switch to the close tag + * open state. + */ + state = transition(state, Tokenizer.CLOSE_TAG_OPEN, reconsume, pos); + continue stateloop; + case '?': + // CPPONLY: if (viewingXmlSource) { + // CPPONLY: state = transition(state, + // CPPONLY: Tokenizer.PROCESSING_INSTRUCTION, + // CPPONLY: reconsume, + // CPPONLY: pos); + // CPPONLY: continue stateloop; + // CPPONLY: } + /* + * U+003F QUESTION MARK (?) Parse error. + */ + errProcessingInstruction(); + /* + * Switch to the bogus comment state. + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Parse error. + */ + errLtGt(); + /* + * Emit a U+003C LESS-THAN SIGN character token + * and a U+003E GREATER-THAN SIGN character + * token. + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 2); + /* Switch to the data state. */ + cstart = pos + 1; + state = transition(state, Tokenizer.DATA, reconsume, pos); + continue stateloop; + default: + /* + * Anything else Parse error. + */ + errBadCharAfterLt(c); + /* + * Emit a U+003C LESS-THAN SIGN character token + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + /* + * and reconsume the current input character in + * the data state. + */ + cstart = pos; + reconsume = true; + state = transition(state, Tokenizer.DATA, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case TAG_NAME: + tagnameloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + strBufToElementNameString(); + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the before attribute name state. + */ + strBufToElementNameString(); + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break tagnameloop; + case '/': + /* + * U+002F SOLIDUS (/) Switch to the self-closing + * start tag state. + */ + strBufToElementNameString(); + state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * tag token. + */ + strBufToElementNameString(); + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + if (c >= 'A' && c <= 'Z') { + /* + * U+0041 LATIN CAPITAL LETTER A through to + * U+005A LATIN CAPITAL LETTER Z Append the + * lowercase version of the current input + * character (add 0x0020 to the character's + * code point) to the current tag token's + * tag name. + */ + c += 0x20; + } else if (c == '-') { + containsHyphen = true; + } + /* + * Anything else Append the current input + * character to the current tag token's tag + * name. + */ + appendStrBuf(c); + /* + * Stay in the tag name state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BEFORE_ATTRIBUTE_NAME: + beforeattributenameloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the before attribute name state. + */ + continue; + case '/': + /* + * U+002F SOLIDUS (/) Switch to the self-closing + * start tag state. + */ + state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * tag token. + */ + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + case '\"': + case '\'': + case '<': + case '=': + /* + * U+0022 QUOTATION MARK (") U+0027 APOSTROPHE + * (') U+003C LESS-THAN SIGN (<) U+003D EQUALS + * SIGN (=) Parse error. + */ + errBadCharBeforeAttributeNameOrNull(c); + /* + * Treat it as per the "anything else" entry + * below. + */ + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Start a new attribute in the + * current tag token. + */ + if (c >= 'A' && c <= 'Z') { + /* + * U+0041 LATIN CAPITAL LETTER A through to + * U+005A LATIN CAPITAL LETTER Z Set that + * attribute's name to the lowercase version + * of the current input character (add + * 0x0020 to the character's code point) + */ + c += 0x20; + } + // CPPONLY: attributeLine = line; + /* + * Set that attribute's name to the current + * input character, + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + /* + * and its value to the empty string. + */ + // Will do later. + /* + * Switch to the attribute name state. + */ + state = transition(state, Tokenizer.ATTRIBUTE_NAME, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break beforeattributenameloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case ATTRIBUTE_NAME: + attributenameloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + attributeNameComplete(); + state = transition(state, Tokenizer.AFTER_ATTRIBUTE_NAME, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the after attribute name state. + */ + attributeNameComplete(); + state = transition(state, Tokenizer.AFTER_ATTRIBUTE_NAME, reconsume, pos); + continue stateloop; + case '/': + /* + * U+002F SOLIDUS (/) Switch to the self-closing + * start tag state. + */ + attributeNameComplete(); + addAttributeWithoutValue(); + state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos); + continue stateloop; + case '=': + /* + * U+003D EQUALS SIGN (=) Switch to the before + * attribute value state. + */ + attributeNameComplete(); + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_VALUE, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break attributenameloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * tag token. + */ + attributeNameComplete(); + addAttributeWithoutValue(); + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + case '\"': + case '\'': + case '<': + /* + * U+0022 QUOTATION MARK (") U+0027 APOSTROPHE + * (') U+003C LESS-THAN SIGN (<) Parse error. + */ + errQuoteOrLtInAttributeNameOrNull(c); + /* + * Treat it as per the "anything else" entry + * below. + */ + // CPPONLY: MOZ_FALLTHROUGH; + default: + if (c >= 'A' && c <= 'Z') { + /* + * U+0041 LATIN CAPITAL LETTER A through to + * U+005A LATIN CAPITAL LETTER Z Append the + * lowercase version of the current input + * character (add 0x0020 to the character's + * code point) to the current attribute's + * name. + */ + c += 0x20; + } + /* + * Anything else Append the current input + * character to the current attribute's name. + */ + appendStrBuf(c); + /* + * Stay in the attribute name state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BEFORE_ATTRIBUTE_VALUE: + beforeattributevalueloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the before attribute value state. + */ + continue; + case '"': + /* + * U+0022 QUOTATION MARK (") Switch to the + * attribute value (double-quoted) state. + */ + // CPPONLY: attributeLine = line; + clearStrBufBeforeUse(); + state = transition(state, Tokenizer.ATTRIBUTE_VALUE_DOUBLE_QUOTED, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break beforeattributevalueloop; + case '&': + /* + * U+0026 AMPERSAND (&) Switch to the attribute + * value (unquoted) state and reconsume this + * input character. + */ + // CPPONLY: attributeLine = line; + clearStrBufBeforeUse(); + reconsume = true; + state = transition(state, Tokenizer.ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos); + noteUnquotedAttributeValue(); + continue stateloop; + case '\'': + /* + * U+0027 APOSTROPHE (') Switch to the attribute + * value (single-quoted) state. + */ + // CPPONLY: attributeLine = line; + clearStrBufBeforeUse(); + state = transition(state, Tokenizer.ATTRIBUTE_VALUE_SINGLE_QUOTED, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Parse error. + */ + errAttributeValueMissing(); + /* + * Emit the current tag token. + */ + addAttributeWithoutValue(); + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + case '<': + case '=': + case '`': + /* + * U+003C LESS-THAN SIGN (<) U+003D EQUALS SIGN + * (=) U+0060 GRAVE ACCENT (`) + */ + errLtOrEqualsOrGraveInUnquotedAttributeOrNull(c); + /* + * Treat it as per the "anything else" entry + * below. + */ + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current attribute's value. + */ + // CPPONLY: attributeLine = line; + clearStrBufBeforeUse(); + appendStrBuf(c); + /* + * Switch to the attribute value (unquoted) + * state. + */ + + state = transition(state, Tokenizer.ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos); + noteUnquotedAttributeValue(); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case ATTRIBUTE_VALUE_DOUBLE_QUOTED: + attributevaluedoublequotedloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '"': + /* + * U+0022 QUOTATION MARK (") Switch to the after + * attribute value (quoted) state. + */ + addAttributeWithValue(); + + state = transition(state, Tokenizer.AFTER_ATTRIBUTE_VALUE_QUOTED, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break attributevaluedoublequotedloop; + case '&': + /* + * U+0026 AMPERSAND (&) Switch to the character + * reference in attribute value state, with the + * additional allowed character being U+0022 + * QUOTATION MARK ("). + */ + assert charRefBufLen == 0: "charRefBufLen not reset after previous use!"; + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\"'); + returnState = state; + state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current attribute's value. + */ + appendStrBuf(c); + /* + * Stay in the attribute value (double-quoted) + * state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case AFTER_ATTRIBUTE_VALUE_QUOTED: + afterattributevaluequotedloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the before attribute name state. + */ + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + continue stateloop; + case '/': + /* + * U+002F SOLIDUS (/) Switch to the self-closing + * start tag state. + */ + state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break afterattributevaluequotedloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * tag token. + */ + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + default: + /* + * Anything else Parse error. + */ + errNoSpaceBetweenAttributes(); + /* + * Reconsume the character in the before + * attribute name state. + */ + reconsume = true; + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SELF_CLOSING_START_TAG: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Set the self-closing + * flag of the current tag token. Emit the current + * tag token. + */ + state = transition(state, emitCurrentTagToken(true, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + default: + /* Anything else Parse error. */ + errSlashNotFollowedByGt(); + /* + * Reconsume the character in the before attribute + * name state. + */ + reconsume = true; + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + continue stateloop; + } + // no fallthrough, reordering opportunity + case ATTRIBUTE_VALUE_UNQUOTED: + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + addAttributeWithValue(); + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the before attribute name state. + */ + addAttributeWithValue(); + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + continue stateloop; + case '&': + /* + * U+0026 AMPERSAND (&) Switch to the character + * reference in attribute value state, with the + * additional allowed character being U+003E + * GREATER-THAN SIGN (>) + */ + assert charRefBufLen == 0: "charRefBufLen not reset after previous use!"; + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('>'); + returnState = state; + state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * tag token. + */ + addAttributeWithValue(); + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + case '<': + case '\"': + case '\'': + case '=': + case '`': + /* + * U+0022 QUOTATION MARK (") U+0027 APOSTROPHE + * (') U+003C LESS-THAN SIGN (<) U+003D EQUALS + * SIGN (=) U+0060 GRAVE ACCENT (`) Parse error. + */ + errUnquotedAttributeValOrNull(c); + /* + * Treat it as per the "anything else" entry + * below. + */ + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current attribute's value. + */ + appendStrBuf(c); + /* + * Stay in the attribute value (unquoted) state. + */ + continue; + } + } + // no fallthrough, reordering opportunity + case AFTER_ATTRIBUTE_NAME: + for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the after attribute name state. + */ + continue; + case '/': + /* + * U+002F SOLIDUS (/) Switch to the self-closing + * start tag state. + */ + addAttributeWithoutValue(); + state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos); + continue stateloop; + case '=': + /* + * U+003D EQUALS SIGN (=) Switch to the before + * attribute value state. + */ + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_VALUE, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * tag token. + */ + addAttributeWithoutValue(); + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + /* + * Switch to the data state. + */ + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + case '\"': + case '\'': + case '<': + errQuoteOrLtInAttributeNameOrNull(c); + /* + * Treat it as per the "anything else" entry + * below. + */ + // CPPONLY: MOZ_FALLTHROUGH; + default: + addAttributeWithoutValue(); + /* + * Anything else Start a new attribute in the + * current tag token. + */ + if (c >= 'A' && c <= 'Z') { + /* + * U+0041 LATIN CAPITAL LETTER A through to + * U+005A LATIN CAPITAL LETTER Z Set that + * attribute's name to the lowercase version + * of the current input character (add + * 0x0020 to the character's code point) + */ + c += 0x20; + } + /* + * Set that attribute's name to the current + * input character, + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + /* + * and its value to the empty string. + */ + // Will do later. + /* + * Switch to the attribute name state. + */ + state = transition(state, Tokenizer.ATTRIBUTE_NAME, reconsume, pos); + continue stateloop; + } + } + // no fallthrough, reordering opportunity + case MARKUP_DECLARATION_OPEN: + markupdeclarationopenloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * If the next two characters are both U+002D + * HYPHEN-MINUS characters (-), consume those two + * characters, create a comment token whose data is the + * empty string, and switch to the comment start state. + * + * Otherwise, if the next seven characters are an ASCII + * case-insensitive match for the word "DOCTYPE", then + * consume those characters and switch to the DOCTYPE + * state. + * + * Otherwise, if the insertion mode is + * "in foreign content" and the current node is not an + * element in the HTML namespace and the next seven + * characters are an case-sensitive match for the string + * "[CDATA[" (the five uppercase letters "CDATA" with a + * U+005B LEFT SQUARE BRACKET character before and + * after), then consume those characters and switch to + * the CDATA section state. + * + * Otherwise, is is a parse error. Switch to the bogus + * comment state. The next character that is consumed, + * if any, is the first character that will be in the + * comment. + */ + switch (c) { + case '-': + clearStrBufBeforeUse(); + appendStrBuf(c); + state = transition(state, Tokenizer.MARKUP_DECLARATION_HYPHEN, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break markupdeclarationopenloop; + case 'd': + case 'D': + clearStrBufBeforeUse(); + appendStrBuf(c); + index = 0; + state = transition(state, Tokenizer.MARKUP_DECLARATION_OCTYPE, reconsume, pos); + continue stateloop; + case '[': + if (tokenHandler.cdataSectionAllowed()) { + clearStrBufBeforeUse(); + appendStrBuf(c); + index = 0; + state = transition(state, Tokenizer.CDATA_START, reconsume, pos); + continue stateloop; + } + // CPPONLY: MOZ_FALLTHROUGH; + default: + errBogusComment(); + clearStrBufBeforeUse(); + reconsume = true; + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case MARKUP_DECLARATION_HYPHEN: + markupdeclarationhyphenloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '-': + clearStrBufAfterOneHyphen(); + state = transition(state, Tokenizer.COMMENT_START, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break markupdeclarationhyphenloop; + default: + errBogusComment(); + reconsume = true; + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT_START: + reportedConsecutiveHyphens = false; + commentstartloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Comment start state + * + * + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Switch to the comment + * start dash state. + */ + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_START_DASH, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Parse error. + */ + errPrematureEndOfComment(); + /* Emit the comment token. */ + emitComment(0, pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '<': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break commentstartloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the input character to + * the comment token's data. + */ + appendStrBuf(c); + /* + * Switch to the comment state. + */ + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break commentstartloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT: + commentloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Comment state Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Switch to the comment + * end dash state + */ + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_END_DASH, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break commentloop; + case '<': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the input character to + * the comment token's data. + */ + appendStrBuf(c); + /* + * Stay in the comment state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT_END_DASH: + commentenddashloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Comment end dash state Consume the next input + * character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Switch to the comment + * end state + */ + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_END, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break commentenddashloop; + case '<': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append a U+002D HYPHEN-MINUS + * (-) character and the input character to the + * comment token's data. + */ + appendStrBuf(c); + /* + * Switch to the comment state. + */ + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT_END: + commentendloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Comment end dash state Consume the next input + * character: + */ + switch (c) { + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the comment + * token. + */ + emitComment(2, pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '-': + /* U+002D HYPHEN-MINUS (-) Parse error. */ + /* + * Append a U+002D HYPHEN-MINUS (-) character to + * the comment token's data. + */ + adjustDoubleHyphenAndAppendToStrBufAndErr(c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + /* + * Stay in the comment end state. + */ + continue; + case '<': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos); + continue stateloop; + case '\r': + adjustDoubleHyphenAndAppendToStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break stateloop; + case '\n': + adjustDoubleHyphenAndAppendToStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + case '!': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_END_BANG, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break commentendloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Append two U+002D HYPHEN-MINUS (-) characters + * and the input character to the comment + * token's data. + */ + adjustDoubleHyphenAndAppendToStrBufAndErr(c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + /* + * Switch to the comment state. + */ + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT_END_BANG: + for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Comment end bang state + * + * Consume the next input character: + */ + switch (c) { + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the comment + * token. + */ + emitComment(3, pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '-': + /* + * Append two U+002D HYPHEN-MINUS (-) characters + * and a U+0021 EXCLAMATION MARK (!) character + * to the comment token's data. + */ + appendStrBuf(c); + /* + * Switch to the comment end dash state. + */ + state = transition(state, Tokenizer.COMMENT_END_DASH, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append two U+002D HYPHEN-MINUS + * (-) characters, a U+0021 EXCLAMATION MARK (!) + * character, and the input character to the + * comment token's data. Switch to the comment + * state. + */ + appendStrBuf(c); + /* + * Switch to the comment state. + */ + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + } + } + // no fallthrough, reordering opportunity + case COMMENT_LESSTHAN: + commentlessthanloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '!': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN_BANG, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break commentlessthanloop; + case '<': + appendStrBuf(c); + continue; + case '-': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_END_DASH, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT_LESSTHAN_BANG: + commentlessthanbangloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '-': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN_BANG_DASH, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break commentlessthanbangloop; + case '<': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT_LESSTHAN_BANG_DASH: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '-': + appendStrBuf(c); + state = transition(state, + Tokenizer.COMMENT_LESSTHAN_BANG_DASH_DASH, + reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break; + case '<': + appendStrBuf(c); + state = transition(state, + Tokenizer.COMMENT_LESSTHAN, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, + reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, + reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT, + reconsume, pos); + continue stateloop; + } + // CPPONLY: MOZ_FALLTHROUGH; + case COMMENT_LESSTHAN_BANG_DASH_DASH: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '>': + appendStrBuf(c); + emitComment(3, pos); + state = transition(state, Tokenizer.DATA, reconsume, + pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '-': + errNestedComment(); + adjustDoubleHyphenAndAppendToStrBufAndErr(c, + reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = transition(state, Tokenizer.COMMENT_END, + reconsume, pos); + continue stateloop; + case '\r': + c = '\n'; + silentCarriageReturn(); + errNestedComment(); + adjustDoubleHyphenAndAppendToStrBufAndErr(c, + reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = transition(state, Tokenizer.COMMENT, + reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + errNestedComment(); + adjustDoubleHyphenAndAppendToStrBufAndErr(c, + reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = transition(state, Tokenizer.COMMENT, + reconsume, pos); + continue stateloop; + case '!': + errNestedComment(); + adjustDoubleHyphenAndAppendToStrBufAndErr(c, + reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = transition(state, + Tokenizer.COMMENT_END_BANG, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + errNestedComment(); + adjustDoubleHyphenAndAppendToStrBufAndErr(c, + reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = transition(state, Tokenizer.COMMENT, + reconsume, pos); + continue stateloop; + } + // no fallthrough, reordering opportunity + case COMMENT_START_DASH: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Comment start dash state + * + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Switch to the comment end + * state + */ + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_END, reconsume, pos); + continue stateloop; + case '>': + errPrematureEndOfComment(); + /* Emit the comment token. */ + emitComment(1, pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '<': + appendStrBuf(c); + state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos); + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Append a U+002D HYPHEN-MINUS character (-) and + * the current input character to the comment + * token's data. + */ + appendStrBuf(c); + /* + * Switch to the comment state. + */ + state = transition(state, Tokenizer.COMMENT, reconsume, pos); + continue stateloop; + } + // no fallthrough, reordering opportunity + case CDATA_START: + for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + if (index < 6) { // CDATA_LSQB.length + if (c == Tokenizer.CDATA_LSQB[index]) { + appendStrBuf(c); + } else { + errBogusComment(); + reconsume = true; + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + } + index++; + continue; + } else { + clearStrBufAfterUse(); + cstart = pos; // start coalescing + reconsume = true; + state = transition(state, Tokenizer.CDATA_SECTION, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case CDATA_SECTION: + cdatasectionloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + switch (c) { + case ']': + flushChars(buf, pos); + state = transition(state, Tokenizer.CDATA_RSQB, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break cdatasectionloop; + case '\u0000': + maybeEmitReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case CDATA_RSQB: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case ']': + state = transition(state, Tokenizer.CDATA_RSQB_RSQB, + reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break; + default: + tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 1); + cstart = pos; + reconsume = true; + state = transition(state, Tokenizer.CDATA_SECTION, + reconsume, pos); + continue stateloop; + } + // CPPONLY: MOZ_FALLTHROUGH; + case CDATA_RSQB_RSQB: + cdatarsqbrsqb: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case ']': + // Saw a third ]. Emit one ] (logically the + // first one) and stay in this state to + // remember that the last two characters seen + // have been ]]. + tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 1); + continue; + case '>': + cstart = pos + 1; + state = transition(state, Tokenizer.DATA, reconsume, pos); + // Since a CDATA section starts with a less-than sign, it + // participates in the suspension-after-current-token + // behavior. (The suspension can be requested when the + // less-than sign has been seen but we don't yet know the + // resulting token type.) Therefore, we need to deal with + // a potential request here. + suspendIfRequestedAfterCurrentNonTextToken(); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 2); + cstart = pos; + reconsume = true; + state = transition(state, Tokenizer.CDATA_SECTION, reconsume, pos); + continue stateloop; + } + } + // no fallthrough, reordering opportunity + case ATTRIBUTE_VALUE_SINGLE_QUOTED: + attributevaluesinglequotedloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '\'': + /* + * U+0027 APOSTROPHE (') Switch to the after + * attribute value (quoted) state. + */ + addAttributeWithValue(); + + state = transition(state, Tokenizer.AFTER_ATTRIBUTE_VALUE_QUOTED, reconsume, pos); + continue stateloop; + case '&': + /* + * U+0026 AMPERSAND (&) Switch to the character + * reference in attribute value state, with the + * + additional allowed character being U+0027 + * APOSTROPHE ('). + */ + assert charRefBufLen == 0: "charRefBufLen not reset after previous use!"; + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\''); + returnState = state; + state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break attributevaluesinglequotedloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current attribute's value. + */ + appendStrBuf(c); + /* + * Stay in the attribute value (double-quoted) + * state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case CONSUME_CHARACTER_REFERENCE: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Unlike the definition is the spec, this state does not + * return a value and never requires the caller to + * backtrack. This state takes care of emitting characters + * or appending to the current attribute value. It also + * takes care of that in the case when consuming the + * character reference fails. + */ + /* + * This section defines how to consume a character + * reference. This definition is used when parsing character + * references in text and in attributes. + * + * The behavior depends on the identity of the next + * character (the one immediately after the U+0026 AMPERSAND + * character): + */ + switch (c) { + case ' ': + case '\t': + case '\n': + case '\r': // we'll reconsume! + case '\u000C': + case '<': + case '&': + case '\u0000': + case ';': + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + case '#': + /* + * U+0023 NUMBER SIGN (#) Consume the U+0023 NUMBER + * SIGN. + */ + appendCharRefBuf('#'); + state = transition(state, Tokenizer.CONSUME_NCR, reconsume, pos); + continue stateloop; + default: + if (c == additional) { + emitOrAppendCharRefBuf(returnState); + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + if (c >= 'a' && c <= 'z') { + firstCharKey = c - 'a' + 26; + } else if (c >= 'A' && c <= 'Z') { + firstCharKey = c - 'A'; + } else { + // No match + if (c == ';') { + errNoNamedCharacterMatch(); + } + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + // Didn't fail yet + appendCharRefBuf(c); + state = transition(state, Tokenizer.CHARACTER_REFERENCE_HILO_LOOKUP, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break; + } + // CPPONLY: MOZ_FALLTHROUGH; + case CHARACTER_REFERENCE_HILO_LOOKUP: + { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * The data structure is as follows: + * + * HILO_ACCEL is a two-dimensional int array whose major + * index corresponds to the second character of the + * character reference (code point as index) and the + * minor index corresponds to the first character of the + * character reference (packed so that A-Z runs from 0 + * to 25 and a-z runs from 26 to 51). This layout makes + * it easier to use the sparseness of the data structure + * to omit parts of it: The second dimension of the + * table is null when no character reference starts with + * the character corresponding to that row. + * + * The int value HILO_ACCEL (by these indeces) is zero + * if there exists no character reference starting with + * that two-letter prefix. Otherwise, the value is an + * int that packs two shorts so that the higher short is + * the index of the highest character reference name + * with that prefix in NAMES and the lower short + * corresponds to the index of the lowest character + * reference name with that prefix. (It happens that the + * first two character reference names share their + * prefix so the packed int cannot be 0 by packing the + * two shorts.) + * + * NAMES is an array of byte arrays where each byte + * array encodes the name of a character references as + * ASCII. The names omit the first two letters of the + * name. (Since storing the first two letters would be + * redundant with the data contained in HILO_ACCEL.) The + * entries are lexically sorted. + * + * For a given index in NAMES, the same index in VALUES + * contains the corresponding expansion as an array of + * two UTF-16 code units (either the character and + * U+0000 or a suggogate pair). + */ + int hilo = 0; + if (c <= 'z') { + @Const @NoLength int[] row = NamedCharactersAccel.HILO_ACCEL[c]; + if (row != null) { + hilo = row[firstCharKey]; + } + } + if (hilo == 0) { + if (c == ';') { + errNoNamedCharacterMatch(); + } + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + // Didn't fail yet + appendCharRefBuf(c); + lo = hilo & 0xFFFF; + hi = hilo >> 16; + entCol = -1; + candidate = -1; + charRefBufMark = 0; + state = transition(state, Tokenizer.CHARACTER_REFERENCE_TAIL, reconsume, pos); + // fallthrough optimizes; `continue stateloop;` would also be valid + } + // CPPONLY: MOZ_FALLTHROUGH; + case CHARACTER_REFERENCE_TAIL: + outer: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + entCol++; + /* + * Consume the maximum number of characters possible, + * with the consumed characters matching one of the + * identifiers in the first column of the named + * character references table (in a case-sensitive + * manner). + */ + loloop: for (;;) { + if (hi < lo) { + break outer; + } + if (entCol == NamedCharacters.NAMES[lo].length()) { + candidate = lo; + charRefBufMark = charRefBufLen; + lo++; + } else if (entCol > NamedCharacters.NAMES[lo].length()) { + break outer; + } else if (c > NamedCharacters.NAMES[lo].charAt(entCol)) { + lo++; + } else { + break loloop; + } + } + + hiloop: for (;;) { + if (hi < lo) { + break outer; + } + if (entCol == NamedCharacters.NAMES[hi].length()) { + break hiloop; + } + if (entCol > NamedCharacters.NAMES[hi].length()) { + break outer; + } else if (c < NamedCharacters.NAMES[hi].charAt(entCol)) { + hi--; + } else { + break hiloop; + } + } + + if (c == ';') { + // If we see a semicolon, there cannot be a + // longer match. Break the loop. However, before + // breaking, take the longest match so far as the + // candidate, if we are just about to complete a + // match. + if (entCol + 1 == NamedCharacters.NAMES[lo].length()) { + candidate = lo; + charRefBufMark = charRefBufLen; + } + break outer; + } + + if (hi < lo) { + break outer; + } + appendCharRefBuf(c); + continue; + } + + if (candidate == -1) { + // reconsume deals with CR, LF or nul + if (c == ';') { + errNoNamedCharacterMatch(); + } + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } else { + // c can't be CR, LF or nul if we got here + @Const @CharacterName String candidateName = NamedCharacters.NAMES[candidate]; + if (candidateName.length() == 0 + || candidateName.charAt(candidateName.length() - 1) != ';') { + /* + * If the last character matched is not a U+003B + * SEMICOLON (;), there is a parse error. + */ + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + /* + * If the entity is being consumed as part of an + * attribute, and the last character matched is + * not a U+003B SEMICOLON (;), + */ + char ch; + if (charRefBufMark == charRefBufLen) { + ch = c; + } else { + ch = charRefBuf[charRefBufMark]; + } + if (ch == '=' || (ch >= '0' && ch <= '9') + || (ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z')) { + /* + * and the next character is either a U+003D + * EQUALS SIGN character (=) or in the range + * U+0030 DIGIT ZERO to U+0039 DIGIT NINE, + * U+0041 LATIN CAPITAL LETTER A to U+005A + * LATIN CAPITAL LETTER Z, or U+0061 LATIN + * SMALL LETTER A to U+007A LATIN SMALL + * LETTER Z, then, for historical reasons, + * all the characters that were matched + * after the U+0026 AMPERSAND (&) must be + * unconsumed, and nothing is returned. + */ + if (c == ';') { + errNoNamedCharacterMatch(); + } + appendCharRefBufToStrBuf(); + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + } + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + errUnescapedAmpersandInterpretedAsCharacterReference(); + } else { + errNotSemicolonTerminated(); + } + } + + /* + * Otherwise, return a character token for the character + * corresponding to the entity name (as given by the + * second column of the named character references + * table). + */ + // CPPONLY: completedNamedCharacterReference(); + @Const @NoLength char[] val = NamedCharacters.VALUES[candidate]; + if ( + // [NOCPP[ + val.length == 1 + // ]NOCPP] + // CPPONLY: val[1] == 0 + ) { + emitOrAppendOne(val, returnState); + } else { + emitOrAppendTwo(val, returnState); + } + // this is so complicated! + if (charRefBufMark < charRefBufLen) { + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + appendStrBuf(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } else { + tokenHandler.characters(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } + } + // charRefBufLen will be zeroed below! + + // Check if we broke out early with c being the last + // character that matched as opposed to being the + // first one that didn't match. In the case of an + // early break, the next run on text should start + // *after* the current character and the current + // character shouldn't be reconsumed. + boolean earlyBreak = (c == ';' && charRefBufMark == charRefBufLen); + charRefBufLen = 0; + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = earlyBreak ? pos + 1 : pos; + } + reconsume = !earlyBreak; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + /* + * If the markup contains I'm ¬it; I tell you, the + * entity is parsed as "not", as in, I'm ¬it; I tell + * you. But if the markup was I'm ∉ I tell you, + * the entity would be parsed as "notin;", resulting in + * I'm ∉ I tell you. + */ + } + // no fallthrough, reordering opportunity + case CONSUME_NCR: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + value = 0; + seenDigits = false; + /* + * The behavior further depends on the character after the + * U+0023 NUMBER SIGN: + */ + switch (c) { + case 'x': + case 'X': + + /* + * U+0078 LATIN SMALL LETTER X U+0058 LATIN CAPITAL + * LETTER X Consume the X. + * + * Follow the steps below, but using the range of + * characters U+0030 DIGIT ZERO through to U+0039 + * DIGIT NINE, U+0061 LATIN SMALL LETTER A through + * to U+0066 LATIN SMALL LETTER F, and U+0041 LATIN + * CAPITAL LETTER A, through to U+0046 LATIN CAPITAL + * LETTER F (in other words, 0-9, A-F, a-f). + * + * When it comes to interpreting the number, + * interpret it as a hexadecimal number. + */ + appendCharRefBuf(c); + state = transition(state, Tokenizer.HEX_NCR_LOOP, reconsume, pos); + continue stateloop; + default: + /* + * Anything else Follow the steps below, but using + * the range of characters U+0030 DIGIT ZERO through + * to U+0039 DIGIT NINE (i.e. just 0-9). + * + * When it comes to interpreting the number, + * interpret it as a decimal number. + */ + reconsume = true; + state = transition(state, Tokenizer.DECIMAL_NRC_LOOP, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break; + } + // CPPONLY: MOZ_FALLTHROUGH; + case DECIMAL_NRC_LOOP: + decimalloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume as many characters as match the range of + * characters given above. + */ + assert value >= 0: "value must not become negative."; + if (c >= '0' && c <= '9') { + seenDigits = true; + // Avoid overflow + if (value <= 0x10FFFF) { + value *= 10; + value += c - '0'; + } + continue; + } else if (c == ';') { + if (seenDigits) { + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos + 1; + } + state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break decimalloop; + } else { + errNoDigitsInNCR(); + appendCharRefBuf(';'); + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos + 1; + } + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + } else { + /* + * If no characters match the range, then don't + * consume any characters (and unconsume the U+0023 + * NUMBER SIGN character and, if appropriate, the X + * character). This is a parse error; nothing is + * returned. + * + * Otherwise, if the next character is a U+003B + * SEMICOLON, consume that too. If it isn't, there + * is a parse error. + */ + if (!seenDigits) { + errNoDigitsInNCR(); + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } else { + errCharRefLacksSemicolon(); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break decimalloop; + } + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case HANDLE_NCR_VALUE: + // WARNING previous state sets reconsume + // We are not going to emit the contents of charRefBuf. + charRefBufLen = 0; + // XXX inline this case if the method size can take it + handleNcrValue(returnState); + state = transition(state, returnState, reconsume, pos); + continue stateloop; + // no fallthrough, reordering opportunity + case HEX_NCR_LOOP: + for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume as many characters as match the range of + * characters given above. + */ + assert value >= 0: "value must not become negative."; + if (c >= '0' && c <= '9') { + seenDigits = true; + // Avoid overflow + if (value <= 0x10FFFF) { + value *= 16; + value += c - '0'; + } + continue; + } else if (c >= 'A' && c <= 'F') { + seenDigits = true; + // Avoid overflow + if (value <= 0x10FFFF) { + value *= 16; + value += c - 'A' + 10; + } + continue; + } else if (c >= 'a' && c <= 'f') { + seenDigits = true; + // Avoid overflow + if (value <= 0x10FFFF) { + value *= 16; + value += c - 'a' + 10; + } + continue; + } else if (c == ';') { + if (seenDigits) { + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos + 1; + } + state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos); + continue stateloop; + } else { + errNoDigitsInNCR(); + appendCharRefBuf(';'); + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos + 1; + } + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + } else { + /* + * If no characters match the range, then don't + * consume any characters (and unconsume the U+0023 + * NUMBER SIGN character and, if appropriate, the X + * character). This is a parse error; nothing is + * returned. + * + * Otherwise, if the next character is a U+003B + * SEMICOLON, consume that too. If it isn't, there + * is a parse error. + */ + if (!seenDigits) { + errNoDigitsInNCR(); + emitOrAppendCharRefBuf(returnState); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } else { + errCharRefLacksSemicolon(); + if ((returnState & DATA_AND_RCDATA_MASK) == 0) { + cstart = pos; + } + reconsume = true; + state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos); + continue stateloop; + } + } + } + // no fallthrough, reordering opportunity + case PLAINTEXT: + plaintextloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + switch (c) { + case '\u0000': + emitPlaintextReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Stay in the + * RAWTEXT state. + */ + continue; + } + } + // no fallthrough, reordering opportunity + case CLOSE_TAG_OPEN: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Otherwise, if the content model flag is set to the PCDATA + * state, or if the next few characters do match that tag + * name, consume the next input character: + */ + switch (c) { + case '>': + /* U+003E GREATER-THAN SIGN (>) Parse error. */ + errLtSlashGt(); + /* + * Switch to the data state. + */ + cstart = pos + 1; + state = transition(state, Tokenizer.DATA, reconsume, pos); + continue stateloop; + case '\r': + silentCarriageReturn(); + /* Anything else Parse error. */ + errGarbageAfterLtSlash(); + /* + * Switch to the bogus comment state. + */ + clearStrBufBeforeUse(); + appendStrBuf('\n'); + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + /* Anything else Parse error. */ + errGarbageAfterLtSlash(); + /* + * Switch to the bogus comment state. + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + if (c >= 'A' && c <= 'Z') { + c += 0x20; + } + if (c >= 'a' && c <= 'z') { + /* + * U+0061 LATIN SMALL LETTER A through to U+007A + * LATIN SMALL LETTER Z Create a new end tag + * token, + */ + endTag = true; + /* + * set its tag name to the input character, + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + containsHyphen = false; + /* + * then switch to the tag name state. (Don't + * emit the token yet; further details will be + * filled in before it is emitted.) + */ + state = transition(state, Tokenizer.TAG_NAME, reconsume, pos); + continue stateloop; + } else { + /* Anything else Parse error. */ + errGarbageAfterLtSlash(); + /* + * Switch to the bogus comment state. + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + } + } + // no fallthrough, reordering opportunity + case RCDATA: + rcdataloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + switch (c) { + case '&': + /* + * U+0026 AMPERSAND (&) Switch to the character + * reference in RCDATA state. + */ + flushChars(buf, pos); + assert charRefBufLen == 0: "charRefBufLen not reset after previous use!"; + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\u0000'); + returnState = state; + state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos); + continue stateloop; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Switch to the + * RCDATA less-than sign state. + */ + flushChars(buf, pos); + + returnState = state; + state = transition(state, Tokenizer.RAWTEXT_RCDATA_LESS_THAN_SIGN, reconsume, pos); + continue stateloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Emit the current input character as a + * character token. Stay in the RCDATA state. + */ + continue; + } + } + // no fallthrough, reordering opportunity + case RAWTEXT: + rawtextloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + switch (c) { + case '<': + /* + * U+003C LESS-THAN SIGN (<) Switch to the + * RAWTEXT less-than sign state. + */ + flushChars(buf, pos); + + returnState = state; + state = transition(state, Tokenizer.RAWTEXT_RCDATA_LESS_THAN_SIGN, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break rawtextloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Emit the current input character as a + * character token. Stay in the RAWTEXT state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case RAWTEXT_RCDATA_LESS_THAN_SIGN: + rawtextrcdatalessthansignloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '/': + /* + * U+002F SOLIDUS (/) Set the temporary buffer + * to the empty string. Switch to the script + * data end tag open state. + */ + index = 0; + clearStrBufBeforeUse(); + state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break rawtextrcdatalessthansignloop; + default: + /* + * Otherwise, emit a U+003C LESS-THAN SIGN + * character token + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + /* + * and reconsume the current input character in + * the data state. + */ + cstart = pos; + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case NON_DATA_END_TAG_NAME: + for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * ASSERT! when entering this state, set index to 0 and + * call clearStrBufBeforeUse(); Let's implement the above + * without lookahead. strBuf is the 'temporary buffer'. + */ + if (endTagExpectationAsArray == null) { + tokenHandler.characters(Tokenizer.LT_SOLIDUS, + 0, 2); + cstart = pos; + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } else if (index < endTagExpectationAsArray.length) { + char e = endTagExpectationAsArray[index]; + char folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != e) { + // [NOCPP[ + errHtml4LtSlashInRcdata(folded); + // ]NOCPP] + tokenHandler.characters(Tokenizer.LT_SOLIDUS, + 0, 2); + emitStrBuf(); + cstart = pos; + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + appendStrBuf(c); + index++; + continue; + } else { + endTag = true; + // XXX replace contentModelElement with different + // type + tagName = endTagExpectation; + switch (c) { + case '\r': + silentCarriageReturn(); + clearStrBufAfterUse(); // strBuf not used + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE + * FEED (LF) U+000C FORM FEED (FF) U+0020 + * SPACE If the current end tag token is an + * appropriate end tag token, then switch to + * the before attribute name state. + */ + clearStrBufAfterUse(); // strBuf not used + state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos); + continue stateloop; + case '/': + /* + * U+002F SOLIDUS (/) If the current end tag + * token is an appropriate end tag token, + * then switch to the self-closing start tag + * state. + */ + clearStrBufAfterUse(); // strBuf not used + state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) If the + * current end tag token is an appropriate + * end tag token, then emit the current tag + * token and switch to the data state. + */ + clearStrBufAfterUse(); // strBuf not used + state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + /* + * Emit a U+003C LESS-THAN SIGN character + * token, a U+002F SOLIDUS character token, + * a character token for each of the + * characters in the temporary buffer (in + * the order they were added to the buffer), + * and reconsume the current input character + * in the RAWTEXT state. + */ + // [NOCPP[ + errWarnLtSlashInRcdata(); + // ]NOCPP] + tokenHandler.characters( + Tokenizer.LT_SOLIDUS, 0, 2); + emitStrBuf(); + cstart = pos; // don't drop the + // character + reconsume = true; + state = transition(state, returnState, reconsume, pos); + continue stateloop; + } + } + } + // no fallthrough, reordering opportunity + // BEGIN HOTSPOT WORKAROUND + case BOGUS_COMMENT: + boguscommentloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume every character up to and including the first + * U+003E GREATER-THAN SIGN character (>) or the end of + * the file (EOF), whichever comes first. Emit a comment + * token whose data is the concatenation of all the + * characters starting from and including the character + * that caused the state machine to switch into the + * bogus comment state, up to and including the + * character immediately before the last consumed + * character (i.e. up to the character just before the + * U+003E or EOF character). (If the comment was started + * by the end of the file (EOF), the token is empty.) + * + * Switch to the data state. + * + * If the end of the file was reached, reconsume the EOF + * character. + */ + switch (c) { + case '>': + emitComment(0, pos); + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '-': + appendStrBuf(c); + state = transition(state, Tokenizer.BOGUS_COMMENT_HYPHEN, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break boguscommentloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + appendStrBuf(c); + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BOGUS_COMMENT_HYPHEN: + boguscommenthyphenloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '>': + // [NOCPP[ + maybeAppendSpaceToBogusComment(); + // ]NOCPP] + emitComment(0, pos); + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '-': + appendSecondHyphenToBogusComment(); + continue boguscommenthyphenloop; + case '\r': + appendStrBufCarriageReturn(); + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + break stateloop; + case '\n': + appendStrBufLineFeed(); + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + appendStrBuf(c); + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + } + } + // no fallthrough, reordering opportunity + case SCRIPT_DATA: + scriptdataloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + switch (c) { + case '<': + /* + * U+003C LESS-THAN SIGN (<) Switch to the + * script data less-than sign state. + */ + flushChars(buf, pos); + returnState = state; + state = transition(state, Tokenizer.SCRIPT_DATA_LESS_THAN_SIGN, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdataloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Stay in the + * script data state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_LESS_THAN_SIGN: + scriptdatalessthansignloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '/': + /* + * U+002F SOLIDUS (/) Set the temporary buffer + * to the empty string. Switch to the script + * data end tag open state. + */ + index = 0; + clearStrBufBeforeUse(); + state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos); + continue stateloop; + case '!': + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + cstart = pos; + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPE_START, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdatalessthansignloop; + default: + /* + * Otherwise, emit a U+003C LESS-THAN SIGN + * character token + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + /* + * and reconsume the current input character in + * the data state. + */ + cstart = pos; + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_ESCAPE_START: + scriptdataescapestartloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Switch to the + * script data escape start dash state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPE_START_DASH, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdataescapestartloop; + default: + /* + * Anything else Reconsume the current input + * character in the script data state. + */ + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_ESCAPE_START_DASH: + scriptdataescapestartdashloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Switch to the + * script data escaped dash dash state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_DASH_DASH, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdataescapestartdashloop; + default: + /* + * Anything else Reconsume the current input + * character in the script data state. + */ + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_ESCAPED_DASH_DASH: + scriptdataescapeddashdashloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Stay in the + * script data escaped dash dash state. + */ + continue; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Switch to the + * script data escaped less-than sign state. + */ + flushChars(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, reconsume, pos); + continue stateloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit a U+003E + * GREATER-THAN SIGN character token. Switch to + * the script data state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos); + continue stateloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + break scriptdataescapeddashdashloop; + case '\r': + emitCarriageReturn(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Switch to the + * script data escaped state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdataescapeddashdashloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_ESCAPED: + scriptdataescapedloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Switch to the + * script data escaped dash state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_DASH, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdataescapedloop; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Switch to the + * script data escaped less-than sign state. + */ + flushChars(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, reconsume, pos); + continue stateloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Stay in the + * script data escaped state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_ESCAPED_DASH: + scriptdataescapeddashloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Switch to the + * script data escaped dash dash state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_DASH_DASH, reconsume, pos); + continue stateloop; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Switch to the + * script data escaped less-than sign state. + */ + flushChars(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdataescapeddashloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + continue stateloop; + case '\r': + emitCarriageReturn(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Switch to the + * script data escaped state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: + scriptdataescapedlessthanloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '/': + /* + * U+002F SOLIDUS (/) Set the temporary buffer + * to the empty string. Switch to the script + * data escaped end tag open state. + */ + index = 0; + clearStrBufBeforeUse(); + returnState = Tokenizer.SCRIPT_DATA_ESCAPED; + state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos); + continue stateloop; + case 'S': + case 's': + /* + * U+0041 LATIN CAPITAL LETTER A through to + * U+005A LATIN CAPITAL LETTER Z Emit a U+003C + * LESS-THAN SIGN character token and the + * current input character as a character token. + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + cstart = pos; + index = 1; + /* + * Set the temporary buffer to the empty string. + * Append the lowercase version of the current + * input character (add 0x0020 to the + * character's code point) to the temporary + * buffer. Switch to the script data double + * escape start state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPE_START, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdataescapedlessthanloop; + default: + /* + * Anything else Emit a U+003C LESS-THAN SIGN + * character token and reconsume the current + * input character in the script data escaped + * state. + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + cstart = pos; + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_DOUBLE_ESCAPE_START: + scriptdatadoubleescapestartloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + assert index > 0; + if (index < 6) { // SCRIPT_ARR.length + char folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != Tokenizer.SCRIPT_ARR[index]) { + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + continue stateloop; + } + index++; + continue; + } + switch (c) { + case '\r': + emitCarriageReturn(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + case '/': + case '>': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * U+002F SOLIDUS (/) U+003E GREATER-THAN SIGN + * (>) Emit the current input character as a + * character token. If the temporary buffer is + * the string "script", then switch to the + * script data double escaped state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdatadoubleescapestartloop; + default: + /* + * Anything else Reconsume the current input + * character in the script data escaped state. + */ + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_DOUBLE_ESCAPED: + scriptdatadoubleescapedloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Switch to the + * script data double escaped dash state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_DASH, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdatadoubleescapedloop; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Emit a U+003C + * LESS-THAN SIGN character token. Switch to the + * script data double escaped less-than sign + * state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, reconsume, pos); + continue stateloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + continue; + case '\r': + emitCarriageReturn(buf, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Stay in the + * script data double escaped state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: + scriptdatadoubleescapeddashloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Switch to the + * script data double escaped dash dash state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdatadoubleescapeddashloop; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Emit a U+003C + * LESS-THAN SIGN character token. Switch to the + * script data double escaped less-than sign + * state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, reconsume, pos); + continue stateloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + continue stateloop; + case '\r': + emitCarriageReturn(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Switch to the + * script data double escaped state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: + scriptdatadoubleescapeddashdashloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '-': + /* + * U+002D HYPHEN-MINUS (-) Emit a U+002D + * HYPHEN-MINUS character token. Stay in the + * script data double escaped dash dash state. + */ + continue; + case '<': + /* + * U+003C LESS-THAN SIGN (<) Emit a U+003C + * LESS-THAN SIGN character token. Switch to the + * script data double escaped less-than sign + * state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdatadoubleescapeddashdashloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit a U+003E + * GREATER-THAN SIGN character token. Switch to + * the script data state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos); + continue stateloop; + case '\u0000': + emitReplacementCharacter(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + continue stateloop; + case '\r': + emitCarriageReturn(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Emit the current input + * character as a character token. Switch to the + * script data double escaped state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: + scriptdatadoubleescapedlessthanloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '/': + /* + * U+002F SOLIDUS (/) Emit a U+002F SOLIDUS + * character token. Set the temporary buffer to + * the empty string. Switch to the script data + * double escape end state. + */ + index = 0; + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPE_END, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break scriptdatadoubleescapedlessthanloop; + default: + /* + * Anything else Reconsume the current input + * character in the script data double escaped + * state. + */ + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case SCRIPT_DATA_DOUBLE_ESCAPE_END: + scriptdatadoubleescapeendloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + if (index < 6) { // SCRIPT_ARR.length + char folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != Tokenizer.SCRIPT_ARR[index]) { + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + continue stateloop; + } + index++; + continue; + } + switch (c) { + case '\r': + emitCarriageReturn(buf, pos); + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + case '/': + case '>': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * U+002F SOLIDUS (/) U+003E GREATER-THAN SIGN + * (>) Emit the current input character as a + * character token. If the temporary buffer is + * the string "script", then switch to the + * script data escaped state. + */ + state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos); + continue stateloop; + default: + /* + * Reconsume the current input character in the + * script data double escaped state. + */ + reconsume = true; + state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + continue stateloop; + } + } + // no fallthrough, reordering opportunity + case MARKUP_DECLARATION_OCTYPE: + markupdeclarationdoctypeloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + if (index < 6) { // OCTYPE.length + char folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded == Tokenizer.OCTYPE[index]) { + appendStrBuf(c); + } else { + errBogusComment(); + reconsume = true; + state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos); + continue stateloop; + } + index++; + continue; + } else { + reconsume = true; + state = transition(state, Tokenizer.DOCTYPE, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break markupdeclarationdoctypeloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case DOCTYPE: + doctypeloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + initDoctypeFields(); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + state = transition(state, Tokenizer.BEFORE_DOCTYPE_NAME, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the before DOCTYPE name state. + */ + state = transition(state, Tokenizer.BEFORE_DOCTYPE_NAME, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break doctypeloop; + default: + /* + * Anything else Parse error. + */ + errMissingSpaceBeforeDoctypeName(); + /* + * Reconsume the current character in the before + * DOCTYPE name state. + */ + reconsume = true; + state = transition(state, Tokenizer.BEFORE_DOCTYPE_NAME, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break doctypeloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BEFORE_DOCTYPE_NAME: + beforedoctypenameloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the before DOCTYPE name state. + */ + continue; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Parse error. + */ + errNamelessDoctype(); + /* + * Create a new DOCTYPE token. Set its + * force-quirks flag to on. + */ + forceQuirks = true; + /* + * Emit the token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + if (c >= 'A' && c <= 'Z') { + /* + * U+0041 LATIN CAPITAL LETTER A through to + * U+005A LATIN CAPITAL LETTER Z Create a + * new DOCTYPE token. Set the token's name + * to the lowercase version of the input + * character (add 0x0020 to the character's + * code point). + */ + c += 0x20; + } + /* Anything else Create a new DOCTYPE token. */ + /* + * Set the token's name name to the current + * input character. + */ + clearStrBufBeforeUse(); + appendStrBuf(c); + /* + * Switch to the DOCTYPE name state. + */ + state = transition(state, Tokenizer.DOCTYPE_NAME, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break beforedoctypenameloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case DOCTYPE_NAME: + doctypenameloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + strBufToDoctypeName(); + state = transition(state, Tokenizer.AFTER_DOCTYPE_NAME, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the after DOCTYPE name state. + */ + strBufToDoctypeName(); + state = transition(state, Tokenizer.AFTER_DOCTYPE_NAME, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break doctypenameloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * DOCTYPE token. + */ + strBufToDoctypeName(); + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * U+0041 LATIN CAPITAL LETTER A through to + * U+005A LATIN CAPITAL LETTER Z Append the + * lowercase version of the input character (add + * 0x0020 to the character's code point) to the + * current DOCTYPE token's name. + */ + if (c >= 'A' && c <= 'Z') { + c += 0x0020; + } + /* + * Anything else Append the current input + * character to the current DOCTYPE token's + * name. + */ + appendStrBuf(c); + /* + * Stay in the DOCTYPE name state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case AFTER_DOCTYPE_NAME: + afterdoctypenameloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the after DOCTYPE name state. + */ + continue; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case 'p': + case 'P': + index = 0; + state = transition(state, Tokenizer.DOCTYPE_UBLIC, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break afterdoctypenameloop; + case 's': + case 'S': + index = 0; + state = transition(state, Tokenizer.DOCTYPE_YSTEM, reconsume, pos); + continue stateloop; + default: + /* + * Otherwise, this is the parse error. + */ + bogusDoctype(); + + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + // done by bogusDoctype(); + /* + * Switch to the bogus DOCTYPE state. + */ + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case DOCTYPE_UBLIC: + doctypeublicloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * If the six characters starting from the current input + * character are an ASCII case-insensitive match for the + * word "PUBLIC", then consume those characters and + * switch to the before DOCTYPE public identifier state. + */ + if (index < 5) { // UBLIC.length + char folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != Tokenizer.UBLIC[index]) { + bogusDoctype(); + // forceQuirks = true; + reconsume = true; + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + index++; + continue; + } else { + reconsume = true; + state = transition(state, Tokenizer.AFTER_DOCTYPE_PUBLIC_KEYWORD, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break doctypeublicloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case AFTER_DOCTYPE_PUBLIC_KEYWORD: + afterdoctypepublickeywordloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + state = transition(state, Tokenizer.BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the before DOCTYPE public + * identifier state. + */ + state = transition(state, Tokenizer.BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break afterdoctypepublickeywordloop; + case '"': + /* + * U+0022 QUOTATION MARK (") Parse Error. + */ + errNoSpaceBetweenDoctypePublicKeywordAndQuote(); + /* + * Set the DOCTYPE token's public identifier to + * the empty string (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE public identifier + * (double-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos); + continue stateloop; + case '\'': + /* + * U+0027 APOSTROPHE (') Parse Error. + */ + errNoSpaceBetweenDoctypePublicKeywordAndQuote(); + /* + * Set the DOCTYPE token's public identifier to + * the empty string (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE public identifier + * (single-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos); + continue stateloop; + case '>': + /* U+003E GREATER-THAN SIGN (>) Parse error. */ + errExpectedPublicId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + bogusDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + // done by bogusDoctype(); + /* + * Switch to the bogus DOCTYPE state. + */ + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: + beforedoctypepublicidentifierloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the before DOCTYPE public identifier + * state. + */ + continue; + case '"': + /* + * U+0022 QUOTATION MARK (") Set the DOCTYPE + * token's public identifier to the empty string + * (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE public identifier + * (double-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break beforedoctypepublicidentifierloop; + case '\'': + /* + * U+0027 APOSTROPHE (') Set the DOCTYPE token's + * public identifier to the empty string (not + * missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE public identifier + * (single-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos); + continue stateloop; + case '>': + /* U+003E GREATER-THAN SIGN (>) Parse error. */ + errExpectedPublicId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + bogusDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + // done by bogusDoctype(); + /* + * Switch to the bogus DOCTYPE state. + */ + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: + doctypepublicidentifierdoublequotedloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '"': + /* + * U+0022 QUOTATION MARK (") Switch to the after + * DOCTYPE public identifier state. + */ + publicIdentifier = strBufToString(); + state = transition(state, Tokenizer.AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break doctypepublicidentifierdoublequotedloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Parse error. + */ + errGtInPublicId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + publicIdentifier = strBufToString(); + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current DOCTYPE token's + * public identifier. + */ + appendStrBuf(c); + /* + * Stay in the DOCTYPE public identifier + * (double-quoted) state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: + afterdoctypepublicidentifierloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + state = transition(state, Tokenizer.BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the between DOCTYPE public and + * system identifiers state. + */ + state = transition(state, Tokenizer.BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break afterdoctypepublicidentifierloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '"': + /* + * U+0022 QUOTATION MARK (") Parse error. + */ + errNoSpaceBetweenPublicAndSystemIds(); + /* + * Set the DOCTYPE token's system identifier to + * the empty string (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE system identifier + * (double-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos); + continue stateloop; + case '\'': + /* + * U+0027 APOSTROPHE (') Parse error. + */ + errNoSpaceBetweenPublicAndSystemIds(); + /* + * Set the DOCTYPE token's system identifier to + * the empty string (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE system identifier + * (single-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos); + continue stateloop; + default: + bogusDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + // done by bogusDoctype(); + /* + * Switch to the bogus DOCTYPE state. + */ + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: + betweendoctypepublicandsystemidentifiersloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the between DOCTYPE public and system + * identifiers state. + */ + continue; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '"': + /* + * U+0022 QUOTATION MARK (") Set the DOCTYPE + * token's system identifier to the empty string + * (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE system identifier + * (double-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break betweendoctypepublicandsystemidentifiersloop; + case '\'': + /* + * U+0027 APOSTROPHE (') Set the DOCTYPE token's + * system identifier to the empty string (not + * missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE system identifier + * (single-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos); + continue stateloop; + default: + bogusDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + // done by bogusDoctype(); + /* + * Switch to the bogus DOCTYPE state. + */ + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: + doctypesystemidentifierdoublequotedloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '"': + /* + * U+0022 QUOTATION MARK (") Switch to the after + * DOCTYPE system identifier state. + */ + systemIdentifier = strBufToString(); + state = transition(state, Tokenizer.AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break doctypesystemidentifierdoublequotedloop; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Parse error. + */ + errGtInSystemId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + systemIdentifier = strBufToString(); + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current DOCTYPE token's + * system identifier. + */ + appendStrBuf(c); + /* + * Stay in the DOCTYPE system identifier + * (double-quoted) state. + */ + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: + afterdoctypesystemidentifierloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the after DOCTYPE system identifier state. + */ + continue; + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit the current + * DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + /* + * Switch to the bogus DOCTYPE state. (This does + * not set the DOCTYPE token's force-quirks flag + * to on.) + */ + bogusDoctypeWithoutQuirks(); + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break afterdoctypesystemidentifierloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BOGUS_DOCTYPE: + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '>': + /* + * U+003E GREATER-THAN SIGN (>) Emit that + * DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Stay in the bogus DOCTYPE + * state. + */ + continue; + } + } + // no fallthrough, reordering opportunity + case DOCTYPE_YSTEM: + doctypeystemloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Otherwise, if the six characters starting from the + * current input character are an ASCII case-insensitive + * match for the word "SYSTEM", then consume those + * characters and switch to the before DOCTYPE system + * identifier state. + */ + if (index < 5) { // YSTEM.length + char folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != Tokenizer.YSTEM[index]) { + bogusDoctype(); + reconsume = true; + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + index++; + continue stateloop; + } else { + reconsume = true; + state = transition(state, Tokenizer.AFTER_DOCTYPE_SYSTEM_KEYWORD, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break doctypeystemloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case AFTER_DOCTYPE_SYSTEM_KEYWORD: + afterdoctypesystemkeywordloop: for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + } + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + state = transition(state, Tokenizer.BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE + * Switch to the before DOCTYPE public + * identifier state. + */ + state = transition(state, Tokenizer.BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break afterdoctypesystemkeywordloop; + case '"': + /* + * U+0022 QUOTATION MARK (") Parse Error. + */ + errNoSpaceBetweenDoctypeSystemKeywordAndQuote(); + /* + * Set the DOCTYPE token's system identifier to + * the empty string (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE public identifier + * (double-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos); + continue stateloop; + case '\'': + /* + * U+0027 APOSTROPHE (') Parse Error. + */ + errNoSpaceBetweenDoctypeSystemKeywordAndQuote(); + /* + * Set the DOCTYPE token's public identifier to + * the empty string (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE public identifier + * (single-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos); + continue stateloop; + case '>': + /* U+003E GREATER-THAN SIGN (>) Parse error. */ + errExpectedPublicId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + bogusDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + // done by bogusDoctype(); + /* + * Switch to the bogus DOCTYPE state. + */ + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + beforedoctypesystemidentifierloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\r': + silentCarriageReturn(); + break stateloop; + case '\n': + silentLineFeed(); + // CPPONLY: MOZ_FALLTHROUGH; + case ' ': + case '\t': + case '\u000C': + /* + * U+0009 CHARACTER TABULATION U+000A LINE FEED + * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay + * in the before DOCTYPE system identifier + * state. + */ + continue; + case '"': + /* + * U+0022 QUOTATION MARK (") Set the DOCTYPE + * token's system identifier to the empty string + * (not missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE system identifier + * (double-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos); + continue stateloop; + case '\'': + /* + * U+0027 APOSTROPHE (') Set the DOCTYPE token's + * system identifier to the empty string (not + * missing), + */ + clearStrBufBeforeUse(); + /* + * then switch to the DOCTYPE system identifier + * (single-quoted) state. + */ + state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break beforedoctypesystemidentifierloop; + case '>': + /* U+003E GREATER-THAN SIGN (>) Parse error. */ + errExpectedSystemId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + bogusDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + // done by bogusDoctype(); + /* + * Switch to the bogus DOCTYPE state. + */ + state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos); + continue stateloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: + for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\'': + /* + * U+0027 APOSTROPHE (') Switch to the after + * DOCTYPE system identifier state. + */ + systemIdentifier = strBufToString(); + state = transition(state, Tokenizer.AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos); + continue stateloop; + case '>': + errGtInSystemId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + systemIdentifier = strBufToString(); + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current DOCTYPE token's + * system identifier. + */ + appendStrBuf(c); + /* + * Stay in the DOCTYPE system identifier + * (double-quoted) state. + */ + continue; + } + } + // no fallthrough, reordering opportunity + case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: + for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + /* + * Consume the next input character: + */ + switch (c) { + case '\'': + /* + * U+0027 APOSTROPHE (') Switch to the after + * DOCTYPE public identifier state. + */ + publicIdentifier = strBufToString(); + state = transition(state, Tokenizer.AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos); + continue stateloop; + case '>': + errGtInPublicId(); + /* + * Set the DOCTYPE token's force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + publicIdentifier = strBufToString(); + emitDoctypeToken(pos); + /* + * Switch to the data state. + */ + state = transition(state, Tokenizer.DATA, reconsume, pos); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + case '\r': + appendStrBufCarriageReturn(); + break stateloop; + case '\n': + appendStrBufLineFeed(); + continue; + case '\u0000': + c = '\uFFFD'; + // CPPONLY: MOZ_FALLTHROUGH; + default: + /* + * Anything else Append the current input + * character to the current DOCTYPE token's + * public identifier. + */ + appendStrBuf(c); + /* + * Stay in the DOCTYPE public identifier + * (single-quoted) state. + */ + continue; + } + } + // no fallthrough, reordering opportunity + case PROCESSING_INSTRUCTION: + processinginstructionloop: for (;;) { + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '?': + state = transition( + state, + Tokenizer.PROCESSING_INSTRUCTION_QUESTION_MARK, + reconsume, pos); + // `break` optimizes; `continue stateloop;` would be valid + break processinginstructionloop; + default: + continue; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case PROCESSING_INSTRUCTION_QUESTION_MARK: + if (++pos == endPos) { + break stateloop; + } + c = checkChar(buf, pos); + switch (c) { + case '>': + state = transition(state, Tokenizer.DATA, + reconsume, pos); + // Processing instruction syntax goes through these + // states only in Gecko's XML View Source--not in HTML + // parsing in Java or in Gecko. + // Since XML View Source doesn't use the + // suspension-after-current-token facility, its extension + // to processing-instruction states is strictly unnecessary + // at the moment. However, if these states ever were to be + // used together with the suspension-after-current-token + // facility, these states would need to participate, since + // suspension could be requested when only less-than has been + // seen and we don't yet know if we end up here. Handling + // the currently-unnecessary case in order to avoid leaving + // a trap for future modification. + suspendIfRequestedAfterCurrentNonTextToken(); + if (shouldSuspend) { + break stateloop; + } + continue stateloop; + default: + state = transition(state, + Tokenizer.PROCESSING_INSTRUCTION, + reconsume, pos); + continue stateloop; + } + // END HOTSPOT WORKAROUND + } + } + flushChars(buf, pos); + /* + * if (prevCR && pos != endPos) { // why is this needed? pos--; col--; } + */ + // Save locals + stateSave = state; + returnStateSave = returnState; + return pos; + } + + // HOTSPOT WORKAROUND INSERTION POINT + + // [NOCPP[ + + protected int transition(int from, int to, boolean reconsume, int pos) throws SAXException { + return to; + } + + // ]NOCPP] + + private void initDoctypeFields() { + // Discard the characters "DOCTYPE" accumulated as a potential bogus + // comment into strBuf. + clearStrBufAfterUse(); + doctypeName = null; + if (systemIdentifier != null) { + Portability.releaseString(systemIdentifier); + systemIdentifier = null; + } + if (publicIdentifier != null) { + Portability.releaseString(publicIdentifier); + publicIdentifier = null; + } + forceQuirks = false; + } + + @Inline private void adjustDoubleHyphenAndAppendToStrBufCarriageReturn() + throws SAXException { + silentCarriageReturn(); + adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false); + } + + @Inline private void adjustDoubleHyphenAndAppendToStrBufLineFeed() + throws SAXException { + silentLineFeed(); + adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false); + } + + @Inline private void appendStrBufLineFeed() { + silentLineFeed(); + appendStrBuf('\n'); + } + + @Inline private void appendStrBufCarriageReturn() { + silentCarriageReturn(); + appendStrBuf('\n'); + } + + // [NOCPP[ + + @Inline protected void silentCarriageReturn() { + ++line; + lastCR = true; + } + + @Inline protected void silentLineFeed() { + ++line; + } + + // ]NOCPP] + + private void emitCarriageReturn(@NoLength char[] buf, int pos) + throws SAXException { + silentCarriageReturn(); + flushChars(buf, pos); + tokenHandler.characters(Tokenizer.LF, 0, 1); + cstart = Integer.MAX_VALUE; + } + + private void emitReplacementCharacter(@NoLength char[] buf, int pos) + throws SAXException { + flushChars(buf, pos); + tokenHandler.zeroOriginatingReplacementCharacter(); + cstart = pos + 1; + } + + private void maybeEmitReplacementCharacter(@NoLength char[] buf, int pos) + throws SAXException { + flushChars(buf, pos); + tokenHandler.zeroOrReplacementCharacter(); + cstart = pos + 1; + } + + private void emitPlaintextReplacementCharacter(@NoLength char[] buf, int pos) + throws SAXException { + flushChars(buf, pos); + tokenHandler.characters(REPLACEMENT_CHARACTER, 0, 1); + cstart = pos + 1; + } + + private void setAdditionalAndRememberAmpersandLocation(char add) { + additional = add; + // [NOCPP[ + ampersandLocation = new LocatorImpl(this); + // ]NOCPP] + } + + private void bogusDoctype() throws SAXException { + errBogusDoctype(); + forceQuirks = true; + } + + private void bogusDoctypeWithoutQuirks() throws SAXException { + errBogusDoctype(); + forceQuirks = false; + } + + private void handleNcrValue(int returnState) throws SAXException { + /* + * If one or more characters match the range, then take them all and + * interpret the string of characters as a number (either hexadecimal or + * decimal as appropriate). + */ + if (value <= 0xFFFF) { + if (value >= 0x80 && value <= 0x9f) { + /* + * If that number is one of the numbers in the first column of + * the following table, then this is a parse error. + */ + errNcrInC1Range(); + /* + * Find the row with that number in the first column, and return + * a character token for the Unicode character given in the + * second column of that row. + */ + @NoLength char[] val = NamedCharacters.WINDOWS_1252[value - 0x80]; + emitOrAppendOne(val, returnState); + // [NOCPP[ + } else if (value == 0xC + && contentSpacePolicy != XmlViolationPolicy.ALLOW) { + if (contentSpacePolicy == XmlViolationPolicy.ALTER_INFOSET) { + emitOrAppendOne(Tokenizer.SPACE, returnState); + } else if (contentSpacePolicy == XmlViolationPolicy.FATAL) { + fatal("A character reference expanded to a form feed which is not legal XML 1.0 white space."); + } + // ]NOCPP] + } else if (value == 0x0) { + errNcrZero(); + emitOrAppendOne(Tokenizer.REPLACEMENT_CHARACTER, returnState); + } else if ((value & 0xF800) == 0xD800) { + errNcrSurrogate(); + emitOrAppendOne(Tokenizer.REPLACEMENT_CHARACTER, returnState); + } else { + /* + * Otherwise, return a character token for the Unicode character + * whose code point is that number. + */ + char ch = (char) value; + // [NOCPP[ + if (value == 0x0D) { + errNcrCr(); + } else if ((value <= 0x0008) || (value == 0x000B) + || (value >= 0x000E && value <= 0x001F)) { + ch = errNcrControlChar(ch); + } else if (value >= 0xFDD0 && value <= 0xFDEF) { + errNcrUnassigned(); + } else if ((value & 0xFFFE) == 0xFFFE) { + ch = errNcrNonCharacter(ch); + } else if (value >= 0x007F && value <= 0x009F) { + errNcrControlChar(); + } else { + maybeWarnPrivateUse(ch); + } + // ]NOCPP] + bmpChar[0] = ch; + emitOrAppendOne(bmpChar, returnState); + } + } else if (value <= 0x10FFFF) { + // [NOCPP[ + maybeWarnPrivateUseAstral(); + if ((value & 0xFFFE) == 0xFFFE) { + errAstralNonCharacter(value); + } + // ]NOCPP] + astralChar[0] = (char) (Tokenizer.LEAD_OFFSET + (value >> 10)); + astralChar[1] = (char) (0xDC00 + (value & 0x3FF)); + emitOrAppendTwo(astralChar, returnState); + } else { + errNcrOutOfRange(); + emitOrAppendOne(Tokenizer.REPLACEMENT_CHARACTER, returnState); + } + } + + public void eof() throws SAXException { + int state = stateSave; + int returnState = returnStateSave; + + eofloop: for (;;) { + switch (state) { + case SCRIPT_DATA_LESS_THAN_SIGN: + case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: + /* + * Otherwise, emit a U+003C LESS-THAN SIGN character token + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + /* + * and reconsume the current input character in the data + * state. + */ + break eofloop; + case TAG_OPEN: + /* + * The behavior of this state depends on the content model + * flag. + */ + /* + * Anything else Parse error. + */ + errEofAfterLt(); + /* + * Emit a U+003C LESS-THAN SIGN character token + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + /* + * and reconsume the current input character in the data + * state. + */ + break eofloop; + case RAWTEXT_RCDATA_LESS_THAN_SIGN: + /* + * Emit a U+003C LESS-THAN SIGN character token + */ + tokenHandler.characters(Tokenizer.LT_GT, 0, 1); + /* + * and reconsume the current input character in the RCDATA + * state. + */ + break eofloop; + case NON_DATA_END_TAG_NAME: + /* + * Emit a U+003C LESS-THAN SIGN character token, a U+002F + * SOLIDUS character token, + */ + tokenHandler.characters(Tokenizer.LT_SOLIDUS, 0, 2); + /* + * a character token for each of the characters in the + * temporary buffer (in the order they were added to the + * buffer), + */ + emitStrBuf(); + /* + * and reconsume the current input character in the RCDATA + * state. + */ + break eofloop; + case CLOSE_TAG_OPEN: + /* EOF Parse error. */ + errEofAfterLt(); + /* + * Emit a U+003C LESS-THAN SIGN character token and a U+002F + * SOLIDUS character token. + */ + tokenHandler.characters(Tokenizer.LT_SOLIDUS, 0, 2); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case TAG_NAME: + /* + * EOF Parse error. + */ + errEofInTagName(); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case BEFORE_ATTRIBUTE_NAME: + case AFTER_ATTRIBUTE_VALUE_QUOTED: + case SELF_CLOSING_START_TAG: + /* EOF Parse error. */ + errEofWithoutGt(); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case ATTRIBUTE_NAME: + /* + * EOF Parse error. + */ + errEofInAttributeName(); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case AFTER_ATTRIBUTE_NAME: + case BEFORE_ATTRIBUTE_VALUE: + /* EOF Parse error. */ + errEofWithoutGt(); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case ATTRIBUTE_VALUE_DOUBLE_QUOTED: + case ATTRIBUTE_VALUE_SINGLE_QUOTED: + case ATTRIBUTE_VALUE_UNQUOTED: + /* EOF Parse error. */ + errEofInAttributeValue(); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case BOGUS_COMMENT: + emitComment(0, 0); + break eofloop; + case BOGUS_COMMENT_HYPHEN: + // [NOCPP[ + maybeAppendSpaceToBogusComment(); + // ]NOCPP] + emitComment(0, 0); + break eofloop; + case MARKUP_DECLARATION_OPEN: + errBogusComment(); + emitComment(0, 0); + break eofloop; + case MARKUP_DECLARATION_HYPHEN: + errBogusComment(); + emitComment(0, 0); + break eofloop; + case MARKUP_DECLARATION_OCTYPE: + if (index < 6) { + errBogusComment(); + emitComment(0, 0); + } else { + /* EOF Parse error. */ + errEofInDoctype(); + /* + * Create a new DOCTYPE token. Set its force-quirks flag + * to on. + */ + doctypeName = null; + if (systemIdentifier != null) { + Portability.releaseString(systemIdentifier); + systemIdentifier = null; + } + if (publicIdentifier != null) { + Portability.releaseString(publicIdentifier); + publicIdentifier = null; + } + forceQuirks = true; + /* + * Emit the token. + */ + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + } + break eofloop; + case COMMENT_START: + case COMMENT: + case COMMENT_LESSTHAN: + case COMMENT_LESSTHAN_BANG: + /* + * EOF Parse error. + */ + errEofInComment(); + /* Emit the comment token. */ + emitComment(0, 0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case COMMENT_END: + case COMMENT_LESSTHAN_BANG_DASH_DASH: + errEofInComment(); + /* Emit the comment token. */ + emitComment(2, 0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case COMMENT_END_DASH: + case COMMENT_START_DASH: + case COMMENT_LESSTHAN_BANG_DASH: + errEofInComment(); + /* Emit the comment token. */ + emitComment(1, 0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case COMMENT_END_BANG: + errEofInComment(); + /* Emit the comment token. */ + emitComment(3, 0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case DOCTYPE: + case BEFORE_DOCTYPE_NAME: + errEofInDoctype(); + /* + * Create a new DOCTYPE token. Set its force-quirks flag to + * on. + */ + forceQuirks = true; + /* + * Emit the token. + */ + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case DOCTYPE_NAME: + errEofInDoctype(); + strBufToDoctypeName(); + /* + * Set the DOCTYPE token's force-quirks flag to on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case DOCTYPE_UBLIC: + case DOCTYPE_YSTEM: + case AFTER_DOCTYPE_NAME: + case AFTER_DOCTYPE_PUBLIC_KEYWORD: + case AFTER_DOCTYPE_SYSTEM_KEYWORD: + case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: + errEofInDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: + /* EOF Parse error. */ + errEofInPublicId(); + /* + * Set the DOCTYPE token's force-quirks flag to on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + publicIdentifier = strBufToString(); + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: + case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: + errEofInDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: + /* EOF Parse error. */ + errEofInSystemId(); + /* + * Set the DOCTYPE token's force-quirks flag to on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + systemIdentifier = strBufToString(); + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: + errEofInDoctype(); + /* + * Set the DOCTYPE token's force-quirks flag to on. + */ + forceQuirks = true; + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case BOGUS_DOCTYPE: + /* + * Emit that DOCTYPE token. + */ + emitDoctypeToken(0); + /* + * Reconsume the EOF character in the data state. + */ + break eofloop; + case CONSUME_CHARACTER_REFERENCE: + /* + * Unlike the definition is the spec, this state does not + * return a value and never requires the caller to + * backtrack. This state takes care of emitting characters + * or appending to the current attribute value. It also + * takes care of that in the case when consuming the entity + * fails. + */ + /* + * This section defines how to consume an entity. This + * definition is used when parsing entities in text and in + * attributes. + * + * The behavior depends on the identity of the next + * character (the one immediately after the U+0026 AMPERSAND + * character): + */ + + emitOrAppendCharRefBuf(returnState); + state = returnState; + continue; + case CHARACTER_REFERENCE_HILO_LOOKUP: + emitOrAppendCharRefBuf(returnState); + state = returnState; + continue; + case CHARACTER_REFERENCE_TAIL: + outer: for (;;) { + char c = '\u0000'; + entCol++; + /* + * Consume the maximum number of characters possible, + * with the consumed characters matching one of the + * identifiers in the first column of the named + * character references table (in a case-sensitive + * manner). + */ + hiloop: for (;;) { + if (hi == -1) { + break hiloop; + } + if (entCol == NamedCharacters.NAMES[hi].length()) { + break hiloop; + } + if (entCol > NamedCharacters.NAMES[hi].length()) { + break outer; + } else if (c < NamedCharacters.NAMES[hi].charAt(entCol)) { + hi--; + } else { + break hiloop; + } + } + + loloop: for (;;) { + if (hi < lo) { + break outer; + } + if (entCol == NamedCharacters.NAMES[lo].length()) { + candidate = lo; + charRefBufMark = charRefBufLen; + lo++; + } else if (entCol > NamedCharacters.NAMES[lo].length()) { + break outer; + } else if (c > NamedCharacters.NAMES[lo].charAt(entCol)) { + lo++; + } else { + break loloop; + } + } + if (hi < lo) { + break outer; + } + continue; + } + + if (candidate == -1) { + emitOrAppendCharRefBuf(returnState); + state = returnState; + continue eofloop; + } else { + @Const @CharacterName String candidateName = NamedCharacters.NAMES[candidate]; + if (candidateName.length() == 0 + || candidateName.charAt(candidateName.length() - 1) != ';') { + /* + * If the last character matched is not a U+003B + * SEMICOLON (;), there is a parse error. + */ + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + /* + * If the entity is being consumed as part of an + * attribute, and the last character matched is + * not a U+003B SEMICOLON (;), + */ + char ch; + if (charRefBufMark == charRefBufLen) { + ch = '\u0000'; + } else { + ch = charRefBuf[charRefBufMark]; + } + if ((ch >= '0' && ch <= '9') + || (ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z')) { + /* + * and the next character is in the range + * U+0030 DIGIT ZERO to U+0039 DIGIT NINE, + * U+0041 LATIN CAPITAL LETTER A to U+005A + * LATIN CAPITAL LETTER Z, or U+0061 LATIN + * SMALL LETTER A to U+007A LATIN SMALL + * LETTER Z, then, for historical reasons, + * all the characters that were matched + * after the U+0026 AMPERSAND (&) must be + * unconsumed, and nothing is returned. + */ + appendCharRefBufToStrBuf(); + state = returnState; + continue eofloop; + } + } + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + errUnescapedAmpersandInterpretedAsCharacterReference(); + } else { + errNotSemicolonTerminated(); + } + } + + /* + * Otherwise, return a character token for the character + * corresponding to the entity name (as given by the + * second column of the named character references + * table). + */ + @Const @NoLength char[] val = NamedCharacters.VALUES[candidate]; + if ( + // [NOCPP[ + val.length == 1 + // ]NOCPP] + // CPPONLY: val[1] == 0 + ) { + emitOrAppendOne(val, returnState); + } else { + emitOrAppendTwo(val, returnState); + } + // this is so complicated! + if (charRefBufMark < charRefBufLen) { + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + appendStrBuf(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } else { + tokenHandler.characters(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } + } + charRefBufLen = 0; + state = returnState; + continue eofloop; + /* + * If the markup contains I'm ¬it; I tell you, the + * entity is parsed as "not", as in, I'm ¬it; I tell + * you. But if the markup was I'm ∉ I tell you, + * the entity would be parsed as "notin;", resulting in + * I'm ∉ I tell you. + */ + } + case CONSUME_NCR: + case DECIMAL_NRC_LOOP: + case HEX_NCR_LOOP: + /* + * If no characters match the range, then don't consume any + * characters (and unconsume the U+0023 NUMBER SIGN + * character and, if appropriate, the X character). This is + * a parse error; nothing is returned. + * + * Otherwise, if the next character is a U+003B SEMICOLON, + * consume that too. If it isn't, there is a parse error. + */ + if (!seenDigits) { + errNoDigitsInNCR(); + emitOrAppendCharRefBuf(returnState); + state = returnState; + continue; + } else { + errCharRefLacksSemicolon(); + } + // WARNING previous state sets reconsume + handleNcrValue(returnState); + state = returnState; + continue; + case CDATA_RSQB: + tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 1); + break eofloop; + case CDATA_RSQB_RSQB: + tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 2); + break eofloop; + case DATA: + default: + break eofloop; + } + } + // case DATA: + /* + * EOF Emit an end-of-file token. + */ + tokenHandler.eof(); + return; + } + + /** + * Emits a doctype token. + * + * NOTE: The method may set <code>shouldSuspend</code>, so the caller + * must have this pattern after the state's <code>transition</code> call: + * <pre> + * if (shouldSuspend) { + * break stateloop; + * } + * continue stateloop; + * </pre> + * + * @param pos + * @throws SAXException + */ + private void emitDoctypeToken(int pos) throws SAXException { + // CPPONLY: RememberGt(pos); + cstart = pos + 1; + tokenHandler.doctype(doctypeName, publicIdentifier, systemIdentifier, + forceQuirks); + // It is OK and sufficient to release these here, since + // there's no way out of the doctype states than through paths + // that call this method. + doctypeName = null; + Portability.releaseString(publicIdentifier); + publicIdentifier = null; + Portability.releaseString(systemIdentifier); + systemIdentifier = null; + suspendIfRequestedAfterCurrentNonTextToken(); + } + + /** + * If a previous call to <code>suspendAfterCurrentTokenIfNotInText()</code> + * happened in a non-text context, this method turns that deferred suspension + * request into an immediately-pending suspension request. + */ + private void suspendIfRequestedAfterCurrentNonTextToken() { + if (suspendAfterCurrentNonTextToken) { + suspendAfterCurrentNonTextToken = false; + shouldSuspend = true; + } + } + + // Making this private until the full Java implementation is done. + /** + * Request suspension after the current token if the tokenizer is currently + * in a non-text state (i.e. it's known that the next token will be a + * non-text token). + * + * Must not be called when <code>tokenizeBuffer()</code> is on the call + * stack. + */ + @SuppressWarnings("unused") private void suspendAfterCurrentTokenIfNotInText() { + switch (stateSave) { + case DATA: + case RCDATA: + case SCRIPT_DATA: + case RAWTEXT: + case SCRIPT_DATA_ESCAPED: + case PLAINTEXT: + case NON_DATA_END_TAG_NAME: // We haven't yet committed to the next + // token being a non-text token, though + // it could be. + case SCRIPT_DATA_LESS_THAN_SIGN: + case SCRIPT_DATA_ESCAPE_START: + case SCRIPT_DATA_ESCAPE_START_DASH: + case SCRIPT_DATA_ESCAPED_DASH: + case SCRIPT_DATA_ESCAPED_DASH_DASH: + case RAWTEXT_RCDATA_LESS_THAN_SIGN: + case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: + case SCRIPT_DATA_DOUBLE_ESCAPE_START: + case SCRIPT_DATA_DOUBLE_ESCAPED: + case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPE_END: + return; + case TAG_NAME: + case BEFORE_ATTRIBUTE_NAME: + case ATTRIBUTE_NAME: + case AFTER_ATTRIBUTE_NAME: + case BEFORE_ATTRIBUTE_VALUE: + case AFTER_ATTRIBUTE_VALUE_QUOTED: + case BOGUS_COMMENT: + case MARKUP_DECLARATION_OPEN: + case DOCTYPE: + case BEFORE_DOCTYPE_NAME: + case DOCTYPE_NAME: + case AFTER_DOCTYPE_NAME: + case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: + case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: + case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: + case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: + case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: + case BOGUS_DOCTYPE: + case COMMENT_START: + case COMMENT_START_DASH: + case COMMENT: + case COMMENT_END_DASH: + case COMMENT_END: + case COMMENT_END_BANG: + case TAG_OPEN: + case CLOSE_TAG_OPEN: + case MARKUP_DECLARATION_HYPHEN: + case MARKUP_DECLARATION_OCTYPE: + case DOCTYPE_UBLIC: + case DOCTYPE_YSTEM: + case AFTER_DOCTYPE_PUBLIC_KEYWORD: + case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: + case AFTER_DOCTYPE_SYSTEM_KEYWORD: + case SELF_CLOSING_START_TAG: + case ATTRIBUTE_VALUE_DOUBLE_QUOTED: + case ATTRIBUTE_VALUE_SINGLE_QUOTED: + case ATTRIBUTE_VALUE_UNQUOTED: + case BOGUS_COMMENT_HYPHEN: + case COMMENT_LESSTHAN: + case COMMENT_LESSTHAN_BANG: + case COMMENT_LESSTHAN_BANG_DASH: + case COMMENT_LESSTHAN_BANG_DASH_DASH: + case CDATA_START: + case CDATA_SECTION: + case CDATA_RSQB: + case CDATA_RSQB_RSQB: + case PROCESSING_INSTRUCTION: + case PROCESSING_INSTRUCTION_QUESTION_MARK: + break; + case CONSUME_CHARACTER_REFERENCE: + case CONSUME_NCR: + case CHARACTER_REFERENCE_TAIL: + case HEX_NCR_LOOP: + case DECIMAL_NRC_LOOP: + case HANDLE_NCR_VALUE: + case HANDLE_NCR_VALUE_RECONSUME: + case CHARACTER_REFERENCE_HILO_LOOKUP: + if (returnStateSave == DATA || returnStateSave == RCDATA) { + return; + } + break; + default: + assert false : "Incomplete switch"; + return; + } + suspendAfterCurrentNonTextToken = true; + } + + // Making this private until the full Java implementation is done. + /** + * Queries if we are about to suspend after the current non-text token due to a request + * from <code>suspendAfterCurrentTokenIfNotInText()</code>. + * @return <code>true</code> iff <code>suspendAfterCurrentTokenIfNotInText()</code> was + * called in a non-text position and the then-current token has not been emitted yet. + */ + @SuppressWarnings("unused") private boolean suspensionAfterCurrentNonTextTokenPending() { + return suspendAfterCurrentNonTextToken; + } + + // [NOCPP[ + + @Inline protected char checkChar(@NoLength char[] buf, int pos) + throws SAXException { + return buf[pos]; + } + + // ]NOCPP] + + public boolean internalEncodingDeclaration(String internalCharset) + throws SAXException { + if (encodingDeclarationHandler != null) { + return encodingDeclarationHandler.internalEncodingDeclaration(internalCharset); + } + return false; + } + + /** + * @param val + * @throws SAXException + */ + private void emitOrAppendTwo(@Const @NoLength char[] val, int returnState) + throws SAXException { + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + appendStrBuf(val[0]); + appendStrBuf(val[1]); + } else { + tokenHandler.characters(val, 0, 2); + } + } + + private void emitOrAppendOne(@Const @NoLength char[] val, int returnState) + throws SAXException { + if ((returnState & DATA_AND_RCDATA_MASK) != 0) { + appendStrBuf(val[0]); + } else { + tokenHandler.characters(val, 0, 1); + } + } + + public void end() throws SAXException { + strBuf = null; + doctypeName = null; + if (systemIdentifier != null) { + Portability.releaseString(systemIdentifier); + systemIdentifier = null; + } + if (publicIdentifier != null) { + Portability.releaseString(publicIdentifier); + publicIdentifier = null; + } + tagName = null; + nonInternedTagName.setNameForNonInterned(null + // CPPONLY: , false + ); + attributeName = null; + // CPPONLY: nonInternedAttributeName.setNameForNonInterned(null); + tokenHandler.endTokenization(); + if (attributes != null) { + // [NOCPP[ + attributes = null; + // ]NOCPP] + // CPPONLY: attributes.clear(mappingLangToXmlLang); + } + } + + public void requestSuspension() { + shouldSuspend = true; + } + + // [NOCPP[ + + public void becomeConfident() { + confident = true; + } + + /** + * Returns the nextCharOnNewLine. + * + * @return the nextCharOnNewLine + */ + public boolean isNextCharOnNewLine() { + return false; + } + + public boolean isPrevCR() { + return lastCR; + } + + /** + * Returns the line. + * + * @return the line + */ + public int getLine() { + return -1; + } + + /** + * Returns the col. + * + * @return the col + */ + public int getCol() { + return -1; + } + + // ]NOCPP] + + public boolean isInDataState() { + return (stateSave == DATA); + } + + public void resetToDataState() { + clearStrBufAfterUse(); + charRefBufLen = 0; + stateSave = Tokenizer.DATA; + // line = 1; XXX line numbers + lastCR = false; + index = 0; + forceQuirks = false; + additional = '\u0000'; + entCol = -1; + firstCharKey = -1; + lo = 0; + hi = 0; // will always be overwritten before use anyway + candidate = -1; + charRefBufMark = 0; + value = 0; + seenDigits = false; + suspendAfterCurrentNonTextToken = false; + endTag = false; + shouldSuspend = false; + initDoctypeFields(); + containsHyphen = false; + tagName = null; + attributeName = null; + if (newAttributesEachTime) { + if (attributes != null) { + Portability.delete(attributes); + attributes = null; + } + } + } + + public void loadState(Tokenizer other) throws SAXException { + strBufLen = other.strBufLen; + if (strBufLen > strBuf.length) { + strBuf = new char[strBufLen]; + } + System.arraycopy(other.strBuf, 0, strBuf, 0, strBufLen); + + charRefBufLen = other.charRefBufLen; + System.arraycopy(other.charRefBuf, 0, charRefBuf, 0, charRefBufLen); + + stateSave = other.stateSave; + returnStateSave = other.returnStateSave; + endTagExpectation = other.endTagExpectation; + endTagExpectationAsArray = other.endTagExpectationAsArray; + // line = 1; XXX line numbers + lastCR = other.lastCR; + index = other.index; + forceQuirks = other.forceQuirks; + additional = other.additional; + entCol = other.entCol; + firstCharKey = other.firstCharKey; + lo = other.lo; + hi = other.hi; + candidate = other.candidate; + charRefBufMark = other.charRefBufMark; + value = other.value; + seenDigits = other.seenDigits; + endTag = other.endTag; + shouldSuspend = false; + suspendAfterCurrentNonTextToken = false; + doctypeName = other.doctypeName; + + Portability.releaseString(systemIdentifier); + if (other.systemIdentifier == null) { + systemIdentifier = null; + } else { + systemIdentifier = Portability.newStringFromString(other.systemIdentifier); + } + + Portability.releaseString(publicIdentifier); + if (other.publicIdentifier == null) { + publicIdentifier = null; + } else { + publicIdentifier = Portability.newStringFromString(other.publicIdentifier); + } + + containsHyphen = other.containsHyphen; + if (other.tagName == null) { + tagName = null; + } else if (other.tagName.isInterned()) { + tagName = other.tagName; + } else { + // 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(other.tagName.getName() + // CPPONLY: , other.tagName.isCustom() + ); + tagName = nonInternedTagName; + } + + // [NOCPP[ + attributeName = other.attributeName; + // ]NOCPP] + // CPPONLY: if (other.attributeName == null) { + // CPPONLY: attributeName = null; + // CPPONLY: } else if (other.attributeName.isInterned()) { + // CPPONLY: attributeName = other.attributeName; + // CPPONLY: } else { + // CPPONLY: // In the C++ case, the atoms in the other tokenizer are from a + // CPPONLY: // different tokenizer-scoped atom table. Therefore, we have to + // CPPONLY: // obtain the correspoding atom from our own atom table. + // CPPONLY: nonInternedAttributeName.setNameForNonInterned(other.attributeName.getLocal(AttributeName.HTML)); + // CPPONLY: attributeName = nonInternedAttributeName; + // CPPONLY: } + + Portability.delete(attributes); + if (other.attributes == null) { + attributes = null; + } else { + attributes = other.attributes.cloneAttributes(); + } + } + + public void initializeWithoutStarting() throws SAXException { + confident = false; + strBuf = null; + line = 1; + // CPPONLY: attributeLine = 1; + // [NOCPP[ + metaBoundaryPassed = false; + wantsComments = tokenHandler.wantsComments(); + if (!newAttributesEachTime) { + attributes = new HtmlAttributes(mappingLangToXmlLang); + } + // ]NOCPP] + resetToDataState(); + } + + protected void errGarbageAfterLtSlash() throws SAXException { + } + + protected void errLtSlashGt() throws SAXException { + } + + protected void errWarnLtSlashInRcdata() throws SAXException { + } + + protected void errHtml4LtSlashInRcdata(char folded) throws SAXException { + } + + protected void errCharRefLacksSemicolon() throws SAXException { + } + + protected void errNoDigitsInNCR() throws SAXException { + } + + protected void errGtInSystemId() throws SAXException { + } + + protected void errGtInPublicId() throws SAXException { + } + + protected void errNamelessDoctype() throws SAXException { + } + + protected void errNestedComment() throws SAXException { + } + + protected void errPrematureEndOfComment() throws SAXException { + } + + protected void errBogusComment() throws SAXException { + } + + protected void errUnquotedAttributeValOrNull(char c) throws SAXException { + } + + protected void errSlashNotFollowedByGt() throws SAXException { + } + + protected void errNoSpaceBetweenAttributes() throws SAXException { + } + + protected void errLtOrEqualsOrGraveInUnquotedAttributeOrNull(char c) + throws SAXException { + } + + protected void errAttributeValueMissing() throws SAXException { + } + + protected void errBadCharBeforeAttributeNameOrNull(char c) + throws SAXException { + } + + protected void errEqualsSignBeforeAttributeName() throws SAXException { + } + + protected void errBadCharAfterLt(char c) throws SAXException { + } + + protected void errLtGt() throws SAXException { + } + + protected void errProcessingInstruction() throws SAXException { + } + + protected void errUnescapedAmpersandInterpretedAsCharacterReference() + throws SAXException { + } + + protected void errNotSemicolonTerminated() throws SAXException { + } + + protected void errNoNamedCharacterMatch() throws SAXException { + } + + protected void errQuoteBeforeAttributeName(char c) throws SAXException { + } + + protected void errQuoteOrLtInAttributeNameOrNull(char c) + throws SAXException { + } + + protected void errExpectedPublicId() throws SAXException { + } + + protected void errBogusDoctype() throws SAXException { + } + + protected void maybeWarnPrivateUseAstral() throws SAXException { + } + + protected void maybeWarnPrivateUse(char ch) throws SAXException { + } + + protected void maybeErrAttributesOnEndTag(HtmlAttributes attrs) + throws SAXException { + } + + protected void maybeErrSlashInEndTag(boolean selfClosing) + throws SAXException { + } + + protected char errNcrNonCharacter(char ch) throws SAXException { + return ch; + } + + protected void errAstralNonCharacter(int ch) throws SAXException { + } + + protected void errNcrSurrogate() throws SAXException { + } + + protected char errNcrControlChar(char ch) throws SAXException { + return ch; + } + + protected void errNcrCr() throws SAXException { + } + + protected void errNcrInC1Range() throws SAXException { + } + + protected void errEofInPublicId() throws SAXException { + } + + protected void errEofInComment() throws SAXException { + } + + protected void errEofInDoctype() throws SAXException { + } + + protected void errEofInAttributeValue() throws SAXException { + } + + protected void errEofInAttributeName() throws SAXException { + } + + protected void errEofWithoutGt() throws SAXException { + } + + protected void errEofInTagName() throws SAXException { + } + + protected void errEofInEndTag() throws SAXException { + } + + protected void errEofAfterLt() throws SAXException { + } + + protected void errNcrOutOfRange() throws SAXException { + } + + protected void errNcrUnassigned() throws SAXException { + } + + protected void errDuplicateAttribute() throws SAXException { + } + + protected void errEofInSystemId() throws SAXException { + } + + protected void errExpectedSystemId() throws SAXException { + } + + protected void errMissingSpaceBeforeDoctypeName() throws SAXException { + } + + protected void errNcrControlChar() throws SAXException { + } + + protected void errNcrZero() throws SAXException { + } + + protected void errNoSpaceBetweenDoctypeSystemKeywordAndQuote() + throws SAXException { + } + + protected void errNoSpaceBetweenPublicAndSystemIds() throws SAXException { + } + + protected void errNoSpaceBetweenDoctypePublicKeywordAndQuote() + throws SAXException { + } + + protected void noteAttributeWithoutValue() throws SAXException { + } + + protected void noteUnquotedAttributeValue() throws SAXException { + } + + /** + * Sets the encodingDeclarationHandler. + * + * @param encodingDeclarationHandler + * the encodingDeclarationHandler to set + */ + public void setEncodingDeclarationHandler( + EncodingDeclarationHandler encodingDeclarationHandler) { + this.encodingDeclarationHandler = encodingDeclarationHandler; + } + + void destructor() { + Portability.delete(nonInternedTagName); + nonInternedTagName = null; + // CPPONLY: Portability.delete(nonInternedAttributeName); + // CPPONLY: nonInternedAttributeName = null; + // The translator will write refcount tracing stuff here + Portability.delete(attributes); + attributes = null; + } + + // [NOCPP[ + + /** + * Sets an offset to be added to the position reported to + * <code>TransitionHandler</code>. + * + * @param offset the offset + */ + public void setTransitionBaseOffset(int offset) { + + } + + // ]NOCPP] + +} diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java new file mode 100644 index 0000000000..1f437bf744 --- /dev/null +++ b/parser/html/javasrc/TreeBuilder.java @@ -0,0 +1,6550 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2007-2017 Mozilla Foundation + * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla + * Foundation, and Opera Software ASA. + * + * 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. + */ + +/* + * The comments following this one that use the same comment syntax as this + * comment are quotes from the WHATWG HTML 5 spec as of 27 June 2007 + * amended as of June 28 2007. + * That document came with this statement: + * "© Copyright 2004-2007 Apple Computer, Inc., Mozilla Foundation, and + * Opera Software ASA. You are granted a license to use, reproduce and + * create derivative works of this document." + */ + +package nu.validator.htmlparser.impl; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.xml.sax.ErrorHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import nu.validator.htmlparser.annotation.Auto; +import nu.validator.htmlparser.annotation.Const; +import nu.validator.htmlparser.annotation.IdType; +import nu.validator.htmlparser.annotation.Inline; +import nu.validator.htmlparser.annotation.Literal; +import nu.validator.htmlparser.annotation.Local; +import nu.validator.htmlparser.annotation.NoLength; +import nu.validator.htmlparser.annotation.NsUri; +import nu.validator.htmlparser.common.DocumentMode; +import nu.validator.htmlparser.common.DocumentModeHandler; +import nu.validator.htmlparser.common.Interner; +import nu.validator.htmlparser.common.TokenHandler; +import nu.validator.htmlparser.common.XmlViolationPolicy; + +public abstract class TreeBuilder<T> implements TokenHandler, + TreeBuilderState<T> { + + /** + * Array version of U+FFFD. + */ + private static final @NoLength char[] REPLACEMENT_CHARACTER = { '\uFFFD' }; + + // Start dispatch groups + + final static int OTHER = 0; + + final static int A = 1; + + final static int BASE = 2; + + final static int BODY = 3; + + final static int BR = 4; + + final static int BUTTON = 5; + + final static int CAPTION = 6; + + final static int COL = 7; + + final static int COLGROUP = 8; + + final static int FORM = 9; + + final static int FRAME = 10; + + final static int FRAMESET = 11; + + final static int IMAGE = 12; + + final static int INPUT = 13; + + final static int RT_OR_RP = 14; + + final static int LI = 15; + + final static int LINK_OR_BASEFONT_OR_BGSOUND = 16; + + final static int MATH = 17; + + final static int META = 18; + + final static int SVG = 19; + + final static int HEAD = 20; + + final static int HR = 22; + + final static int HTML = 23; + + final static int NOBR = 24; + + final static int NOFRAMES = 25; + + final static int NOSCRIPT = 26; + + final static int OPTGROUP = 27; + + final static int OPTION = 28; + + final static int P = 29; + + final static int PLAINTEXT = 30; + + final static int SCRIPT = 31; + + final static int SELECT = 32; + + final static int STYLE = 33; + + final static int TABLE = 34; + + final static int TEXTAREA = 35; + + final static int TITLE = 36; + + final static int TR = 37; + + final static int XMP = 38; + + final static int TBODY_OR_THEAD_OR_TFOOT = 39; + + final static int TD_OR_TH = 40; + + final static int DD_OR_DT = 41; + + final static int H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 = 42; + + final static int MARQUEE_OR_APPLET = 43; + + final static int PRE_OR_LISTING = 44; + + final static int B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U = 45; + + final static int UL_OR_OL_OR_DL = 46; + + final static int IFRAME = 47; + + final static int EMBED = 48; + + final static int AREA_OR_WBR = 49; + + final static int DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU = 50; + + final static int ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY = 51; + + final static int RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR = 52; + + final static int RB_OR_RTC = 53; + + final static int PARAM_OR_SOURCE_OR_TRACK = 55; + + final static int MGLYPH_OR_MALIGNMARK = 56; + + final static int MI_MO_MN_MS_MTEXT = 57; + + final static int ANNOTATION_XML = 58; + + final static int FOREIGNOBJECT_OR_DESC = 59; + + final static int NOEMBED = 60; + + final static int FIELDSET = 61; + + final static int OUTPUT = 62; + + final static int OBJECT = 63; + + final static int FONT = 64; + + final static int KEYGEN = 65; + + final static int TEMPLATE = 66; + + final static int IMG = 67; + + // start insertion modes + + private static final int IN_ROW = 0; + + private static final int IN_TABLE_BODY = 1; + + private static final int IN_TABLE = 2; + + private static final int IN_CAPTION = 3; + + private static final int IN_CELL = 4; + + private static final int FRAMESET_OK = 5; + + private static final int IN_BODY = 6; + + private static final int IN_HEAD = 7; + + private static final int IN_HEAD_NOSCRIPT = 8; + + // no fall-through + + private static final int IN_COLUMN_GROUP = 9; + + // no fall-through + + private static final int IN_SELECT_IN_TABLE = 10; + + private static final int IN_SELECT = 11; + + // no fall-through + + private static final int AFTER_BODY = 12; + + // no fall-through + + private static final int IN_FRAMESET = 13; + + private static final int AFTER_FRAMESET = 14; + + // no fall-through + + private static final int INITIAL = 15; + + // could add fall-through + + private static final int BEFORE_HTML = 16; + + // could add fall-through + + private static final int BEFORE_HEAD = 17; + + // no fall-through + + private static final int AFTER_HEAD = 18; + + // no fall-through + + private static final int AFTER_AFTER_BODY = 19; + + // no fall-through + + private static final int AFTER_AFTER_FRAMESET = 20; + + // no fall-through + + private static final int TEXT = 21; + + private static final int IN_TEMPLATE = 22; + + // start charset states + + private static final int CHARSET_INITIAL = 0; + + private static final int CHARSET_C = 1; + + private static final int CHARSET_H = 2; + + private static final int CHARSET_A = 3; + + private static final int CHARSET_R = 4; + + private static final int CHARSET_S = 5; + + private static final int CHARSET_E = 6; + + private static final int CHARSET_T = 7; + + private static final int CHARSET_EQUALS = 8; + + private static final int CHARSET_SINGLE_QUOTED = 9; + + private static final int CHARSET_DOUBLE_QUOTED = 10; + + private static final int CHARSET_UNQUOTED = 11; + + // end pseudo enums + + @Literal private final static String[] QUIRKY_PUBLIC_IDS = { + "+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//" }; + + private static final int NOT_FOUND_ON_STACK = Integer.MAX_VALUE; + + // [NOCPP[ + + private static final @Local String HTML_LOCAL = "html"; + + // ]NOCPP] + + private int mode = INITIAL; + + private int originalMode = INITIAL; + + /** + * Used only when moving back to IN_BODY. + */ + private boolean framesetOk = true; + + protected Tokenizer tokenizer; + + // [NOCPP[ + + protected ErrorHandler errorHandler; + + private DocumentModeHandler documentModeHandler; + + // ]NOCPP] + + private boolean scriptingEnabled = false; + + private boolean needToDropLF; + + // [NOCPP[ + + private boolean wantingComments; + + // ]NOCPP] + + private boolean fragment; + + private @Local String contextName; + + private @NsUri String contextNamespace; + + private T contextNode; + + /** + * Stack of template insertion modes + */ + private @Auto int[] templateModeStack; + + /** + * Current template mode stack pointer. + */ + private int templateModePtr = -1; + + private @Auto StackNode<T>[] stackNodes; + + /** + * Index of the earliest possible unused or empty element in stackNodes. + */ + private int stackNodesIdx = -1; + + private int numStackNodes = 0; + + private @Auto StackNode<T>[] stack; + + private int currentPtr = -1; + + private @Auto StackNode<T>[] listOfActiveFormattingElements; + + private int listPtr = -1; + + private T formPointer; + + private T headPointer; + + protected @Auto char[] charBuffer; + + protected int charBufferLen = 0; + + private boolean quirks = false; + + private boolean forceNoQuirks = false; + + // [NOCPP[ + + private boolean reportingDoctype = true; + + private XmlViolationPolicy namePolicy = XmlViolationPolicy.ALTER_INFOSET; + + private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>(); + + // ]NOCPP] + + protected TreeBuilder() { + fragment = false; + } + + /** + * Reports an condition that would make the infoset incompatible with XML + * 1.0 as fatal. + * + * @throws SAXException + * @throws SAXParseException + */ + 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 { + SAXParseException spe = new SAXParseException(e.getMessage(), + tokenizer, e); + if (errorHandler != null) { + errorHandler.fatalError(spe); + } + throw spe; + } + + final void fatal(String s) throws SAXException { + SAXParseException spe = new SAXParseException(s, tokenizer); + if (errorHandler != null) { + errorHandler.fatalError(spe); + } + throw spe; + } + + /** + * Reports a Parse Error. + * + * @param message + * the message + * @throws SAXException + */ + final void err(String message) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck(message); + } + + /** + * Reports a Parse Error without checking if an error handler is present. + * + * @param message + * the message + * @throws SAXException + */ + final void errNoCheck(String message) throws SAXException { + SAXParseException spe = new SAXParseException(message, tokenizer); + errorHandler.error(spe); + } + + private void errListUnclosedStartTags(int eltPos) throws SAXException { + if (currentPtr != -1) { + for (int i = currentPtr; i > eltPos; i--) { + reportUnclosedElementNameAndLocation(i); + } + } + } + + /** + * Reports the name and location of an unclosed element. + * + * @throws SAXException + */ + private final void reportUnclosedElementNameAndLocation(int pos) throws SAXException { + StackNode<T> node = stack[pos]; + if (node.isOptionalEndTag()) { + return; + } + TaintableLocatorImpl locator = node.getLocator(); + if (locator.isTainted()) { + return; + } + locator.markTainted(); + SAXParseException spe = new SAXParseException( + "Unclosed element \u201C" + node.popName + "\u201D.", locator); + errorHandler.error(spe); + } + + /** + * Reports a warning + * + * @param message + * the message + * @throws SAXException + */ + final void warn(String message) throws SAXException { + if (errorHandler == null) { + return; + } + SAXParseException spe = new SAXParseException(message, tokenizer); + errorHandler.warning(spe); + } + + /** + * Reports a warning with an explicit locator + * + * @param message + * the message + * @throws SAXException + */ + final void warn(String message, Locator locator) throws SAXException { + if (errorHandler == null) { + return; + } + SAXParseException spe = new SAXParseException(message, locator); + errorHandler.warning(spe); + } + + // ]NOCPP] + + @SuppressWarnings("unchecked") public final void startTokenization(Tokenizer self) throws SAXException { + tokenizer = self; + stackNodes = new StackNode[64]; + stack = new StackNode[64]; + templateModeStack = new int[64]; + listOfActiveFormattingElements = new StackNode[64]; + needToDropLF = false; + originalMode = INITIAL; + templateModePtr = -1; + stackNodesIdx = 0; + numStackNodes = 0; + currentPtr = -1; + listPtr = -1; + formPointer = null; + headPointer = null; + // [NOCPP[ + idLocations.clear(); + wantingComments = wantsComments(); + // ]NOCPP] + start(fragment); + charBufferLen = 0; + charBuffer = null; + framesetOk = true; + if (fragment) { + T elt; + if (contextNode != null) { + elt = contextNode; + } else { + elt = createHtmlElementSetAsRoot(tokenizer.emptyAttributes()); + } + // When the context node is not in the HTML namespace, contrary + // to the spec, the first node on the stack is not set to "html" + // in the HTML namespace. Instead, it is set to a node that has + // the characteristics of the appropriate "adjusted current node". + // This way, there is no need to perform "adjusted current node" + // checks during tree construction. Instead, it's sufficient to + // just look at the current node. However, this also means that it + // is not safe to treat "html" in the HTML namespace as a sentinel + // that ends stack popping. Instead, stack popping loops that are + // meant not to pop the first element on the stack need to check + // for currentPos becoming zero. + if (contextNamespace == "http://www.w3.org/2000/svg") { + ElementName elementName = ElementName.SVG; + if ("title" == contextName || "desc" == contextName + || "foreignObject" == contextName) { + // These elements are all alike and we don't care about + // the exact name. + elementName = ElementName.FOREIGNOBJECT; + } + // This is the SVG variant of the StackNode constructor. + StackNode<T> node = createStackNode(elementName, + elementName.getCamelCaseName(), elt + // [NOCPP[ + , errorHandler == null ? null + : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + currentPtr++; + stack[currentPtr] = node; + tokenizer.setState(Tokenizer.DATA); + // The frameset-ok flag is set even though <frameset> never + // ends up being allowed as HTML frameset in the fragment case. + mode = FRAMESET_OK; + } else if (contextNamespace == "http://www.w3.org/1998/Math/MathML") { + ElementName elementName = ElementName.MATH; + if ("mi" == contextName || "mo" == contextName + || "mn" == contextName || "ms" == contextName + || "mtext" == contextName) { + // These elements are all alike and we don't care about + // the exact name. + elementName = ElementName.MTEXT; + } else if ("annotation-xml" == contextName) { + elementName = ElementName.ANNOTATION_XML; + // Blink does not check the encoding attribute of the + // annotation-xml element innerHTML is being set on. + // Let's do the same at least until + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26783 + // is resolved. + } + // This is the MathML variant of the StackNode constructor. + StackNode<T> node = createStackNode(elementName, elt, + elementName.getName(), false + // [NOCPP[ + , errorHandler == null ? null + : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + currentPtr++; + stack[currentPtr] = node; + tokenizer.setState(Tokenizer.DATA); + // The frameset-ok flag is set even though <frameset> never + // ends up being allowed as HTML frameset in the fragment case. + mode = FRAMESET_OK; + } else { // html + StackNode<T> node = createStackNode(ElementName.HTML, elt + // [NOCPP[ + , errorHandler == null ? null + : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + currentPtr++; + stack[currentPtr] = node; + if ("template" == contextName) { + pushTemplateMode(IN_TEMPLATE); + } + resetTheInsertionMode(); + formPointer = getFormPointerForContext(contextNode); + if ("title" == contextName || "textarea" == contextName) { + tokenizer.setState(Tokenizer.RCDATA); + } else if ("style" == contextName || "xmp" == contextName + || "iframe" == contextName || "noembed" == contextName + || "noframes" == contextName + || (scriptingEnabled && "noscript" == contextName)) { + tokenizer.setState(Tokenizer.RAWTEXT); + } else if ("plaintext" == contextName) { + tokenizer.setState(Tokenizer.PLAINTEXT); + } else if ("script" == contextName) { + tokenizer.setState(Tokenizer.SCRIPT_DATA); + } else { + tokenizer.setState(Tokenizer.DATA); + } + } + } else { + mode = INITIAL; + // If we are viewing XML source, put a foreign element permanently + // on the stack so that cdataSectionAllowed() returns true. + // CPPONLY: if (tokenizer.isViewingXmlSource()) { + // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg", + // CPPONLY: "svg", + // CPPONLY: tokenizer.emptyAttributes(), null, + // CPPONLY: svgCreator(NS_NewSVGSVGElement)); + // CPPONLY: StackNode<T> node = createStackNode(ElementName.SVG, + // CPPONLY: "svg", + // CPPONLY: elt); + // CPPONLY: currentPtr++; + // CPPONLY: stack[currentPtr] = node; + // CPPONLY: } + } + } + + public final void doctype(@Local String name, String publicIdentifier, + String systemIdentifier, boolean forceQuirks) throws SAXException { + needToDropLF = false; + if (!isInForeign() && mode == INITIAL) { + // [NOCPP[ + if (reportingDoctype) { + // ]NOCPP] + String emptyString = Portability.newEmptyString(); + appendDoctypeToDocument(name == null ? "" : name, + publicIdentifier == null ? emptyString + : publicIdentifier, + systemIdentifier == null ? emptyString + : systemIdentifier); + Portability.releaseString(emptyString); + // [NOCPP[ + } + // ]NOCPP] + if (isQuirky(name, publicIdentifier, systemIdentifier, + forceQuirks)) { + errQuirkyDoctype(); + documentModeInternal(DocumentMode.QUIRKS_MODE, + publicIdentifier, systemIdentifier); + } else if (isAlmostStandards(publicIdentifier, + systemIdentifier)) { + errAlmostStandardsDoctype(); + documentModeInternal( + DocumentMode.ALMOST_STANDARDS_MODE, + publicIdentifier, systemIdentifier); + } else { + // [NOCPP[ + if ((Portability.literalEqualsString( + "-//W3C//DTD HTML 4.0//EN", publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString( + "http://www.w3.org/TR/REC-html40/strict.dtd", + systemIdentifier))) + || (Portability.literalEqualsString( + "-//W3C//DTD HTML 4.01//EN", + publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString( + "http://www.w3.org/TR/html4/strict.dtd", + systemIdentifier))) + || (Portability.literalEqualsString( + "-//W3C//DTD XHTML 1.0 Strict//EN", + publicIdentifier) && Portability.literalEqualsString( + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", + systemIdentifier)) + || (Portability.literalEqualsString( + "-//W3C//DTD XHTML 1.1//EN", + publicIdentifier) && Portability.literalEqualsString( + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd", + systemIdentifier)) + + ) { + err("Obsolete doctype. Expected \u201C<!DOCTYPE html>\u201D."); + } else if (!((systemIdentifier == null || Portability.literalEqualsString( + "about:legacy-compat", systemIdentifier)) && publicIdentifier == null)) { + err("Legacy doctype. Expected \u201C<!DOCTYPE html>\u201D."); + } + // ]NOCPP] + documentModeInternal(DocumentMode.STANDARDS_MODE, + publicIdentifier, systemIdentifier); + } + + /* + * + * Then, switch to the root element mode of the tree construction + * stage. + */ + mode = BEFORE_HTML; + return; + } + /* + * A DOCTYPE token Parse error. + */ + errStrayDoctype(); + /* + * Ignore the token. + */ + return; + } + + public final void comment(@NoLength char[] buf, int start, int length) + throws SAXException { + needToDropLF = false; + // [NOCPP[ + if (!wantingComments) { + return; + } + // ]NOCPP] + if (!isInForeign()) { + switch (mode) { + case INITIAL: + case BEFORE_HTML: + case AFTER_AFTER_BODY: + case AFTER_AFTER_FRAMESET: + /* + * A comment token Append a Comment node to the Document + * object with the data attribute set to the data given in + * the comment token. + */ + appendCommentToDocument(buf, start, length); + return; + case AFTER_BODY: + /* + * A comment token Append a Comment node to the first + * element in the stack of open elements (the html element), + * with the data attribute set to the data given in the + * comment token. + */ + flushCharacters(); + appendComment(stack[0].node, buf, start, length); + return; + default: + break; + } + } + /* + * A comment token Append a Comment node to the current node with the + * data attribute set to the data given in the comment token. + */ + flushCharacters(); + appendComment(stack[currentPtr].node, buf, start, length); + return; + } + + /** + * @see nu.validator.htmlparser.common.TokenHandler#characters(char[], int, + * int) + */ + public final void characters(@Const @NoLength char[] buf, int start, int length) + throws SAXException { + // Note: Can't attach error messages to EOF in C++ yet + + // CPPONLY: if (tokenizer.isViewingXmlSource()) { + // CPPONLY: return; + // CPPONLY: } + if (needToDropLF) { + needToDropLF = false; + if (buf[start] == '\n') { + start++; + length--; + if (length == 0) { + return; + } + } + } + + // optimize the most common case + switch (mode) { + case IN_BODY: + case IN_CELL: + case IN_CAPTION: + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { + reconstructTheActiveFormattingElements(); + } + // CPPONLY: MOZ_FALLTHROUGH; + case TEXT: + accumulateCharacters(buf, start, length); + return; + case IN_TABLE: + case IN_TABLE_BODY: + case IN_ROW: + accumulateCharactersForced(buf, start, length); + return; + default: + int end = start + length; + charactersloop: for (int i = start; i < end; i++) { + switch (buf[i]) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\u000C': + /* + * A character token that is one of one of U+0009 + * CHARACTER TABULATION, U+000A LINE FEED (LF), + * U+000C FORM FEED (FF), or U+0020 SPACE + */ + switch (mode) { + case INITIAL: + case BEFORE_HTML: + case BEFORE_HEAD: + /* + * Ignore the token. + */ + start = i + 1; + continue; + case IN_HEAD: + case IN_HEAD_NOSCRIPT: + case AFTER_HEAD: + case IN_COLUMN_GROUP: + case IN_FRAMESET: + case AFTER_FRAMESET: + /* + * Append the character to the current node. + */ + continue; + case FRAMESET_OK: + case IN_TEMPLATE: + case IN_BODY: + case IN_CELL: + case IN_CAPTION: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + + /* + * Reconstruct the active formatting + * elements, if any. + */ + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { + flushCharacters(); + reconstructTheActiveFormattingElements(); + } + /* + * Append the token's character to the + * current node. + */ + break charactersloop; + case IN_SELECT: + case IN_SELECT_IN_TABLE: + break charactersloop; + case IN_TABLE: + case IN_TABLE_BODY: + case IN_ROW: + accumulateCharactersForced(buf, i, 1); + start = i + 1; + continue; + case AFTER_BODY: + case AFTER_AFTER_BODY: + case AFTER_AFTER_FRAMESET: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + /* + * Reconstruct the active formatting + * elements, if any. + */ + flushCharacters(); + reconstructTheActiveFormattingElements(); + /* + * Append the token's character to the + * current node. + */ + continue; + } + // CPPONLY: MOZ_FALLTHROUGH_ASSERT(); + default: + /* + * A character token that is not one of one of + * U+0009 CHARACTER TABULATION, U+000A LINE FEED + * (LF), U+000C FORM FEED (FF), or U+0020 SPACE + */ + switch (mode) { + case INITIAL: + /* + * Parse error. + */ + // [NOCPP[ + // XXX figure out a way to report this in the Gecko View Source case + err("Non-space characters found without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); + // ]NOCPP] + /* + * + * Set the document to quirks mode. + */ + documentModeInternal( + DocumentMode.QUIRKS_MODE, null, + null); + /* + * Then, switch to the root element mode of + * the tree construction stage + */ + mode = BEFORE_HTML; + /* + * and reprocess the current token. + */ + i--; + continue; + case BEFORE_HTML: + /* + * Create an HTMLElement node with the tag + * name html, in the HTML namespace. Append + * it to the Document object. + */ + // No need to flush characters here, + // because there's nothing to flush. + appendHtmlElementToDocumentAndPush(); + /* Switch to the main mode */ + mode = BEFORE_HEAD; + /* + * reprocess the current token. + */ + i--; + continue; + case BEFORE_HEAD: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + /* + * /Act as if a start tag token with the tag + * name "head" and no attributes had been + * seen, + */ + flushCharacters(); + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); + mode = IN_HEAD; + /* + * then reprocess the current token. + * + * This will result in an empty head element + * being generated, with the current token + * being reprocessed in the "after head" + * insertion mode. + */ + i--; + continue; + case IN_HEAD: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + /* + * Act as if an end tag token with the tag + * name "head" had been seen, + */ + flushCharacters(); + pop(); + mode = AFTER_HEAD; + /* + * and reprocess the current token. + */ + i--; + continue; + case IN_HEAD_NOSCRIPT: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + /* + * Parse error. Act as if an end tag with + * the tag name "noscript" had been seen + */ + errNonSpaceInNoscriptInHead(); + flushCharacters(); + pop(); + mode = IN_HEAD; + /* + * and reprocess the current token. + */ + i--; + continue; + case AFTER_HEAD: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + /* + * Act as if a start tag token with the tag + * name "body" and no attributes had been + * seen, + */ + flushCharacters(); + appendToCurrentNodeAndPushBodyElement(); + mode = FRAMESET_OK; + /* + * and then reprocess the current token. + */ + i--; + continue; + case FRAMESET_OK: + framesetOk = false; + mode = IN_BODY; + i--; + continue; + case IN_TEMPLATE: + case IN_BODY: + case IN_CELL: + case IN_CAPTION: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + /* + * Reconstruct the active formatting + * elements, if any. + */ + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { + flushCharacters(); + reconstructTheActiveFormattingElements(); + } + /* + * Append the token's character to the + * current node. + */ + break charactersloop; + case IN_TABLE: + case IN_TABLE_BODY: + case IN_ROW: + accumulateCharactersForced(buf, i, 1); + start = i + 1; + continue; + case IN_COLUMN_GROUP: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + start = i; + } + /* + * Act as if an end tag with the tag name + * "colgroup" had been seen, and then, if + * that token wasn't ignored, reprocess the + * current token. + */ + if (currentPtr == 0 || stack[currentPtr].getGroup() == + TreeBuilder.TEMPLATE) { + errNonSpaceInColgroupInFragment(); + start = i + 1; + continue; + } + flushCharacters(); + pop(); + mode = IN_TABLE; + i--; + continue; + case IN_SELECT: + case IN_SELECT_IN_TABLE: + break charactersloop; + case AFTER_BODY: + errNonSpaceAfterBody(); + fatal(); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + i--; + continue; + case IN_FRAMESET: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + // start index is adjusted below. + } + /* + * Parse error. + */ + errNonSpaceInFrameset(); + /* + * Ignore the token. + */ + start = i + 1; + continue; + case AFTER_FRAMESET: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + // start index is adjusted below. + } + /* + * Parse error. + */ + errNonSpaceAfterFrameset(); + /* + * Ignore the token. + */ + start = i + 1; + continue; + case AFTER_AFTER_BODY: + /* + * Parse error. + */ + errNonSpaceInTrailer(); + /* + * Switch back to the main mode and + * reprocess the token. + */ + mode = framesetOk ? FRAMESET_OK : IN_BODY; + i--; + continue; + case AFTER_AFTER_FRAMESET: + if (start < i) { + accumulateCharacters(buf, start, i + - start); + // start index is adjusted below. + } + /* + * Parse error. + */ + errNonSpaceInTrailer(); + /* + * Ignore the token. + */ + start = i + 1; + continue; + } + } + } + if (start < end) { + accumulateCharacters(buf, start, end - start); + } + } + } + + /** + * @see nu.validator.htmlparser.common.TokenHandler#zeroOriginatingReplacementCharacter() + */ + public void zeroOriginatingReplacementCharacter() throws SAXException { + if (mode == TEXT) { + accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1); + return; + } + if (currentPtr >= 0) { + if (isSpecialParentInForeign(stack[currentPtr])) { + return; + } + accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1); + } + } + + /** + * @see nu.validator.htmlparser.common.TokenHandler#zeroOrReplacementCharacter() + */ + public void zeroOrReplacementCharacter() throws SAXException { + zeroOriginatingReplacementCharacter(); + } + + public final void eof() throws SAXException { + flushCharacters(); + // Note: Can't attach error messages to EOF in C++ yet + eofloop: for (;;) { + switch (mode) { + case INITIAL: + /* + * Parse error. + */ + // [NOCPP[ + err("End of file seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); + // ]NOCPP] + /* + * + * Set the document to quirks mode. + */ + documentModeInternal(DocumentMode.QUIRKS_MODE, null, null); + /* + * Then, switch to the root element mode of the tree + * construction stage + */ + mode = BEFORE_HTML; + /* + * and reprocess the current token. + */ + continue; + case BEFORE_HTML: + /* + * Create an HTMLElement node with the tag name html, in the + * HTML namespace. Append it to the Document object. + */ + appendHtmlElementToDocumentAndPush(); + // XXX application cache manifest + /* Switch to the main mode */ + mode = BEFORE_HEAD; + /* + * reprocess the current token. + */ + continue; + case BEFORE_HEAD: + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); + mode = IN_HEAD; + continue; + case IN_HEAD: + // [NOCPP[ + if (errorHandler != null && currentPtr > 1) { + errEofWithUnclosedElements(); + } + // ]NOCPP] + while (currentPtr > 0) { + popOnEof(); + } + mode = AFTER_HEAD; + continue; + case IN_HEAD_NOSCRIPT: + // [NOCPP[ + errEofWithUnclosedElements(); + // ]NOCPP] + while (currentPtr > 1) { + popOnEof(); + } + mode = IN_HEAD; + continue; + case AFTER_HEAD: + appendToCurrentNodeAndPushBodyElement(); + mode = IN_BODY; + continue; + case IN_TABLE_BODY: + case IN_ROW: + case IN_TABLE: + case IN_SELECT_IN_TABLE: + case IN_SELECT: + case IN_COLUMN_GROUP: + case FRAMESET_OK: + case IN_CAPTION: + case IN_CELL: + case IN_BODY: + // [NOCPP[ + // i > 0 to stop in time in the foreign fragment case. + openelementloop: for (int i = currentPtr; i > 0; i--) { + int group = stack[i].getGroup(); + switch (group) { + case DD_OR_DT: + case LI: + case P: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case BODY: + case HTML: + break; + default: + errEofWithUnclosedElements(); + break openelementloop; + } + } + // ]NOCPP] + + if (isTemplateModeStackEmpty()) { + break eofloop; + } + + // fall through to IN_TEMPLATE + // CPPONLY: MOZ_FALLTHROUGH; + case IN_TEMPLATE: + int eltPos = findLast("template"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment; + break eofloop; + } + if (errorHandler != null) { + errListUnclosedStartTags(0); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + popTemplateMode(); + resetTheInsertionMode(); + + // Reprocess token. + continue; + case TEXT: + // [NOCPP[ + if (errorHandler != null) { + errNoCheck("End of file seen when expecting text or an end tag."); + errListUnclosedStartTags(0); + } + // ]NOCPP] + // XXX mark script as already executed + if (originalMode == AFTER_HEAD) { + popOnEof(); + } + popOnEof(); + mode = originalMode; + continue; + case IN_FRAMESET: + // [NOCPP[ + if (errorHandler != null && currentPtr > 0) { + errEofWithUnclosedElements(); + } + // ]NOCPP] + break eofloop; + case AFTER_BODY: + case AFTER_FRAMESET: + case AFTER_AFTER_BODY: + case AFTER_AFTER_FRAMESET: + default: + // [NOCPP[ + if (currentPtr == 0) { // This silliness is here to poison + // buggy compiler optimizations in + // GWT + System.currentTimeMillis(); + } + // ]NOCPP] + break eofloop; + } + } + while (currentPtr > 0) { + popOnEof(); + } + if (!fragment) { + popOnEof(); + } + /* Stop parsing. */ + } + + /** + * @see nu.validator.htmlparser.common.TokenHandler#endTokenization() + */ + public final void endTokenization() throws SAXException { + formPointer = null; + headPointer = null; + contextName = null; + contextNode = null; + templateModeStack = null; + if (stack != null) { + while (currentPtr > -1) { + stack[currentPtr].release(this); + currentPtr--; + } + stack = null; + } + if (listOfActiveFormattingElements != null) { + while (listPtr > -1) { + if (listOfActiveFormattingElements[listPtr] != null) { + listOfActiveFormattingElements[listPtr].release(this); + } + listPtr--; + } + listOfActiveFormattingElements = null; + } + if (stackNodes != null) { + for (int i = 0; i < numStackNodes; i++) { + assert stackNodes[i].isUnused(); + Portability.delete(stackNodes[i]); + } + numStackNodes = 0; + stackNodesIdx = 0; + stackNodes = null; + } + // [NOCPP[ + idLocations.clear(); + // ]NOCPP] + charBuffer = null; + end(); + } + + public final void startTag(ElementName elementName, + HtmlAttributes attributes, boolean selfClosing) throws SAXException { + flushCharacters(); + + // [NOCPP[ + if (errorHandler != null) { + // ID uniqueness + @IdType String id = attributes.getId(); + if (id != null) { + LocatorImpl oldLoc = idLocations.get(id); + if (oldLoc != null) { + err("Duplicate ID \u201C" + id + "\u201D."); + errorHandler.warning(new SAXParseException( + "The first occurrence of ID \u201C" + id + + "\u201D was here.", oldLoc)); + } else { + idLocations.put(id, new LocatorImpl(tokenizer)); + } + } + } + // ]NOCPP] + + int eltPos; + needToDropLF = false; + starttagloop: for (;;) { + int group = elementName.getGroup(); + @Local String name = elementName.getName(); + if (isInForeign()) { + StackNode<T> currentNode = stack[currentPtr]; + @NsUri String currNs = currentNode.ns; + if (!(currentNode.isHtmlIntegrationPoint() || (currNs == "http://www.w3.org/1998/Math/MathML" && ((currentNode.getGroup() == MI_MO_MN_MS_MTEXT && group != MGLYPH_OR_MALIGNMARK) || (currentNode.getGroup() == ANNOTATION_XML && group == SVG))))) { + switch (group) { + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: + case BODY: + case BR: + case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR: + case DD_OR_DT: + case UL_OR_OL_OR_DL: + case EMBED: + case IMG: + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: + case HEAD: + case HR: + case LI: + case META: + case NOBR: + case P: + case PRE_OR_LISTING: + case TABLE: + case FONT: + // re-check FONT to deal with the special case + if (!(group == FONT && !(attributes.contains(AttributeName.COLOR) + || attributes.contains(AttributeName.FACE) || attributes.contains(AttributeName.SIZE)))) { + errHtmlStartTagInForeignContext(name); + if (!fragment) { + while (!isSpecialParentInForeign(stack[currentPtr])) { + popForeign(-1, -1); + } + continue starttagloop; + } // else fall thru + } + // CPPONLY: MOZ_FALLTHROUGH; + default: + if ("http://www.w3.org/2000/svg" == currNs) { + attributes.adjustForSvg(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterSVG( + elementName, attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterSVG( + elementName, attributes); + } + attributes = null; // CPP + break starttagloop; + } else { + attributes.adjustForMath(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterMathML( + elementName, attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterMathML( + elementName, attributes); + } + attributes = null; // CPP + break starttagloop; + } + } // switch + } // foreignObject / annotation-xml + } + switch (mode) { + case IN_TEMPLATE: + switch (group) { + case COL: + popTemplateMode(); + pushTemplateMode(IN_COLUMN_GROUP); + mode = IN_COLUMN_GROUP; + // Reprocess token. + continue; + case CAPTION: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + popTemplateMode(); + pushTemplateMode(IN_TABLE); + mode = IN_TABLE; + // Reprocess token. + continue; + case TR: + popTemplateMode(); + pushTemplateMode(IN_TABLE_BODY); + mode = IN_TABLE_BODY; + // Reprocess token. + continue; + case TD_OR_TH: + popTemplateMode(); + pushTemplateMode(IN_ROW); + mode = IN_ROW; + // Reprocess token. + continue; + case META: + checkMetaCharset(attributes); + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case TITLE: + startTagTitleInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case SCRIPT: + startTagScriptInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case NOFRAMES: + case STYLE: + startTagGenericRawText(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case TEMPLATE: + startTagTemplateInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + default: + popTemplateMode(); + pushTemplateMode(IN_BODY); + mode = IN_BODY; + // Reprocess token. + continue; + } + case IN_ROW: + switch (group) { + case TD_OR_TH: + clearStackBackTo(findLastOrRoot(TreeBuilder.TR)); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + mode = IN_CELL; + insertMarker(); + attributes = null; // CPP + break starttagloop; + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + eltPos = findLastOrRoot(TreeBuilder.TR); + if (eltPos == 0) { + assert fragment || isTemplateContents(); + errNoTableRowToClose(); + break starttagloop; + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + continue; + default: + // fall through to IN_TABLE + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_TABLE_BODY: + switch (group) { + case TR: + clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot()); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + mode = IN_ROW; + attributes = null; // CPP + break starttagloop; + case TD_OR_TH: + errStartTagInTableBody(name); + clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot()); + appendToCurrentNodeAndPushElement( + ElementName.TR, + HtmlAttributes.EMPTY_ATTRIBUTES); + mode = IN_ROW; + continue; + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot(); + if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) { + assert fragment || isTemplateContents(); + errStrayStartTag(name); + break starttagloop; + } else { + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE; + continue; + } + default: + // fall through to IN_TABLE + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_TABLE: + intableloop: for (;;) { + switch (group) { + case CAPTION: + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); + insertMarker(); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + mode = IN_CAPTION; + attributes = null; // CPP + break starttagloop; + case COLGROUP: + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + mode = IN_COLUMN_GROUP; + attributes = null; // CPP + break starttagloop; + case COL: + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); + appendToCurrentNodeAndPushElement( + ElementName.COLGROUP, + HtmlAttributes.EMPTY_ATTRIBUTES); + mode = IN_COLUMN_GROUP; + continue starttagloop; + case TBODY_OR_THEAD_OR_TFOOT: + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + mode = IN_TABLE_BODY; + attributes = null; // CPP + break starttagloop; + case TR: + case TD_OR_TH: + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); + appendToCurrentNodeAndPushElement( + ElementName.TBODY, + HtmlAttributes.EMPTY_ATTRIBUTES); + mode = IN_TABLE_BODY; + continue starttagloop; + case TEMPLATE: + // fall through to IN_HEAD + break intableloop; + case TABLE: + errTableSeenWhileTableOpen(); + eltPos = findLastInTableScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment || isTemplateContents(); + break starttagloop; + } + generateImpliedEndTags(); + if (errorHandler != null && !isCurrent("table")) { + errNoCheckUnclosedElementsOnStack(); + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + continue starttagloop; + case SCRIPT: + // XXX need to manage much more stuff + // here if + // supporting + // document.write() + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.SCRIPT_DATA, elementName); + attributes = null; // CPP + break starttagloop; + case STYLE: + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RAWTEXT, elementName); + attributes = null; // CPP + break starttagloop; + case INPUT: + errStartTagInTable(name); + if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "hidden", + attributes.getValue(AttributeName.TYPE))) { + break intableloop; + } + appendVoidInputToCurrent( + attributes, + formPointer); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case FORM: + if (formPointer != null || isTemplateContents()) { + errFormWhenFormOpen(); + break starttagloop; + } else { + errStartTagInTable(name); + appendVoidFormToCurrent(attributes); + attributes = null; // CPP + break starttagloop; + } + default: + errStartTagInTable(name); + // fall through to IN_BODY + break intableloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_CAPTION: + switch (group) { + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: + eltPos = findLastInTableScope("caption"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment || isTemplateContents(); + errStrayStartTag(name); + break starttagloop; + } + generateImpliedEndTags(); + if (errorHandler != null && currentPtr != eltPos) { + errNoCheckUnclosedElementsOnStack(); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_TABLE; + continue; + default: + // fall through to IN_BODY + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_CELL: + switch (group) { + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: + eltPos = findLastInTableScopeTdTh(); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errNoCellToClose(); + break starttagloop; + } else { + closeTheCell(eltPos); + continue; + } + default: + // fall through to IN_BODY + } + // CPPONLY: MOZ_FALLTHROUGH; + case FRAMESET_OK: + switch (group) { + case FRAMESET: + if (mode == FRAMESET_OK) { + if (currentPtr == 0 || stack[1].getGroup() != BODY) { + assert fragment || isTemplateContents(); + errStrayStartTag(name); + break starttagloop; + } else { + errFramesetStart(); + detachFromParent(stack[1].node); + while (currentPtr > 0) { + pop(); + } + appendToCurrentNodeAndPushElement( + elementName, + attributes); + mode = IN_FRAMESET; + attributes = null; // CPP + break starttagloop; + } + } else { + errStrayStartTag(name); + break starttagloop; + } + // NOT falling through! + case PRE_OR_LISTING: + case LI: + case DD_OR_DT: + case BUTTON: + case MARQUEE_OR_APPLET: + case OBJECT: + case TABLE: + case AREA_OR_WBR: + case KEYGEN: + case BR: + case EMBED: + case IMG: + case INPUT: + case HR: + case TEXTAREA: + case XMP: + case IFRAME: + case SELECT: + if (mode == FRAMESET_OK + && !(group == INPUT && Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "hidden", + attributes.getValue(AttributeName.TYPE)))) { + framesetOk = false; + mode = IN_BODY; + } + // CPPONLY: MOZ_FALLTHROUGH; + default: + // fall through to IN_BODY + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_BODY: + inbodyloop: for (;;) { + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: + case META: + case STYLE: + case SCRIPT: + case TITLE: + case TEMPLATE: + // Fall through to IN_HEAD + break inbodyloop; + case BODY: + if (currentPtr == 0 || stack[1].getGroup() != BODY || isTemplateContents()) { + assert fragment || isTemplateContents(); + errStrayStartTag(name); + break starttagloop; + } + errFooSeenWhenFooOpen(name); + framesetOk = false; + if (mode == FRAMESET_OK) { + mode = IN_BODY; + } + if (addAttributesToBody(attributes)) { + attributes = null; // CPP + } + break starttagloop; + case P: + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: + case UL_OR_OL_OR_DL: + case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: + implicitlyCloseP(); + if (stack[currentPtr].getGroup() == H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) { + errHeadingWhenHeadingOpen(); + pop(); + } + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case FIELDSET: + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes, formPointer); + attributes = null; // CPP + break starttagloop; + case PRE_OR_LISTING: + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + needToDropLF = true; + attributes = null; // CPP + break starttagloop; + case FORM: + if (formPointer != null && !isTemplateContents()) { + errFormWhenFormOpen(); + break starttagloop; + } else { + implicitlyCloseP(); + appendToCurrentNodeAndPushFormElementMayFoster(attributes); + attributes = null; // CPP + break starttagloop; + } + case LI: + case DD_OR_DT: + eltPos = currentPtr; + for (;;) { + StackNode<T> node = stack[eltPos]; // weak + // ref + if (node.getGroup() == group) { // LI or + // DD_OR_DT + generateImpliedEndTagsExceptFor(node.name); + if (errorHandler != null + && eltPos != currentPtr) { + errUnclosedElementsImplied(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + break; + } else if (eltPos == 0 || (node.isSpecial() + && (node.ns != "http://www.w3.org/1999/xhtml" + || (node.name != "p" + && node.name != "address" + && node.name != "div")))) { + break; + } + eltPos--; + } + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case PLAINTEXT: + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + tokenizer.setStateAndEndTagExpectation( + Tokenizer.PLAINTEXT, elementName); + attributes = null; // CPP + break starttagloop; + case A: + int activeAPos = findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker("a"); + if (activeAPos != -1) { + errFooSeenWhenFooOpen(name); + StackNode<T> activeA = listOfActiveFormattingElements[activeAPos]; + activeA.retain(); + adoptionAgencyEndTag("a"); + removeFromStack(activeA); + activeAPos = findInListOfActiveFormattingElements(activeA); + if (activeAPos != -1) { + removeFromListOfActiveFormattingElements(activeAPos); + } + activeA.release(this); + } + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushFormattingElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: + case FONT: + reconstructTheActiveFormattingElements(); + maybeForgetEarlierDuplicateFormattingElement(elementName.getName(), attributes); + appendToCurrentNodeAndPushFormattingElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case NOBR: + reconstructTheActiveFormattingElements(); + if (TreeBuilder.NOT_FOUND_ON_STACK != findLastInScope("nobr")) { + errFooSeenWhenFooOpen(name); + adoptionAgencyEndTag("nobr"); + reconstructTheActiveFormattingElements(); + } + appendToCurrentNodeAndPushFormattingElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case BUTTON: + eltPos = findLastInScope(name); + if (eltPos != TreeBuilder.NOT_FOUND_ON_STACK) { + errFooSeenWhenFooOpen(name); + generateImpliedEndTags(); + if (errorHandler != null + && !isCurrent(name)) { + errUnclosedElementsImplied(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + continue starttagloop; + } else { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes, formPointer); + attributes = null; // CPP + break starttagloop; + } + case OBJECT: + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes, formPointer); + insertMarker(); + attributes = null; // CPP + break starttagloop; + case MARQUEE_OR_APPLET: + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + insertMarker(); + attributes = null; // CPP + break starttagloop; + case TABLE: + // The only quirk. Blame Hixie and + // Acid2. + if (!quirks) { + implicitlyCloseP(); + } + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + mode = IN_TABLE; + attributes = null; // CPP + break starttagloop; + case BR: + case EMBED: + case AREA_OR_WBR: + case KEYGEN: + reconstructTheActiveFormattingElements(); + // FALL THROUGH to PARAM_OR_SOURCE_OR_TRACK + // CPPONLY: MOZ_FALLTHROUGH; + case PARAM_OR_SOURCE_OR_TRACK: + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case HR: + implicitlyCloseP(); + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case IMAGE: + errImage(); + elementName = ElementName.IMG; + continue starttagloop; + case IMG: + case INPUT: + reconstructTheActiveFormattingElements(); + appendVoidElementToCurrentMayFoster( + elementName, attributes, + formPointer); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case TEXTAREA: + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes, formPointer); + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RCDATA, elementName); + originalMode = mode; + mode = TEXT; + needToDropLF = true; + attributes = null; // CPP + break starttagloop; + case XMP: + implicitlyCloseP(); + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RAWTEXT, elementName); + attributes = null; // CPP + break starttagloop; + case NOSCRIPT: + if (!scriptingEnabled) { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + } + // CPPONLY: MOZ_FALLTHROUGH; + case NOFRAMES: + case IFRAME: + case NOEMBED: + startTagGenericRawText(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case SELECT: + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes, formPointer); + switch (mode) { + case IN_TABLE: + case IN_CAPTION: + case IN_COLUMN_GROUP: + case IN_TABLE_BODY: + case IN_ROW: + case IN_CELL: + mode = IN_SELECT_IN_TABLE; + break; + default: + mode = IN_SELECT; + break; + } + attributes = null; // CPP + break starttagloop; + case OPTGROUP: + case OPTION: + if (isCurrent("option")) { + pop(); + } + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case RB_OR_RTC: + eltPos = findLastInScope("ruby"); + if (eltPos != NOT_FOUND_ON_STACK) { + generateImpliedEndTags(); + } + if (eltPos != currentPtr) { + if (eltPos == NOT_FOUND_ON_STACK) { + errStartTagSeenWithoutRuby(name); + } else { + errUnclosedChildrenInRuby(); + } + } + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case RT_OR_RP: + eltPos = findLastInScope("ruby"); + if (eltPos != NOT_FOUND_ON_STACK) { + generateImpliedEndTagsExceptFor("rtc"); + } + if (eltPos != currentPtr) { + if (!isCurrent("rtc")) { + if (eltPos == NOT_FOUND_ON_STACK) { + errStartTagSeenWithoutRuby(name); + } else { + errUnclosedChildrenInRuby(); + } + } + } + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case MATH: + reconstructTheActiveFormattingElements(); + attributes.adjustForMath(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterMathML( + elementName, attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterMathML( + elementName, attributes); + } + attributes = null; // CPP + break starttagloop; + case SVG: + reconstructTheActiveFormattingElements(); + attributes.adjustForSvg(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterSVG( + elementName, + attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterSVG( + elementName, attributes); + } + attributes = null; // CPP + break starttagloop; + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: + case FRAME: + case FRAMESET: + case HEAD: + errStrayStartTag(name); + break starttagloop; + case OUTPUT: + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes, formPointer); + attributes = null; // CPP + break starttagloop; + default: + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_HEAD: + inheadloop: for (;;) { + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case META: + // Fall through to IN_HEAD_NOSCRIPT + break inheadloop; + case TITLE: + startTagTitleInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case NOSCRIPT: + if (scriptingEnabled) { + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RAWTEXT, elementName); + } else { + appendToCurrentNodeAndPushElementMayFoster( + elementName, + attributes); + mode = IN_HEAD_NOSCRIPT; + } + attributes = null; // CPP + break starttagloop; + case SCRIPT: + startTagScriptInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case STYLE: + case NOFRAMES: + startTagGenericRawText(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case HEAD: + /* Parse error. */ + errFooSeenWhenFooOpen(name); + /* Ignore the token. */ + break starttagloop; + case TEMPLATE: + startTagTemplateInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + default: + pop(); + mode = AFTER_HEAD; + continue starttagloop; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_HEAD_NOSCRIPT: + switch (group) { + case HTML: + // XXX did Hixie really mean to omit "base" + // here? + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case LINK_OR_BASEFONT_OR_BGSOUND: + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case META: + checkMetaCharset(attributes); + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case STYLE: + case NOFRAMES: + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RAWTEXT, elementName); + attributes = null; // CPP + break starttagloop; + case HEAD: + errFooSeenWhenFooOpen(name); + break starttagloop; + case NOSCRIPT: + errFooSeenWhenFooOpen(name); + break starttagloop; + default: + errBadStartTagInNoscriptInHead(name); + pop(); + mode = IN_HEAD; + continue; + } + case IN_COLUMN_GROUP: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case COL: + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + case TEMPLATE: + startTagTemplateInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + default: + if (currentPtr == 0 || stack[currentPtr].getGroup() == TEMPLATE) { + assert fragment || isTemplateContents(); + errGarbageInColgroup(); + break starttagloop; + } + pop(); + mode = IN_TABLE; + continue; + } + case IN_SELECT_IN_TABLE: + switch (group) { + case CAPTION: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: + case TABLE: + errStartTagWithSelectOpen(name); + eltPos = findLastInTableScope("select"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment; + break starttagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375 + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + continue; + default: + // fall through to IN_SELECT + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_SELECT: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case OPTION: + if (isCurrent("option")) { + pop(); + } + appendToCurrentNodeAndPushElement( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case OPTGROUP: + if (isCurrent("option")) { + pop(); + } + if (isCurrent("optgroup")) { + pop(); + } + appendToCurrentNodeAndPushElement( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case SELECT: + errStartSelectWhereEndSelectExpected(); + eltPos = findLastInTableScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment; + errNoSelectInTableScope(); + break starttagloop; + } else { + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + break starttagloop; + } + case INPUT: + case TEXTAREA: + errStartTagWithSelectOpen(name); + eltPos = findLastInTableScope("select"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment; + break starttagloop; + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + continue; + case SCRIPT: + startTagScriptInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + case TEMPLATE: + startTagTemplateInHead(elementName, attributes); + attributes = null; // CPP + break starttagloop; + default: + errStrayStartTag(name); + break starttagloop; + } + case AFTER_BODY: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + default: + errStrayStartTag(name); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + } + case IN_FRAMESET: + switch (group) { + case FRAMESET: + appendToCurrentNodeAndPushElement( + elementName, + attributes); + attributes = null; // CPP + break starttagloop; + case FRAME: + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + attributes = null; // CPP + break starttagloop; + default: + // fall through to AFTER_FRAMESET + } + // CPPONLY: MOZ_FALLTHROUGH; + case AFTER_FRAMESET: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case NOFRAMES: + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RAWTEXT, elementName); + attributes = null; // CPP + break starttagloop; + default: + errStrayStartTag(name); + break starttagloop; + } + case INITIAL: + /* + * Parse error. + */ + errStartTagWithoutDoctype(); + /* + * + * Set the document to quirks mode. + */ + documentModeInternal(DocumentMode.QUIRKS_MODE, null, null); + /* + * Then, switch to the root element mode of the tree + * construction stage + */ + mode = BEFORE_HTML; + /* + * and reprocess the current token. + */ + continue; + case BEFORE_HTML: + switch (group) { + case HTML: + // optimize error check and streaming SAX by + // hoisting + // "html" handling here. + if (attributes == HtmlAttributes.EMPTY_ATTRIBUTES) { + // This has the right magic side effect + // that + // it + // makes attributes in SAX Tree mutable. + appendHtmlElementToDocumentAndPush(); + } else { + appendHtmlElementToDocumentAndPush(attributes); + } + // XXX application cache should fire here + mode = BEFORE_HEAD; + attributes = null; // CPP + break starttagloop; + default: + /* + * Create an HTMLElement node with the tag name + * html, in the HTML namespace. Append it to the + * Document object. + */ + appendHtmlElementToDocumentAndPush(); + /* Switch to the main mode */ + mode = BEFORE_HEAD; + /* + * reprocess the current token. + */ + continue; + } + case BEFORE_HEAD: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case HEAD: + /* + * A start tag whose tag name is "head" + * + * Create an element for the token. + * + * Set the head element pointer to this new element + * node. + * + * Append the new element to the current node and + * push it onto the stack of open elements. + */ + appendToCurrentNodeAndPushHeadElement(attributes); + /* + * Change the insertion mode to "in head". + */ + mode = IN_HEAD; + attributes = null; // CPP + break starttagloop; + default: + /* + * Any other start tag token + * + * Act as if a start tag token with the tag name + * "head" and no attributes had been seen, + */ + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); + mode = IN_HEAD; + /* + * then reprocess the current token. + * + * This will result in an empty head element being + * generated, with the current token being + * reprocessed in the "after head" insertion mode. + */ + continue; + } + case AFTER_HEAD: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case BODY: + if (attributes.getLength() == 0) { + // This has the right magic side effect + // that + // it + // makes attributes in SAX Tree mutable. + appendToCurrentNodeAndPushBodyElement(); + } else { + appendToCurrentNodeAndPushBodyElement(attributes); + } + framesetOk = false; + mode = IN_BODY; + attributes = null; // CPP + break starttagloop; + case FRAMESET: + appendToCurrentNodeAndPushElement( + elementName, + attributes); + mode = IN_FRAMESET; + attributes = null; // CPP + break starttagloop; + case TEMPLATE: + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + StackNode<T> headOnStack = stack[currentPtr]; + startTagTemplateInHead(elementName, attributes); + removeFromStack(headOnStack); + attributes = null; // CPP + break starttagloop; + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + pop(); // head + attributes = null; // CPP + break starttagloop; + case META: + errFooBetweenHeadAndBody(name); + checkMetaCharset(attributes); + pushHeadPointerOntoStack(); + appendVoidElementToCurrentMayFoster( + elementName, + attributes); + selfClosing = false; + pop(); // head + attributes = null; // CPP + break starttagloop; + case SCRIPT: + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.SCRIPT_DATA, elementName); + attributes = null; // CPP + break starttagloop; + case STYLE: + case NOFRAMES: + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RAWTEXT, elementName); + attributes = null; // CPP + break starttagloop; + case TITLE: + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendToCurrentNodeAndPushElement( + elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation( + Tokenizer.RCDATA, elementName); + attributes = null; // CPP + break starttagloop; + case HEAD: + errStrayStartTag(name); + break starttagloop; + default: + appendToCurrentNodeAndPushBodyElement(); + mode = FRAMESET_OK; + continue; + } + case AFTER_AFTER_BODY: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + default: + errStrayStartTag(name); + fatal(); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + } + case AFTER_AFTER_FRAMESET: + switch (group) { + case HTML: + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = null; // CPP + } + break starttagloop; + case NOFRAMES: + startTagGenericRawText(elementName, attributes); + attributes = null; // CPP + break starttagloop; + default: + errStrayStartTag(name); + break starttagloop; + } + case TEXT: + assert false; + break starttagloop; // Avoid infinite loop if the assertion + // fails + } + } + if (selfClosing) { + errSelfClosing(); + } + // CPPONLY: if (mBuilder == null && attributes != HtmlAttributes.EMPTY_ATTRIBUTES) { + // CPPONLY: Portability.delete(attributes); + // CPPONLY: } + } + + private void startTagTitleInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException { + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA, elementName); + } + + private void startTagGenericRawText(ElementName elementName, HtmlAttributes attributes) throws SAXException { + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation(Tokenizer.RAWTEXT, elementName); + } + + private void startTagScriptInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException { + // XXX need to manage much more stuff here if supporting document.write() + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer.setStateAndEndTagExpectation(Tokenizer.SCRIPT_DATA, elementName); + } + + private void startTagTemplateInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException { + appendToCurrentNodeAndPushElement(elementName, attributes); + insertMarker(); + framesetOk = false; + originalMode = mode; + mode = IN_TEMPLATE; + pushTemplateMode(IN_TEMPLATE); + } + + private boolean isTemplateContents() { + return TreeBuilder.NOT_FOUND_ON_STACK != findLast("template"); + } + + private boolean isTemplateModeStackEmpty() { + return templateModePtr == -1; + } + + private boolean isSpecialParentInForeign(StackNode<T> stackNode) { + @NsUri String ns = stackNode.ns; + return ("http://www.w3.org/1999/xhtml" == ns) + || (stackNode.isHtmlIntegrationPoint()) + || (("http://www.w3.org/1998/Math/MathML" == ns) && (stackNode.getGroup() == MI_MO_MN_MS_MTEXT)); + } + + /** + * + * <p> + * C++ memory note: The return value must be released. + * + * @return + * @throws SAXException + * @throws StopSniffingException + */ + public static String extractCharsetFromContent(String attributeValue + // CPPONLY: , TreeBuilder tb + ) { + // This is a bit ugly. Converting the string to char array in order to + // make the portability layer smaller. + int charsetState = CHARSET_INITIAL; + int start = -1; + int end = -1; + @Auto char[] buffer = Portability.newCharArrayFromString(attributeValue); + + charsetloop: for (int i = 0; i < buffer.length; i++) { + char c = buffer[i]; + switch (charsetState) { + case CHARSET_INITIAL: + switch (c) { + case 'c': + case 'C': + charsetState = CHARSET_C; + continue; + default: + continue; + } + case CHARSET_C: + switch (c) { + case 'h': + case 'H': + charsetState = CHARSET_H; + continue; + default: + charsetState = CHARSET_INITIAL; + continue; + } + case CHARSET_H: + switch (c) { + case 'a': + case 'A': + charsetState = CHARSET_A; + continue; + default: + charsetState = CHARSET_INITIAL; + continue; + } + case CHARSET_A: + switch (c) { + case 'r': + case 'R': + charsetState = CHARSET_R; + continue; + default: + charsetState = CHARSET_INITIAL; + continue; + } + case CHARSET_R: + switch (c) { + case 's': + case 'S': + charsetState = CHARSET_S; + continue; + default: + charsetState = CHARSET_INITIAL; + continue; + } + case CHARSET_S: + switch (c) { + case 'e': + case 'E': + charsetState = CHARSET_E; + continue; + default: + charsetState = CHARSET_INITIAL; + continue; + } + case CHARSET_E: + switch (c) { + case 't': + case 'T': + charsetState = CHARSET_T; + continue; + default: + charsetState = CHARSET_INITIAL; + continue; + } + case CHARSET_T: + switch (c) { + case '\t': + case '\n': + case '\u000C': + case '\r': + case ' ': + continue; + case '=': + charsetState = CHARSET_EQUALS; + continue; + default: + return null; + } + case CHARSET_EQUALS: + switch (c) { + case '\t': + case '\n': + case '\u000C': + case '\r': + case ' ': + continue; + case '\'': + start = i + 1; + charsetState = CHARSET_SINGLE_QUOTED; + continue; + case '\"': + start = i + 1; + charsetState = CHARSET_DOUBLE_QUOTED; + continue; + default: + start = i; + charsetState = CHARSET_UNQUOTED; + continue; + } + case CHARSET_SINGLE_QUOTED: + switch (c) { + case '\'': + end = i; + break charsetloop; + default: + continue; + } + case CHARSET_DOUBLE_QUOTED: + switch (c) { + case '\"': + end = i; + break charsetloop; + default: + continue; + } + case CHARSET_UNQUOTED: + switch (c) { + case '\t': + case '\n': + case '\u000C': + case '\r': + case ' ': + case ';': + end = i; + break charsetloop; + default: + continue; + } + } + } + if (start != -1) { + if (end == -1) { + if (charsetState == CHARSET_UNQUOTED) { + end = buffer.length; + } else { + return null; + } + } + return Portability.newStringFromBuffer(buffer, start, end + - start + // CPPONLY: , tb, false + ); + } + return null; + } + + private void checkMetaCharset(HtmlAttributes attributes) + throws SAXException { + String charset = attributes.getValue(AttributeName.CHARSET); + if (charset != null) { + if (tokenizer.internalEncodingDeclaration(charset)) { + requestSuspension(); + return; + } + return; + } + if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "content-type", + attributes.getValue(AttributeName.HTTP_EQUIV))) { + return; + } + String content = attributes.getValue(AttributeName.CONTENT); + if (content != null) { + String extract = TreeBuilder.extractCharsetFromContent(content + // CPPONLY: , this + ); + // remember not to return early without releasing the string + if (extract != null) { + if (tokenizer.internalEncodingDeclaration(extract)) { + requestSuspension(); + } + } + Portability.releaseString(extract); + } + } + + public final void endTag(ElementName elementName) throws SAXException { + flushCharacters(); + needToDropLF = false; + int eltPos; + int group = elementName.getGroup(); + @Local String name = elementName.getName(); + endtagloop: for (;;) { + if (isInForeign()) { + if (stack[currentPtr].name != name) { + if (currentPtr == 0) { + errStrayEndTag(name); + } else { + errEndTagDidNotMatchCurrentOpenElement(name, stack[currentPtr].popName); + } + } + eltPos = currentPtr; + int origPos = currentPtr; + for (;;) { + if (eltPos == 0) { + assert fragment: "We can get this close to the root of the stack in foreign content only in the fragment case."; + break endtagloop; + } + if (stack[eltPos].name == name) { + while (currentPtr >= eltPos) { + popForeign(origPos, eltPos); + } + break endtagloop; + } + if (stack[--eltPos].ns == "http://www.w3.org/1999/xhtml") { + break; + } + } + } + switch (mode) { + case IN_TEMPLATE: + switch (group) { + case TEMPLATE: + // fall through to IN_HEAD + break; + default: + errStrayEndTag(name); + break endtagloop; + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_ROW: + switch (group) { + case TR: + eltPos = findLastOrRoot(TreeBuilder.TR); + if (eltPos == 0) { + assert fragment || isTemplateContents(); + errNoTableRowToClose(); + break endtagloop; + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + break endtagloop; + case TABLE: + eltPos = findLastOrRoot(TreeBuilder.TR); + if (eltPos == 0) { + assert fragment || isTemplateContents(); + errNoTableRowToClose(); + break endtagloop; + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + continue; + case TBODY_OR_THEAD_OR_TFOOT: + if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + break endtagloop; + } + eltPos = findLastOrRoot(TreeBuilder.TR); + if (eltPos == 0) { + assert fragment || isTemplateContents(); + errNoTableRowToClose(); + break endtagloop; + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + continue; + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: + case TD_OR_TH: + errStrayEndTag(name); + break endtagloop; + default: + // fall through to IN_TABLE + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_TABLE_BODY: + switch (group) { + case TBODY_OR_THEAD_OR_TFOOT: + eltPos = findLastOrRoot(name); + if (eltPos == 0) { + errStrayEndTag(name); + break endtagloop; + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE; + break endtagloop; + case TABLE: + eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot(); + if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) { + assert fragment || isTemplateContents(); + errStrayEndTag(name); + break endtagloop; + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE; + continue; + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: + case TD_OR_TH: + case TR: + errStrayEndTag(name); + break endtagloop; + default: + // fall through to IN_TABLE + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_TABLE: + switch (group) { + case TABLE: + eltPos = findLast("table"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment || isTemplateContents(); + errStrayEndTag(name); + break endtagloop; + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + break endtagloop; + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case TR: + errStrayEndTag(name); + break endtagloop; + case TEMPLATE: + // fall through to IN_HEAD + break; + default: + errStrayEndTag(name); + // fall through to IN_BODY + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_CAPTION: + switch (group) { + case CAPTION: + eltPos = findLastInTableScope("caption"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + break endtagloop; + } + generateImpliedEndTags(); + if (errorHandler != null && currentPtr != eltPos) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_TABLE; + break endtagloop; + case TABLE: + eltPos = findLastInTableScope("caption"); + + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment || isTemplateContents(); + errStrayEndTag(name); + break endtagloop; + } + generateImpliedEndTags(); + if (errorHandler != null && currentPtr != eltPos) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_TABLE; + continue; + case BODY: + case COL: + case COLGROUP: + case HTML: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case TR: + errStrayEndTag(name); + break endtagloop; + default: + // fall through to IN_BODY + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_CELL: + switch (group) { + case TD_OR_TH: + eltPos = findLastInTableScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + break endtagloop; + } + generateImpliedEndTags(); + if (errorHandler != null && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_ROW; + break endtagloop; + case TABLE: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) { + assert name == "tbody" || name == "tfoot" || name == "thead" || fragment || isTemplateContents(); + errStrayEndTag(name); + break endtagloop; + } + closeTheCell(findLastInTableScopeTdTh()); + continue; + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: + errStrayEndTag(name); + break endtagloop; + default: + // fall through to IN_BODY + } + // CPPONLY: MOZ_FALLTHROUGH; + case FRAMESET_OK: + case IN_BODY: + switch (group) { + case BODY: + if (!isSecondOnStackBody()) { + assert fragment || isTemplateContents(); + errStrayEndTag(name); + break endtagloop; + } + assert currentPtr >= 1; + if (errorHandler != null) { + uncloseloop1: for (int i = 2; i <= currentPtr; i++) { + switch (stack[i].getGroup()) { + case DD_OR_DT: + case LI: + case OPTGROUP: + case OPTION: // is this possible? + case P: + case RB_OR_RTC: + case RT_OR_RP: + case TD_OR_TH: + case TBODY_OR_THEAD_OR_TFOOT: + break; + default: + errEndWithUnclosedElements(name); + break uncloseloop1; + } + } + } + mode = AFTER_BODY; + break endtagloop; + case HTML: + if (!isSecondOnStackBody()) { + assert fragment || isTemplateContents(); + errStrayEndTag(name); + break endtagloop; + } + if (errorHandler != null) { + uncloseloop2: for (int i = 0; i <= currentPtr; i++) { + switch (stack[i].getGroup()) { + case DD_OR_DT: + case LI: + case P: + case RB_OR_RTC: + case RT_OR_RP: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case BODY: + case HTML: + break; + default: + errEndWithUnclosedElements(name); + break uncloseloop2; + } + } + } + mode = AFTER_BODY; + continue; + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: + case UL_OR_OL_OR_DL: + case PRE_OR_LISTING: + case FIELDSET: + case BUTTON: + case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: + eltPos = findLastInScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + } else { + generateImpliedEndTags(); + if (errorHandler != null && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + break endtagloop; + case FORM: + if (!isTemplateContents()) { + if (formPointer == null) { + errStrayEndTag(name); + break endtagloop; + } + formPointer = null; + eltPos = findLastInScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + break endtagloop; + } + generateImpliedEndTags(); + if (errorHandler != null && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + removeFromStack(eltPos); + break endtagloop; + } else { + eltPos = findLastInScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + break endtagloop; + } + generateImpliedEndTags(); + if (errorHandler != null && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + break endtagloop; + } + case P: + eltPos = findLastInButtonScope("p"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errNoElementToCloseButEndTagSeen("p"); + // XXX Can the 'in foreign' case happen anymore? + if (isInForeign()) { + errHtmlStartTagInForeignContext(name); + // Check for currentPtr for the fragment + // case. + while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") { + pop(); + } + } + appendVoidElementToCurrentMayFoster( + elementName, + HtmlAttributes.EMPTY_ATTRIBUTES); + break endtagloop; + } + generateImpliedEndTagsExceptFor("p"); + assert eltPos != TreeBuilder.NOT_FOUND_ON_STACK; + if (errorHandler != null && eltPos != currentPtr) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + break endtagloop; + case LI: + eltPos = findLastInListScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errNoElementToCloseButEndTagSeen(name); + } else { + generateImpliedEndTagsExceptFor(name); + if (errorHandler != null + && eltPos != currentPtr) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + break endtagloop; + case DD_OR_DT: + eltPos = findLastInScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errNoElementToCloseButEndTagSeen(name); + } else { + generateImpliedEndTagsExceptFor(name); + if (errorHandler != null + && eltPos != currentPtr) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + break endtagloop; + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: + eltPos = findLastInScopeHn(); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + } else { + generateImpliedEndTags(); + if (errorHandler != null && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + break endtagloop; + case OBJECT: + case MARQUEE_OR_APPLET: + eltPos = findLastInScope(name); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + } else { + generateImpliedEndTags(); + if (errorHandler != null && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + } + break endtagloop; + case BR: + errEndTagBr(); + if (isInForeign()) { + // XXX can this happen anymore? + errHtmlStartTagInForeignContext(name); + // Check for currentPtr for the fragment + // case. + while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") { + pop(); + } + } + reconstructTheActiveFormattingElements(); + appendVoidElementToCurrentMayFoster( + elementName, + HtmlAttributes.EMPTY_ATTRIBUTES); + break endtagloop; + case TEMPLATE: + // fall through to IN_HEAD; + break; + case AREA_OR_WBR: + case KEYGEN: // XXX?? + case PARAM_OR_SOURCE_OR_TRACK: + case EMBED: + case IMG: + case IMAGE: + case INPUT: + case HR: + case IFRAME: + case NOEMBED: // XXX??? + case NOFRAMES: // XXX?? + case SELECT: + case TABLE: + case TEXTAREA: // XXX?? + errStrayEndTag(name); + break endtagloop; + case NOSCRIPT: + if (scriptingEnabled) { + errStrayEndTag(name); + break endtagloop; + } + // CPPONLY: MOZ_FALLTHROUGH; + case A: + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: + case FONT: + case NOBR: + if (adoptionAgencyEndTag(name)) { + break endtagloop; + } + // else handle like any other tag + // CPPONLY: MOZ_FALLTHROUGH; + default: + if (isCurrent(name)) { + pop(); + break endtagloop; + } + + eltPos = currentPtr; + for (;;) { + StackNode<T> node = stack[eltPos]; + if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) { + generateImpliedEndTags(); + if (errorHandler != null + && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + break endtagloop; + } else if (eltPos == 0 || node.isSpecial()) { + errStrayEndTag(name); + break endtagloop; + } + eltPos--; + } + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_HEAD: + switch (group) { + case HEAD: + pop(); + mode = AFTER_HEAD; + break endtagloop; + case BR: + case HTML: + case BODY: + pop(); + mode = AFTER_HEAD; + continue; + case TEMPLATE: + endTagTemplateInHead(); + break endtagloop; + default: + errStrayEndTag(name); + break endtagloop; + } + case IN_HEAD_NOSCRIPT: + switch (group) { + case NOSCRIPT: + pop(); + mode = IN_HEAD; + break endtagloop; + case BR: + errStrayEndTag(name); + pop(); + mode = IN_HEAD; + continue; + default: + errStrayEndTag(name); + break endtagloop; + } + case IN_COLUMN_GROUP: + switch (group) { + case COLGROUP: + if (currentPtr == 0 || stack[currentPtr].getGroup() == + TreeBuilder.TEMPLATE) { + assert fragment || isTemplateContents(); + errGarbageInColgroup(); + break endtagloop; + } + pop(); + mode = IN_TABLE; + break endtagloop; + case COL: + errStrayEndTag(name); + break endtagloop; + case TEMPLATE: + endTagTemplateInHead(); + break endtagloop; + default: + if (currentPtr == 0 || stack[currentPtr].getGroup() == + TreeBuilder.TEMPLATE) { + assert fragment || isTemplateContents(); + errGarbageInColgroup(); + break endtagloop; + } + pop(); + mode = IN_TABLE; + continue; + } + case IN_SELECT_IN_TABLE: + switch (group) { + case CAPTION: + case TABLE: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: + errEndTagSeenWithSelectOpen(name); + if (findLastInTableScope(name) != TreeBuilder.NOT_FOUND_ON_STACK) { + eltPos = findLastInTableScope("select"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment; + break endtagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375 + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + continue; + } else { + break endtagloop; + } + default: + // fall through to IN_SELECT + } + // CPPONLY: MOZ_FALLTHROUGH; + case IN_SELECT: + switch (group) { + case OPTION: + if (isCurrent("option")) { + pop(); + break endtagloop; + } else { + errStrayEndTag(name); + break endtagloop; + } + case OPTGROUP: + if (isCurrent("option") + && "optgroup" == stack[currentPtr - 1].name) { + pop(); + } + if (isCurrent("optgroup")) { + pop(); + } else { + errStrayEndTag(name); + } + break endtagloop; + case SELECT: + eltPos = findLastInTableScope("select"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + assert fragment; + errStrayEndTag(name); + break endtagloop; + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + break endtagloop; + case TEMPLATE: + endTagTemplateInHead(); + break endtagloop; + default: + errStrayEndTag(name); + break endtagloop; + } + case AFTER_BODY: + switch (group) { + case HTML: + if (fragment) { + errStrayEndTag(name); + break endtagloop; + } else { + mode = AFTER_AFTER_BODY; + break endtagloop; + } + default: + errEndTagAfterBody(); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + } + case IN_FRAMESET: + switch (group) { + case FRAMESET: + if (currentPtr == 0) { + assert fragment; + errStrayEndTag(name); + break endtagloop; + } + pop(); + if ((!fragment) && !isCurrent("frameset")) { + mode = AFTER_FRAMESET; + } + break endtagloop; + default: + errStrayEndTag(name); + break endtagloop; + } + case AFTER_FRAMESET: + switch (group) { + case HTML: + mode = AFTER_AFTER_FRAMESET; + break endtagloop; + default: + errStrayEndTag(name); + break endtagloop; + } + case INITIAL: + /* + * Parse error. + */ + errEndTagSeenWithoutDoctype(); + /* + * + * Set the document to quirks mode. + */ + documentModeInternal(DocumentMode.QUIRKS_MODE, null, null); + /* + * Then, switch to the root element mode of the tree + * construction stage + */ + mode = BEFORE_HTML; + /* + * and reprocess the current token. + */ + continue; + case BEFORE_HTML: + switch (group) { + case HEAD: + case BR: + case HTML: + case BODY: + /* + * Create an HTMLElement node with the tag name + * html, in the HTML namespace. Append it to the + * Document object. + */ + appendHtmlElementToDocumentAndPush(); + /* Switch to the main mode */ + mode = BEFORE_HEAD; + /* + * reprocess the current token. + */ + continue; + default: + errStrayEndTag(name); + break endtagloop; + } + case BEFORE_HEAD: + switch (group) { + case HEAD: + case BR: + case HTML: + case BODY: + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); + mode = IN_HEAD; + continue; + default: + errStrayEndTag(name); + break endtagloop; + } + case AFTER_HEAD: + switch (group) { + case TEMPLATE: + endTagTemplateInHead(); + break endtagloop; + case HTML: + case BODY: + case BR: + appendToCurrentNodeAndPushBodyElement(); + mode = FRAMESET_OK; + continue; + default: + errStrayEndTag(name); + break endtagloop; + } + case AFTER_AFTER_BODY: + errStrayEndTag(name); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + case AFTER_AFTER_FRAMESET: + errStrayEndTag(name); + break endtagloop; + case TEXT: + // XXX need to manage insertion point here + pop(); + if (originalMode == AFTER_HEAD) { + silentPop(); + } + mode = originalMode; + break endtagloop; + } + } // endtagloop + } + + private void endTagTemplateInHead() throws SAXException { + int eltPos = findLast("template"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + errStrayEndTag("template"); + return; + } + generateImpliedEndTagsThoroughly(); + if (errorHandler != null && !isCurrent("template")) { + errUnclosedElements(eltPos, "template"); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + popTemplateMode(); + resetTheInsertionMode(); + } + + private int findLastInTableScopeOrRootTemplateTbodyTheadTfoot() { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml" + && (stack[i].getGroup() == TreeBuilder.TBODY_OR_THEAD_OR_TFOOT + || stack[i].getGroup() == TreeBuilder.TEMPLATE)) { + return i; + } + } + return 0; + } + + private int findLast(@Local String name) { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) { + return i; + } + } + return TreeBuilder.NOT_FOUND_ON_STACK; + } + + private int findLastInTableScope(@Local String name) { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { + if (stack[i].name == name) { + return i; + } else if (stack[i].name == "table" || stack[i].name == "template") { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + } + return TreeBuilder.NOT_FOUND_ON_STACK; + } + + private int findLastInButtonScope(@Local String name) { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { + if (stack[i].name == name) { + return i; + } else if (stack[i].name == "button") { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + + if (stack[i].isScoping()) { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + return TreeBuilder.NOT_FOUND_ON_STACK; + } + + private int findLastInScope(@Local String name) { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) { + return i; + } else if (stack[i].isScoping()) { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + return TreeBuilder.NOT_FOUND_ON_STACK; + } + + private int findLastInListScope(@Local String name) { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { + if (stack[i].name == name) { + return i; + } else if (stack[i].name == "ul" || stack[i].name == "ol") { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + + if (stack[i].isScoping()) { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + return TreeBuilder.NOT_FOUND_ON_STACK; + } + + private int findLastInScopeHn() { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].getGroup() == TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) { + return i; + } else if (stack[i].isScoping()) { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + return TreeBuilder.NOT_FOUND_ON_STACK; + } + + private void generateImpliedEndTagsExceptFor(@Local String name) + throws SAXException { + for (;;) { + StackNode<T> node = stack[currentPtr]; + switch (node.getGroup()) { + case P: + case LI: + case DD_OR_DT: + case OPTION: + case OPTGROUP: + case RB_OR_RTC: + case RT_OR_RP: + if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) { + return; + } + pop(); + continue; + default: + return; + } + } + } + + private void generateImpliedEndTags() throws SAXException { + for (;;) { + switch (stack[currentPtr].getGroup()) { + case P: + case LI: + case DD_OR_DT: + case OPTION: + case OPTGROUP: + case RB_OR_RTC: + case RT_OR_RP: + pop(); + continue; + default: + return; + } + } + } + + private void generateImpliedEndTagsThoroughly() throws SAXException { + for (;;) { + switch (stack[currentPtr].getGroup()) { + case CAPTION: + case COLGROUP: + case DD_OR_DT: + case LI: + case OPTGROUP: + case OPTION: + case P: + case RB_OR_RTC: + case RT_OR_RP: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case TR: + pop(); + continue; + default: + return; + } + } + } + + private boolean isSecondOnStackBody() { + return currentPtr >= 1 && stack[1].getGroup() == TreeBuilder.BODY; + } + + private void documentModeInternal(DocumentMode m, String publicIdentifier, + String systemIdentifier) + throws SAXException { + + if (forceNoQuirks) { + // Srcdoc documents are always rendered in standards mode. + quirks = false; + if (documentModeHandler != null) { + documentModeHandler.documentMode( + DocumentMode.STANDARDS_MODE + // [NOCPP[ + , null, null + // ]NOCPP] + ); + } + return; + } + + quirks = (m == DocumentMode.QUIRKS_MODE); + if (documentModeHandler != null) { + documentModeHandler.documentMode( + m + // [NOCPP[ + , publicIdentifier, systemIdentifier + // ]NOCPP] + ); + } + // [NOCPP[ + documentMode(m, publicIdentifier, systemIdentifier); + // ]NOCPP] + } + + private boolean isAlmostStandards(String publicIdentifier, + String systemIdentifier) { + if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier)) { + return true; + } + if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier)) { + return true; + } + if (systemIdentifier != null) { + if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) { + return true; + } + if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) { + return true; + } + } + return false; + } + + private boolean isQuirky(@Local String name, String publicIdentifier, + String systemIdentifier, boolean forceQuirks) { + if (forceQuirks) { + return true; + } + if (name != HTML_LOCAL) { + return true; + } + if (publicIdentifier != null) { + for (int i = 0; i < TreeBuilder.QUIRKY_PUBLIC_IDS.length; i++) { + if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + TreeBuilder.QUIRKY_PUBLIC_IDS[i], publicIdentifier)) { + return true; + } + } + if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) + || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "-/w3c/dtd html 4.0 transitional/en", + publicIdentifier) + || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "html", publicIdentifier)) { + return true; + } + } + if (systemIdentifier == null) { + if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) { + return true; + } else if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) { + return true; + } + } else if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd", + systemIdentifier)) { + return true; + } + return false; + } + + private void closeTheCell(int eltPos) throws SAXException { + generateImpliedEndTags(); + if (errorHandler != null && eltPos != currentPtr) { + errUnclosedElementsCell(eltPos); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_ROW; + return; + } + + private int findLastInTableScopeTdTh() { + for (int i = currentPtr; i > 0; i--) { + @Local String name = stack[i].name; + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { + if ("td" == name || "th" == name) { + return i; + } else if (name == "table" || name == "template") { + return TreeBuilder.NOT_FOUND_ON_STACK; + } + } + } + return TreeBuilder.NOT_FOUND_ON_STACK; + } + + private void clearStackBackTo(int eltPos) throws SAXException { + int eltGroup = stack[eltPos].getGroup(); + while (currentPtr > eltPos) { // > not >= intentional + if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" + && stack[currentPtr].getGroup() == TEMPLATE + && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltPos == 0)) { + return; + } + pop(); + } + } + + private void resetTheInsertionMode() { + StackNode<T> node; + @Local String name; + @NsUri String ns; + for (int i = currentPtr; i >= 0; i--) { + node = stack[i]; + name = node.name; + ns = node.ns; + if (i == 0) { + if (!(contextNamespace == "http://www.w3.org/1999/xhtml" && (contextName == "td" || contextName == "th"))) { + if (fragment) { + // Make sure we are parsing a fragment otherwise the context element doesn't make sense. + name = contextName; + ns = contextNamespace; + } + } else { + mode = framesetOk ? FRAMESET_OK : IN_BODY; // XXX from Hixie's email + return; + } + } + if ("select" == name) { + int ancestorIndex = i; + while (ancestorIndex > 0) { + StackNode<T> ancestor = stack[ancestorIndex--]; + if ("http://www.w3.org/1999/xhtml" == ancestor.ns) { + if ("template" == ancestor.name) { + break; + } + if ("table" == ancestor.name) { + mode = IN_SELECT_IN_TABLE; + return; + } + } + } + mode = IN_SELECT; + return; + } else if ("td" == name || "th" == name) { + mode = IN_CELL; + return; + } else if ("tr" == name) { + mode = IN_ROW; + return; + } else if ("tbody" == name || "thead" == name || "tfoot" == name) { + mode = IN_TABLE_BODY; + return; + } else if ("caption" == name) { + mode = IN_CAPTION; + return; + } else if ("colgroup" == name) { + mode = IN_COLUMN_GROUP; + return; + } else if ("table" == name) { + mode = IN_TABLE; + return; + } else if ("http://www.w3.org/1999/xhtml" != ns) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + return; + } else if ("template" == name) { + assert templateModePtr >= 0; + mode = templateModeStack[templateModePtr]; + return; + } else if ("head" == name) { + if (name == contextName) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; // really + } else { + mode = IN_HEAD; + } + return; + } else if ("body" == name) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + return; + } else if ("frameset" == name) { + // TODO: Fragment case. Add error reporting. + mode = IN_FRAMESET; + return; + } else if ("html" == name) { + if (headPointer == null) { + // TODO: Fragment case. Add error reporting. + mode = BEFORE_HEAD; + } else { + mode = AFTER_HEAD; + } + return; + } else if (i == 0) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + return; + } + } + } + + /** + * @throws SAXException + * + */ + private void implicitlyCloseP() throws SAXException { + int eltPos = findLastInButtonScope("p"); + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { + return; + } + generateImpliedEndTagsExceptFor("p"); + if (errorHandler != null && eltPos != currentPtr) { + errUnclosedElementsImplied(eltPos, "p"); + } + while (currentPtr >= eltPos) { + pop(); + } + } + + private boolean debugOnlyClearLastStackSlot() { + stack[currentPtr] = null; + return true; + } + + private boolean debugOnlyClearLastListSlot() { + listOfActiveFormattingElements[listPtr] = null; + return true; + } + + private void pushTemplateMode(int mode) { + templateModePtr++; + if (templateModePtr == templateModeStack.length) { + int[] newStack = new int[templateModeStack.length + 64]; + System.arraycopy(templateModeStack, 0, newStack, 0, templateModeStack.length); + templateModeStack = newStack; + } + templateModeStack[templateModePtr] = mode; + } + + @SuppressWarnings("unchecked") private void push(StackNode<T> node) throws SAXException { + currentPtr++; + if (currentPtr == stack.length) { + StackNode<T>[] newStack = new StackNode[stack.length + 64]; + System.arraycopy(stack, 0, newStack, 0, stack.length); + stack = newStack; + } + stack[currentPtr] = node; + elementPushed(node.ns, node.popName, node.node); + } + + @SuppressWarnings("unchecked") private void silentPush(StackNode<T> node) throws SAXException { + currentPtr++; + if (currentPtr == stack.length) { + StackNode<T>[] newStack = new StackNode[stack.length + 64]; + System.arraycopy(stack, 0, newStack, 0, stack.length); + stack = newStack; + } + stack[currentPtr] = node; + } + + @SuppressWarnings("unchecked") private void append(StackNode<T> node) { + listPtr++; + if (listPtr == listOfActiveFormattingElements.length) { + StackNode<T>[] newList = new StackNode[listOfActiveFormattingElements.length + 64]; + System.arraycopy(listOfActiveFormattingElements, 0, newList, 0, + listOfActiveFormattingElements.length); + listOfActiveFormattingElements = newList; + } + listOfActiveFormattingElements[listPtr] = node; + } + + @Inline private void insertMarker() { + append(null); + } + + private void clearTheListOfActiveFormattingElementsUpToTheLastMarker() { + while (listPtr > -1) { + if (listOfActiveFormattingElements[listPtr] == null) { + --listPtr; + return; + } + listOfActiveFormattingElements[listPtr].release(this); + --listPtr; + } + } + + @Inline private boolean isCurrent(@Local String name) { + return stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" && + name == stack[currentPtr].name; + } + + private void removeFromStack(int pos) throws SAXException { + if (currentPtr == pos) { + pop(); + } else { + fatal(); + stack[pos].release(this); + System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos); + assert debugOnlyClearLastStackSlot(); + currentPtr--; + } + } + + private void removeFromStack(StackNode<T> node) throws SAXException { + if (stack[currentPtr] == node) { + pop(); + } else { + int pos = currentPtr - 1; + while (pos >= 0 && stack[pos] != node) { + pos--; + } + if (pos == -1) { + // dead code? + return; + } + fatal(); + node.release(this); + System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos); + currentPtr--; + } + } + + private void removeFromListOfActiveFormattingElements(int pos) { + assert listOfActiveFormattingElements[pos] != null; + listOfActiveFormattingElements[pos].release(this); + if (pos == listPtr) { + assert debugOnlyClearLastListSlot(); + listPtr--; + return; + } + assert pos < listPtr; + System.arraycopy(listOfActiveFormattingElements, pos + 1, + listOfActiveFormattingElements, pos, listPtr - pos); + assert debugOnlyClearLastListSlot(); + listPtr--; + } + + /** + * Adoption agency algorithm. + * + * @param name subject as described in the specified algorithm. + * @return Returns true if the algorithm has completed and there is nothing remaining to + * be done. Returns false if the algorithm needs to "act as described in the 'any other + * end tag' entry" as described in the specified algorithm. + * @throws SAXException + */ + private boolean adoptionAgencyEndTag(@Local String name) throws SAXException { + // This check intends to ensure that for properly nested tags, closing tags will match + // against the stack instead of the listOfActiveFormattingElements. + if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" && + stack[currentPtr].name == name && + findInListOfActiveFormattingElements(stack[currentPtr]) == -1) { + // If the current element matches the name but isn't on the list of active + // formatting elements, then it is possible that the list was mangled by the Noah's Ark + // clause. In this case, we want to match the end tag against the stack instead of + // proceeding with the AAA algorithm that may match against the list of + // active formatting elements (and possibly mangle the tree in unexpected ways). + pop(); + return true; + } + + // If you crash around here, perhaps some stack node variable claimed to + // be a weak ref isn't. + for (int i = 0; i < 8; ++i) { + int formattingEltListPos = listPtr; + while (formattingEltListPos > -1) { + StackNode<T> listNode = listOfActiveFormattingElements[formattingEltListPos]; // weak ref + if (listNode == null) { + formattingEltListPos = -1; + break; + } else if (listNode.name == name) { + break; + } + formattingEltListPos--; + } + if (formattingEltListPos == -1) { + return false; + } + // this *looks* like a weak ref to the list of formatting elements + StackNode<T> formattingElt = listOfActiveFormattingElements[formattingEltListPos]; + int formattingEltStackPos = currentPtr; + boolean inScope = true; + while (formattingEltStackPos > -1) { + StackNode<T> node = stack[formattingEltStackPos]; // weak ref + if (node == formattingElt) { + break; + } else if (node.isScoping()) { + inScope = false; + } + formattingEltStackPos--; + } + if (formattingEltStackPos == -1) { + errNoElementToCloseButEndTagSeen(name); + removeFromListOfActiveFormattingElements(formattingEltListPos); + return true; + } + if (!inScope) { + errNoElementToCloseButEndTagSeen(name); + return true; + } + // stackPos now points to the formatting element and it is in scope + if (formattingEltStackPos != currentPtr) { + errEndTagViolatesNestingRules(name); + } + int furthestBlockPos = formattingEltStackPos + 1; + while (furthestBlockPos <= currentPtr) { + StackNode<T> node = stack[furthestBlockPos]; // weak ref + assert furthestBlockPos > 0: "How is formattingEltStackPos + 1 not > 0?"; + if (node.isSpecial()) { + break; + } + furthestBlockPos++; + } + if (furthestBlockPos > currentPtr) { + // no furthest block + while (currentPtr >= formattingEltStackPos) { + pop(); + } + removeFromListOfActiveFormattingElements(formattingEltListPos); + return true; + } + // commonAncestor is used for running the algorithm and + // insertionCommonAncestor is used for the actual insertions to + // keep them depth-limited. + StackNode<T> commonAncestor = stack[formattingEltStackPos - 1]; // weak ref + T insertionCommonAncestor = nodeFromStackWithBlinkCompat(formattingEltStackPos - 1); // weak ref + StackNode<T> furthestBlock = stack[furthestBlockPos]; // weak ref + // detachFromParent(furthestBlock.node); XXX AAA CHANGE + int bookmark = formattingEltListPos; + int nodePos = furthestBlockPos; + StackNode<T> lastNode = furthestBlock; // weak ref + int j = 0; + for (;;) { + ++j; + nodePos--; + if (nodePos == formattingEltStackPos) { + break; + } + StackNode<T> node = stack[nodePos]; // weak ref + int nodeListPos = findInListOfActiveFormattingElements(node); + + if (j > 3 && nodeListPos != -1) { + removeFromListOfActiveFormattingElements(nodeListPos); + + // Adjust the indices into the list to account + // for the removal of nodeListPos. + if (nodeListPos <= formattingEltListPos) { + formattingEltListPos--; + } + if (nodeListPos <= bookmark) { + bookmark--; + } + + // Update position to reflect removal from list. + nodeListPos = -1; + } + + if (nodeListPos == -1) { + assert formattingEltStackPos < nodePos; + assert bookmark < nodePos; + assert furthestBlockPos > nodePos; + removeFromStack(nodePos); // node is now a bad pointer in C++ + furthestBlockPos--; + continue; + } + // now node is both on stack and in the list + if (nodePos == furthestBlockPos) { + bookmark = nodeListPos + 1; + } + // if (hasChildren(node.node)) { XXX AAA CHANGE + assert node == listOfActiveFormattingElements[nodeListPos]; + assert node == stack[nodePos]; + T clone = createElement("http://www.w3.org/1999/xhtml", + node.name, node.attributes.cloneAttributes(), insertionCommonAncestor + // CPPONLY: , htmlCreator(node.getHtmlCreator()) + ); + StackNode<T> newNode = createStackNode(node.getFlags(), node.ns, + node.name, clone, node.popName, node.attributes + // CPPONLY: , node.getHtmlCreator() + // [NOCPP[ + , node.getLocator() + // ]NOCPP] + ); // creation ownership goes to stack + node.dropAttributes(); // adopt ownership to newNode + stack[nodePos] = newNode; + newNode.retain(); // retain for list + listOfActiveFormattingElements[nodeListPos] = newNode; + node.release(this); // release from stack + node.release(this); // release from list + node = newNode; + // } XXX AAA CHANGE + detachFromParent(lastNode.node); + appendElement(lastNode.node, nodeFromStackWithBlinkCompat(nodePos)); + lastNode = node; + } + // If we insert into a foster parent, for simplicity, we insert + // accoding to the spec without Blink's depth limit. + if (commonAncestor.isFosterParenting()) { + fatal(); + detachFromParent(lastNode.node); + insertIntoFosterParent(lastNode.node); + } else { + detachFromParent(lastNode.node); + appendElement(lastNode.node, insertionCommonAncestor); + } + T clone = createElement("http://www.w3.org/1999/xhtml", + formattingElt.name, + formattingElt.attributes.cloneAttributes(), furthestBlock.node + // CPPONLY: , htmlCreator(formattingElt.getHtmlCreator()) + ); + StackNode<T> formattingClone = createStackNode( + formattingElt.getFlags(), formattingElt.ns, + formattingElt.name, clone, formattingElt.popName, + formattingElt.attributes + // CPPONLY: , formattingElt.getHtmlCreator() + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); // Ownership transfers to stack below + formattingElt.dropAttributes(); // transfer ownership to + // formattingClone + appendChildrenToNewParent(furthestBlock.node, clone); + appendElement(clone, furthestBlock.node); + removeFromListOfActiveFormattingElements(formattingEltListPos); + insertIntoListOfActiveFormattingElements(formattingClone, bookmark); + assert formattingEltStackPos < furthestBlockPos; + removeFromStack(formattingEltStackPos); + // furthestBlockPos is now off by one and points to the slot after + // it + insertIntoStack(formattingClone, furthestBlockPos); + } + return true; + } + + private void insertIntoStack(StackNode<T> node, int position) + throws SAXException { + assert currentPtr + 1 < stack.length; + assert position <= currentPtr + 1; + if (position == currentPtr + 1) { + push(node); + } else { + System.arraycopy(stack, position, stack, position + 1, + (currentPtr - position) + 1); + currentPtr++; + stack[position] = node; + } + } + + private void insertIntoListOfActiveFormattingElements( + StackNode<T> formattingClone, int bookmark) { + formattingClone.retain(); + assert listPtr + 1 < listOfActiveFormattingElements.length; + if (bookmark <= listPtr) { + System.arraycopy(listOfActiveFormattingElements, bookmark, + listOfActiveFormattingElements, bookmark + 1, + (listPtr - bookmark) + 1); + } + listPtr++; + listOfActiveFormattingElements[bookmark] = formattingClone; + } + + private int findInListOfActiveFormattingElements(StackNode<T> node) { + for (int i = listPtr; i >= 0; i--) { + if (node == listOfActiveFormattingElements[i]) { + return i; + } + } + return -1; + } + + private int findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker( + @Local String name) { + for (int i = listPtr; i >= 0; i--) { + StackNode<T> node = listOfActiveFormattingElements[i]; + if (node == null) { + return -1; + } else if (node.name == name) { + return i; + } + } + return -1; + } + + + private void maybeForgetEarlierDuplicateFormattingElement( + @Local String name, HtmlAttributes attributes) throws SAXException { + int candidate = -1; + int count = 0; + for (int i = listPtr; i >= 0; i--) { + StackNode<T> node = listOfActiveFormattingElements[i]; + if (node == null) { + break; + } + if (node.name == name && node.attributes.equalsAnother(attributes)) { + candidate = i; + ++count; + } + } + if (count >= 3) { + removeFromListOfActiveFormattingElements(candidate); + } + } + + private int findLastOrRoot(@Local String name) { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) { + return i; + } + } + return 0; + } + + private int findLastOrRoot(int group) { + for (int i = currentPtr; i > 0; i--) { + if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].getGroup() == group) { + return i; + } + } + return 0; + } + + /** + * Attempt to add attribute to the body element. + * @param attributes the attributes + * @return <code>true</code> iff the attributes were added + * @throws SAXException + */ + private boolean addAttributesToBody(HtmlAttributes attributes) + throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + if (currentPtr >= 1) { + StackNode<T> body = stack[1]; + if (body.getGroup() == TreeBuilder.BODY) { + addAttributesToElement(body.node, attributes); + return true; + } + } + return false; + } + + private void addAttributesToHtml(HtmlAttributes attributes) + throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + addAttributesToElement(stack[0].node, attributes); + } + + private void pushHeadPointerOntoStack() throws SAXException { + assert headPointer != null; + assert mode == AFTER_HEAD; + fatal(); + silentPush(createStackNode(ElementName.HEAD, headPointer + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + )); + } + + /** + * @throws SAXException + * + */ + private void reconstructTheActiveFormattingElements() throws SAXException { + if (listPtr == -1) { + return; + } + StackNode<T> mostRecent = listOfActiveFormattingElements[listPtr]; + if (mostRecent == null || isInStack(mostRecent)) { + return; + } + int entryPos = listPtr; + for (;;) { + entryPos--; + if (entryPos == -1) { + break; + } + if (listOfActiveFormattingElements[entryPos] == null) { + break; + } + if (isInStack(listOfActiveFormattingElements[entryPos])) { + break; + } + } + while (entryPos < listPtr) { + entryPos++; + StackNode<T> entry = listOfActiveFormattingElements[entryPos]; + StackNode<T> current = stack[currentPtr]; + + T clone; + if (current.isFosterParenting()) { + clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name, + entry.attributes.cloneAttributes() + // CPPONLY: , htmlCreator(entry.getHtmlCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + clone = createElement("http://www.w3.org/1999/xhtml", entry.name, + entry.attributes.cloneAttributes(), currentNode + // CPPONLY: , htmlCreator(entry.getHtmlCreator()) + ); + appendElement(clone, currentNode); + } + + StackNode<T> entryClone = createStackNode(entry.getFlags(), + entry.ns, entry.name, clone, entry.popName, + entry.attributes + // CPPONLY: , entry.getHtmlCreator() + // [NOCPP[ + , entry.getLocator() + // ]NOCPP] + ); + + entry.dropAttributes(); // transfer ownership to entryClone + + push(entryClone); + // stack takes ownership of the local variable + listOfActiveFormattingElements[entryPos] = entryClone; + // overwriting the old entry on the list, so release & retain + entry.release(this); + entryClone.retain(); + } + } + + void notifyUnusedStackNode(int idxInStackNodes) { + // stackNodesIdx is the earliest possible index of a stack node that might be unused, + // so update the index if necessary. + if (idxInStackNodes < stackNodesIdx) { + stackNodesIdx = idxInStackNodes; + } + } + + @SuppressWarnings("unchecked") private StackNode<T> getUnusedStackNode() { + // Search for an unused stack node. + while (stackNodesIdx < numStackNodes) { + if (stackNodes[stackNodesIdx].isUnused()) { + return stackNodes[stackNodesIdx++]; + } + stackNodesIdx++; + } + + if (stackNodesIdx < stackNodes.length) { + // No unused stack nodes, but there is still space in the storage array. + stackNodes[stackNodesIdx] = new StackNode<T>(stackNodesIdx); + numStackNodes++; + return stackNodes[stackNodesIdx++]; + } + + // Could not find an unused stack node and storage array is full. + StackNode<T>[] newStack = new StackNode[stackNodes.length + 64]; + System.arraycopy(stackNodes, 0, newStack, 0, stackNodes.length); + stackNodes = newStack; + + // Create a new stack node and return it. + stackNodes[stackNodesIdx] = new StackNode<T>(stackNodesIdx); + numStackNodes++; + return stackNodes[stackNodesIdx++]; + } + + private StackNode<T> createStackNode(int flags, @NsUri String ns, @Local String name, T node, + @Local String popName, HtmlAttributes attributes + // CPPONLY: , @HtmlCreator Object htmlCreator + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + StackNode<T> instance = getUnusedStackNode(); + instance.setValues(flags, ns, name, node, popName, attributes + // CPPONLY: , htmlCreator + // [NOCPP[ + , locator + // ]NOCPP] + ); + return instance; + } + + private StackNode<T> createStackNode(ElementName elementName, T node + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + StackNode<T> instance = getUnusedStackNode(); + instance.setValues(elementName, node + // [NOCPP[ + , locator + // ]NOCPP] + ); + return instance; + } + + private StackNode<T> createStackNode(ElementName elementName, T node, HtmlAttributes attributes + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + StackNode<T> instance = getUnusedStackNode(); + instance.setValues(elementName, node, attributes + // [NOCPP[ + , locator + // ]NOCPP] + ); + return instance; + } + + private StackNode<T> createStackNode(ElementName elementName, T node, @Local String popName + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + StackNode<T> instance = getUnusedStackNode(); + instance.setValues(elementName, node, popName + // [NOCPP[ + , locator + // ]NOCPP] + ); + return instance; + } + + private StackNode<T> createStackNode(ElementName elementName, @Local String popName, T node + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + StackNode<T> instance = getUnusedStackNode(); + instance.setValues(elementName, popName, node + // [NOCPP[ + , locator + // ]NOCPP] + ); + return instance; + } + + private StackNode<T> createStackNode(ElementName elementName, T node, @Local String popName, + boolean markAsIntegrationPoint + // [NOCPP[ + , TaintableLocatorImpl locator + // ]NOCPP] + ) { + StackNode<T> instance = getUnusedStackNode(); + instance.setValues(elementName, node, popName, markAsIntegrationPoint + // [NOCPP[ + , locator + // ]NOCPP] + ); + return instance; + } + + private void insertIntoFosterParent(T child) throws SAXException { + int tablePos = findLastOrRoot(TreeBuilder.TABLE); + int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE); + + if (templatePos >= tablePos) { + appendElement(child, stack[templatePos].node); + return; + } + + StackNode<T> node = stack[tablePos]; + insertFosterParentedChild(child, node.node, stack[tablePos - 1].node); + } + + private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name, + 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 + // 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 + // 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 + // CPPONLY: , creator + ); + } + + private boolean isInStack(StackNode<T> node) { + for (int i = currentPtr; i >= 0; i--) { + if (stack[i] == node) { + return true; + } + } + return false; + } + + private void popTemplateMode() { + templateModePtr--; + } + + private void pop() throws SAXException { + StackNode<T> node = stack[currentPtr]; + assert debugOnlyClearLastStackSlot(); + currentPtr--; + elementPopped(node.ns, node.popName, node.node); + node.release(this); + } + + private void popForeign(int origPos, int eltPos) throws SAXException { + StackNode<T> node = stack[currentPtr]; + if (origPos != currentPtr || eltPos != currentPtr) { + markMalformedIfScript(node.node); + } + assert debugOnlyClearLastStackSlot(); + currentPtr--; + elementPopped(node.ns, node.popName, node.node); + node.release(this); + } + + private void silentPop() throws SAXException { + StackNode<T> node = stack[currentPtr]; + assert debugOnlyClearLastStackSlot(); + currentPtr--; + node.release(this); + } + + private void popOnEof() throws SAXException { + StackNode<T> node = stack[currentPtr]; + assert debugOnlyClearLastStackSlot(); + currentPtr--; + markMalformedIfScript(node.node); + elementPopped(node.ns, node.popName, node.node); + node.release(this); + } + + // [NOCPP[ + private void checkAttributes(HtmlAttributes attributes, @NsUri String ns) + throws SAXException { + if (errorHandler != null) { + int len = attributes.getXmlnsLength(); + for (int i = 0; i < len; i++) { + AttributeName name = attributes.getXmlnsAttributeName(i); + if (name == AttributeName.XMLNS) { + String xmlns = attributes.getXmlnsValue(i); + if (!ns.equals(xmlns)) { + err("Bad value \u201C" + + xmlns + + "\u201D for the attribute \u201Cxmlns\u201D (only \u201C" + + ns + "\u201D permitted here)."); + switch (namePolicy) { + case ALTER_INFOSET: + // fall through + case ALLOW: + warn("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0."); + break; + case FATAL: + fatal("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0."); + break; + } + } + } else if (ns != "http://www.w3.org/1999/xhtml" + && name == AttributeName.XMLNS_XLINK) { + String xmlns = attributes.getXmlnsValue(i); + if (!"http://www.w3.org/1999/xlink".equals(xmlns)) { + err("Bad value \u201C" + + xmlns + + "\u201D for the attribute \u201Cxmlns:link\u201D (only \u201Chttp://www.w3.org/1999/xlink\u201D permitted here)."); + switch (namePolicy) { + case ALTER_INFOSET: + // fall through + case ALLOW: + warn("Attribute \u201Cxmlns:xlink\u201D with a value other than \u201Chttp://www.w3.org/1999/xlink\u201D is not serializable as XML 1.0 without changing document semantics."); + break; + case FATAL: + fatal("Attribute \u201Cxmlns:xlink\u201D with a value other than \u201Chttp://www.w3.org/1999/xlink\u201D is not serializable as XML 1.0 without changing document semantics."); + break; + } + } + } else { + err("Attribute \u201C" + attributes.getXmlnsLocalName(i) + + "\u201D not allowed here."); + switch (namePolicy) { + case ALTER_INFOSET: + // fall through + case ALLOW: + warn("Attribute with the local name \u201C" + + attributes.getXmlnsLocalName(i) + + "\u201D is not serializable as XML 1.0."); + break; + case FATAL: + fatal("Attribute with the local name \u201C" + + attributes.getXmlnsLocalName(i) + + "\u201D is not serializable as XML 1.0."); + break; + } + } + } + } + attributes.processNonNcNames(this, namePolicy); + } + + private String checkPopName(@Local String name) throws SAXException { + if (NCName.isNCName(name)) { + return name; + } else { + switch (namePolicy) { + case ALLOW: + warn("Element name \u201C" + name + + "\u201D cannot be represented as XML 1.0."); + return name; + case ALTER_INFOSET: + warn("Element name \u201C" + name + + "\u201D cannot be represented as XML 1.0."); + return NCName.escapeName(name); + case FATAL: + fatal("Element name \u201C" + name + + "\u201D cannot be represented as XML 1.0."); + } + } + return null; // keep compiler happy + } + + // ]NOCPP] + + private void appendHtmlElementToDocumentAndPush(HtmlAttributes attributes) + throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + T elt = createHtmlElementSetAsRoot(attributes); + StackNode<T> node = createStackNode(ElementName.HTML, + elt + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + private void appendHtmlElementToDocumentAndPush() throws SAXException { + appendHtmlElementToDocumentAndPush(tokenizer.emptyAttributes()); + } + + private void appendToCurrentNodeAndPushHeadElement(HtmlAttributes attributes) + throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + 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 = createStackNode(ElementName.HEAD, + elt + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + private void appendToCurrentNodeAndPushBodyElement(HtmlAttributes attributes) + throws SAXException { + appendToCurrentNodeAndPushElement(ElementName.BODY, + attributes); + } + + private void appendToCurrentNodeAndPushBodyElement() throws SAXException { + appendToCurrentNodeAndPushBodyElement(tokenizer.emptyAttributes()); + } + + private void appendToCurrentNodeAndPushFormElementMayFoster( + HtmlAttributes attributes) throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", "form", attributes + // CPPONLY: , htmlCreator(NS_NewHTMLFormElement) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, currentNode + // CPPONLY: , htmlCreator(NS_NewHTMLFormElement) + ); + appendElement(elt, currentNode); + } + + if (!isTemplateContents()) { + formPointer = elt; + } + + StackNode<T> node = createStackNode(ElementName.FORM, + elt + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + private void appendToCurrentNodeAndPushFormattingElementMayFoster( + ElementName elementName, HtmlAttributes attributes) + throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + // This method can't be called for custom elements + HtmlAttributes clone = attributes.cloneAttributes(); + // Attributes must not be read after calling createElement, because + // createElement may delete attributes in C++. + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, currentNode + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + appendElement(elt, currentNode); + } + StackNode<T> node = createStackNode(elementName, elt, clone + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + append(node); + node.retain(); // append doesn't retain itself + } + + private void appendToCurrentNodeAndPushElement(ElementName elementName, + HtmlAttributes attributes) + throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + // This method can't be called for custom elements + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + 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); + } + StackNode<T> node = createStackNode(elementName, elt + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName, + HtmlAttributes attributes) + throws SAXException { + @Local String popName = elementName.getName(); + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + if (!elementName.isInterned()) { + popName = checkPopName(popName); + } + // ]NOCPP] + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, currentNode + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + appendElement(elt, currentNode); + } + StackNode<T> node = createStackNode(elementName, elt, popName + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + private void appendToCurrentNodeAndPushElementMayFosterMathML( + ElementName elementName, HtmlAttributes attributes) + throws SAXException { + @Local String popName = elementName.getName(); + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML"); + if (!elementName.isInterned()) { + popName = checkPopName(popName); + } + // ]NOCPP] + boolean markAsHtmlIntegrationPoint = false; + if (ElementName.ANNOTATION_XML == elementName + && annotationXmlEncodingPermitsHtml(attributes)) { + markAsHtmlIntegrationPoint = true; + } + // Attributes must not be read after calling createElement(), since + // createElement may delete the object in C++. + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes + // CPPONLY: , htmlCreator(null) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, currentNode + // CPPONLY: , htmlCreator(null) + ); + appendElement(elt, currentNode); + } + StackNode<T> node = createStackNode(elementName, elt, popName, + markAsHtmlIntegrationPoint + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + // [NOCPP[ + T getDocumentFragmentForTemplate(T template) { + return template; + } + + T getFormPointerForContext(T context) { + return null; + } + // ]NOCPP] + + private boolean annotationXmlEncodingPermitsHtml(HtmlAttributes attributes) { + String encoding = attributes.getValue(AttributeName.ENCODING); + if (encoding == null) { + return false; + } + return Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "application/xhtml+xml", encoding) + || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "text/html", encoding); + } + + private void appendToCurrentNodeAndPushElementMayFosterSVG( + ElementName elementName, HtmlAttributes attributes) + throws SAXException { + @Local String popName = elementName.getCamelCaseName(); + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/2000/svg"); + if (!elementName.isInterned()) { + popName = checkPopName(popName); + } + // ]NOCPP] + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/2000/svg", popName, attributes, currentNode + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); + appendElement(elt, currentNode); + } + StackNode<T> node = createStackNode(elementName, popName, elt + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName, + HtmlAttributes attributes, T form) + throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + // Can't be called for custom elements + T elt; + T formOwner = form == null || fragment || isTemplateContents() ? null : form; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), + attributes, formOwner + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), + attributes, formOwner, currentNode + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + appendElement(elt, currentNode); + } + StackNode<T> node = createStackNode(elementName, elt + // [NOCPP[ + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) + // ]NOCPP] + ); + push(node); + } + + private void appendVoidElementToCurrentMayFoster( + ElementName elementName, HtmlAttributes attributes, T form) throws SAXException { + @Local String name = elementName.getName(); + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + // Can't be called for custom elements + T elt; + T formOwner = form == null || fragment || isTemplateContents() ? null : form; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", name, + attributes, formOwner + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1999/xhtml", name, + attributes, formOwner, currentNode + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + appendElement(elt, currentNode); + } + elementPushed("http://www.w3.org/1999/xhtml", name, elt); + elementPopped("http://www.w3.org/1999/xhtml", name, elt); + } + + private void appendVoidElementToCurrentMayFoster( + ElementName elementName, HtmlAttributes attributes) + throws SAXException { + @Local String popName = elementName.getName(); + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + if (!elementName.isInterned()) { + popName = checkPopName(popName); + } + // ]NOCPP] + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, currentNode + // CPPONLY: , htmlCreator(elementName.getHtmlCreator()) + ); + appendElement(elt, currentNode); + } + elementPushed("http://www.w3.org/1999/xhtml", popName, elt); + elementPopped("http://www.w3.org/1999/xhtml", popName, elt); + } + + private void appendVoidElementToCurrentMayFosterSVG( + ElementName elementName, HtmlAttributes attributes) + throws SAXException { + @Local String popName = elementName.getCamelCaseName(); + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/2000/svg"); + if (!elementName.isInterned()) { + popName = checkPopName(popName); + } + // ]NOCPP] + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/2000/svg", popName, attributes, currentNode + // CPPONLY: , svgCreator(elementName.getSvgCreator()) + ); + appendElement(elt, currentNode); + } + elementPushed("http://www.w3.org/2000/svg", popName, elt); + elementPopped("http://www.w3.org/2000/svg", popName, elt); + } + + private void appendVoidElementToCurrentMayFosterMathML( + ElementName elementName, HtmlAttributes attributes) + throws SAXException { + @Local String popName = elementName.getName(); + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML"); + if (!elementName.isInterned()) { + popName = checkPopName(popName); + } + // ]NOCPP] + T elt; + StackNode<T> current = stack[currentPtr]; + if (current.isFosterParenting()) { + fatal(); + elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes + // CPPONLY: , htmlCreator(null) + ); + } else { + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, currentNode + // CPPONLY: , htmlCreator(null) + ); + appendElement(elt, currentNode); + } + elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt); + elementPopped("http://www.w3.org/1998/Math/MathML", popName, elt); + } + + 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 = nodeFromStackWithBlinkCompat(currentPtr); + 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", "input", elt); + elementPopped("http://www.w3.org/1999/xhtml", "input", elt); + } + + private void appendVoidFormToCurrent(HtmlAttributes attributes) throws SAXException { + // [NOCPP[ + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); + // ]NOCPP] + T currentNode = nodeFromStackWithBlinkCompat(currentPtr); + T elt = createElement("http://www.w3.org/1999/xhtml", "form", + attributes, currentNode + // CPPONLY: , htmlCreator(NS_NewHTMLFormElement) + ); + formPointer = elt; + // ownership transferred to form pointer + appendElement(elt, currentNode); + elementPushed("http://www.w3.org/1999/xhtml", "form", elt); + elementPopped("http://www.w3.org/1999/xhtml", "form", elt); + } + + // [NOCPP[ + + private final void accumulateCharactersForced(@Const @NoLength char[] buf, + int start, int length) throws SAXException { + System.arraycopy(buf, start, charBuffer, charBufferLen, length); + charBufferLen += length; + } + + @Override public void ensureBufferSpace(int inputLength) + throws SAXException { + // TODO: Unify Tokenizer.strBuf and TreeBuilder.charBuffer so that + // this method becomes unnecessary. + int worstCase = charBufferLen + inputLength; + if (charBuffer == null) { + // Add an arbitrary small value to avoid immediate reallocation + // once there are a few characters in the buffer. + charBuffer = new char[worstCase + 128]; + } else if (worstCase > charBuffer.length) { + // HotSpot reportedly allocates memory with 8-byte accuracy, so + // there's no point in trying to do math here to avoid slop. + // Maybe we should add some small constant to worstCase here + // but not doing that without profiling. In C++ with jemalloc, + // the corresponding method should do math to round up here + // to avoid slop. + char[] newBuf = new char[worstCase]; + System.arraycopy(charBuffer, 0, newBuf, 0, charBufferLen); + charBuffer = newBuf; + } + } + + // ]NOCPP] + + protected void accumulateCharacters(@Const @NoLength char[] buf, int start, + int length) throws SAXException { + appendCharacters(stack[currentPtr].node, buf, start, length); + } + + // ------------------------------- // + + protected final void requestSuspension() { + tokenizer.requestSuspension(); + } + + protected abstract T createElement(@NsUri String ns, @Local String name, + 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 + // 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) + throws SAXException; + + protected abstract void detachFromParent(T element) throws SAXException; + + protected abstract boolean hasChildren(T element) throws SAXException; + + protected abstract void appendElement(T child, T newParent) + throws SAXException; + + protected abstract void appendChildrenToNewParent(T oldParent, T newParent) + throws SAXException; + + protected abstract void insertFosterParentedChild(T child, T table, + T stackParent) throws SAXException; + + // We don't generate CPP code for this method because it is not used in generated CPP + // code. Instead, the form owner version of this method is called with a null form owner. + // [NOCPP[ + + protected abstract T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name, + HtmlAttributes attributes, T table, T stackParent) throws SAXException; + + // ]NOCPP] + + protected T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name, + HtmlAttributes attributes, T form, T table, T stackParent + // CPPONLY: , @Creator Object creator + ) throws SAXException { + return createAndInsertFosterParentedElement(ns, name, attributes, table, stackParent); + }; + + protected abstract void insertFosterParentedCharacters( + @NoLength char[] buf, int start, int length, T table, T stackParent) + throws SAXException; + + protected abstract void appendCharacters(T parent, @NoLength char[] buf, + int start, int length) throws SAXException; + + protected abstract void appendComment(T parent, @NoLength char[] buf, + int start, int length) throws SAXException; + + protected abstract void appendCommentToDocument(@NoLength char[] buf, + int start, int length) throws SAXException; + + protected abstract void addAttributesToElement(T element, + HtmlAttributes attributes) throws SAXException; + + protected void markMalformedIfScript(T elt) throws SAXException { + + } + + protected void start(boolean fragmentMode) throws SAXException { + + } + + protected void end() throws SAXException { + + } + + protected void appendDoctypeToDocument(@Local String name, + String publicIdentifier, String systemIdentifier) + throws SAXException { + + } + + protected void elementPushed(@NsUri String ns, @Local String name, T node) + throws SAXException { + + } + + protected void elementPopped(@NsUri String ns, @Local String name, T node) + throws SAXException { + + } + + // [NOCPP[ + + protected void documentMode(DocumentMode m, String publicIdentifier, + String systemIdentifier) + throws SAXException { + + } + + /** + * @see nu.validator.htmlparser.common.TokenHandler#wantsComments() + */ + public boolean wantsComments() { + return wantingComments; + } + + public void setIgnoringComments(boolean ignoreComments) { + wantingComments = !ignoreComments; + } + + /** + * Sets the errorHandler. + * + * @param errorHandler + * the errorHandler to set + */ + public final void setErrorHandler(ErrorHandler errorHandler) { + this.errorHandler = errorHandler; + } + + /** + * Returns the errorHandler. + * + * @return the errorHandler + */ + public ErrorHandler getErrorHandler() { + return errorHandler; + } + + /** + * The argument MUST be an interned string or <code>null</code>. + * + * @param context + */ + public final void setFragmentContext(@Local String context) { + this.contextName = context; + this.contextNamespace = "http://www.w3.org/1999/xhtml"; + this.contextNode = null; + this.fragment = (contextName != null); + this.quirks = false; + } + + // ]NOCPP] + + /** + * @see nu.validator.htmlparser.common.TokenHandler#cdataSectionAllowed() + */ + @Inline public boolean cdataSectionAllowed() throws SAXException { + return isInForeign(); + } + + private boolean isInForeign() { + return currentPtr >= 0 + && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml"; + } + + private boolean isInForeignButNotHtmlOrMathTextIntegrationPoint() { + if (currentPtr < 0) { + return false; + } + return !isSpecialParentInForeign(stack[currentPtr]); + } + + /** + * The argument MUST be an interned string or <code>null</code>. + * + * @param context + */ + public final void setFragmentContext(@Local String context, + @NsUri String ns, T node, boolean quirks) { + // [NOCPP[ + if (!((context == null && ns == null) + || "http://www.w3.org/1999/xhtml" == ns + || "http://www.w3.org/2000/svg" == ns || "http://www.w3.org/1998/Math/MathML" == ns)) { + throw new IllegalArgumentException( + "The namespace must be the HTML, SVG or MathML namespace (or null when the local name is null). Got: " + + ns); + } + // ]NOCPP] + this.contextName = context; + this.contextNamespace = ns; + this.contextNode = node; + this.fragment = (contextName != null); + this.quirks = quirks; + } + + protected final T currentNode() { + return stack[currentPtr].node; + } + + /** + * Returns the scriptingEnabled. + * + * @return the scriptingEnabled + */ + public boolean isScriptingEnabled() { + return scriptingEnabled; + } + + /** + * Sets the scriptingEnabled. + * + * @param scriptingEnabled + * the scriptingEnabled to set + */ + public void setScriptingEnabled(boolean scriptingEnabled) { + this.scriptingEnabled = scriptingEnabled; + } + + public void setForceNoQuirks(boolean forceNoQuirks) { + this.forceNoQuirks = forceNoQuirks; + } + + // Redundant method retained because previously public. + public void setIsSrcdocDocument(boolean isSrcdocDocument) { + this.setForceNoQuirks(isSrcdocDocument); + } + + // [NOCPP[ + + public void setNamePolicy(XmlViolationPolicy namePolicy) { + this.namePolicy = namePolicy; + } + + /** + * Sets the documentModeHandler. + * + * @param documentModeHandler + * the documentModeHandler to set + */ + public void setDocumentModeHandler(DocumentModeHandler documentModeHandler) { + this.documentModeHandler = documentModeHandler; + } + + /** + * Sets the reportingDoctype. + * + * @param reportingDoctype + * the reportingDoctype to set + */ + public void setReportingDoctype(boolean reportingDoctype) { + this.reportingDoctype = reportingDoctype; + } + + // ]NOCPP] + + /** + * Flushes the pending characters. Public for document.write use cases only. + * @throws SAXException + */ + public final void flushCharacters() throws SAXException { + if (charBufferLen > 0) { + if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW) + && charBufferContainsNonWhitespace()) { + errNonSpaceInTable(); + reconstructTheActiveFormattingElements(); + if (!stack[currentPtr].isFosterParenting()) { + // reconstructing gave us a new current node + appendCharacters(currentNode(), charBuffer, 0, + charBufferLen); + charBufferLen = 0; + return; + } + + int tablePos = findLastOrRoot(TreeBuilder.TABLE); + int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE); + + if (templatePos >= tablePos) { + appendCharacters(stack[templatePos].node, charBuffer, 0, charBufferLen); + charBufferLen = 0; + return; + } + + StackNode<T> tableElt = stack[tablePos]; + insertFosterParentedCharacters(charBuffer, 0, charBufferLen, + tableElt.node, stack[tablePos - 1].node); + charBufferLen = 0; + return; + } + appendCharacters(currentNode(), charBuffer, 0, charBufferLen); + charBufferLen = 0; + } + } + + private boolean charBufferContainsNonWhitespace() { + for (int i = 0; i < charBufferLen; i++) { + switch (charBuffer[i]) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\u000C': + continue; + default: + return true; + } + } + return false; + } + + /** + * Creates a comparable snapshot of the tree builder state. Snapshot + * creation is only supported immediately after a script end tag has been + * processed. In C++ the caller is responsible for calling + * <code>delete</code> on the returned object. + * + * @return a snapshot. + * @throws SAXException + */ + @SuppressWarnings("unchecked") public TreeBuilderState<T> newSnapshot() + throws SAXException { + StackNode<T>[] listCopy = new StackNode[listPtr + 1]; + for (int i = 0; i < listCopy.length; i++) { + StackNode<T> node = listOfActiveFormattingElements[i]; + if (node != null) { + StackNode<T> newNode = new StackNode<T>(-1); + newNode.setValues(node.getFlags(), node.ns, + node.name, node.node, node.popName, + node.attributes.cloneAttributes() + // CPPONLY: , node.getHtmlCreator() + // [NOCPP[ + , node.getLocator() + // ]NOCPP] + ); + listCopy[i] = newNode; + } else { + listCopy[i] = null; + } + } + StackNode<T>[] stackCopy = new StackNode[currentPtr + 1]; + for (int i = 0; i < stackCopy.length; i++) { + StackNode<T> node = stack[i]; + int listIndex = findInListOfActiveFormattingElements(node); + if (listIndex == -1) { + StackNode<T> newNode = new StackNode<T>(-1); + newNode.setValues(node.getFlags(), node.ns, + node.name, node.node, node.popName, + null + // CPPONLY: , node.getHtmlCreator() + // [NOCPP[ + , node.getLocator() + // ]NOCPP] + ); + stackCopy[i] = newNode; + } else { + stackCopy[i] = listCopy[listIndex]; + stackCopy[i].retain(); + } + } + int[] templateModeStackCopy = new int[templateModePtr + 1]; + System.arraycopy(templateModeStack, 0, templateModeStackCopy, 0, + templateModeStackCopy.length); + return new StateSnapshot<T>(stackCopy, listCopy, templateModeStackCopy, formPointer, + headPointer, mode, originalMode, framesetOk, + needToDropLF, quirks); + } + + public boolean snapshotMatches(TreeBuilderState<T> snapshot) { + StackNode<T>[] stackCopy = snapshot.getStack(); + int stackLen = snapshot.getStackLength(); + StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements(); + int listLen = snapshot.getListOfActiveFormattingElementsLength(); + int[] templateModeStackCopy = snapshot.getTemplateModeStack(); + int templateModeStackLen = snapshot.getTemplateModeStackLength(); + + if (stackLen != currentPtr + 1 + || listLen != listPtr + 1 + || templateModeStackLen != templateModePtr + 1 + || formPointer != snapshot.getFormPointer() + || headPointer != snapshot.getHeadPointer() + || mode != snapshot.getMode() + || originalMode != snapshot.getOriginalMode() + || framesetOk != snapshot.isFramesetOk() + || needToDropLF != snapshot.isNeedToDropLF() + || quirks != snapshot.isQuirks()) { // maybe just assert quirks + return false; + } + for (int i = listLen - 1; i >= 0; i--) { + if (listCopy[i] == null + && listOfActiveFormattingElements[i] == null) { + continue; + } else if (listCopy[i] == null + || listOfActiveFormattingElements[i] == null) { + return false; + } + if (listCopy[i].node != listOfActiveFormattingElements[i].node) { + return false; // it's possible that this condition is overly + // strict + } + } + for (int i = stackLen - 1; i >= 0; i--) { + if (stackCopy[i].node != stack[i].node) { + return false; + } + } + for (int i = templateModeStackLen - 1; i >=0; i--) { + if (templateModeStackCopy[i] != templateModeStack[i]) { + return false; + } + } + return true; + } + + @SuppressWarnings("unchecked") public void loadState( + TreeBuilderState<T> snapshot) + throws SAXException { + // CPPONLY: mCurrentHtmlScriptIsAsyncOrDefer = false; + StackNode<T>[] stackCopy = snapshot.getStack(); + int stackLen = snapshot.getStackLength(); + StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements(); + int listLen = snapshot.getListOfActiveFormattingElementsLength(); + int[] templateModeStackCopy = snapshot.getTemplateModeStack(); + int templateModeStackLen = snapshot.getTemplateModeStackLength(); + + for (int i = 0; i <= listPtr; i++) { + if (listOfActiveFormattingElements[i] != null) { + listOfActiveFormattingElements[i].release(this); + } + } + if (listOfActiveFormattingElements.length < listLen) { + listOfActiveFormattingElements = new StackNode[listLen]; + } + listPtr = listLen - 1; + + for (int i = 0; i <= currentPtr; i++) { + stack[i].release(this); + } + if (stack.length < stackLen) { + stack = new StackNode[stackLen]; + } + currentPtr = stackLen - 1; + + if (templateModeStack.length < templateModeStackLen) { + templateModeStack = new int[templateModeStackLen]; + } + templateModePtr = templateModeStackLen - 1; + + for (int i = 0; i < listLen; i++) { + StackNode<T> node = listCopy[i]; + if (node != null) { + StackNode<T> newNode = createStackNode(node.getFlags(), node.ns, + node.name, node.node, + node.popName, + node.attributes.cloneAttributes() + // CPPONLY: , node.getHtmlCreator() + // [NOCPP[ + , node.getLocator() + // ]NOCPP] + ); + listOfActiveFormattingElements[i] = newNode; + } else { + listOfActiveFormattingElements[i] = null; + } + } + for (int i = 0; i < stackLen; i++) { + StackNode<T> node = stackCopy[i]; + int listIndex = findInArray(node, listCopy); + if (listIndex == -1) { + StackNode<T> newNode = createStackNode(node.getFlags(), node.ns, + node.name, node.node, + node.popName, + null + // CPPONLY: , node.getHtmlCreator() + // [NOCPP[ + , node.getLocator() + // ]NOCPP] + ); + stack[i] = newNode; + } else { + stack[i] = listOfActiveFormattingElements[listIndex]; + stack[i].retain(); + } + } + System.arraycopy(templateModeStackCopy, 0, templateModeStack, 0, templateModeStackLen); + formPointer = snapshot.getFormPointer(); + headPointer = snapshot.getHeadPointer(); + mode = snapshot.getMode(); + originalMode = snapshot.getOriginalMode(); + framesetOk = snapshot.isFramesetOk(); + needToDropLF = snapshot.isNeedToDropLF(); + quirks = snapshot.isQuirks(); + } + + private int findInArray(StackNode<T> node, StackNode<T>[] arr) { + for (int i = listPtr; i >= 0; i--) { + if (node == arr[i]) { + return i; + } + } + return -1; + } + + /** + * Returns <code>stack[stackPos].node</code> if <code>stackPos</code> is + * smaller than Blink's magic limit or the node at Blink's magic limit + * otherwise. + * + * In order to get Blink-compatible handling of excessive deeply-nested + * markup, this method must be used to obtain the node that is used as the + * parent node of an insertion. + * + * Blink's magic number is 512, but our counting is off by one compared to + * Blink's way of counting, so in order to get the same + * externally-observable outcome, we use 511 as our magic number. + * + * @param stackPos the stack position to attempt to read + * @return node at the position capped to Blink's magic number + * @throws SAXException + */ + private T nodeFromStackWithBlinkCompat(int stackPos) throws SAXException { + // Magic number if off by one relative to Blink's magic number, but the + // outcome is the same, because the counting is different by one. + if (stackPos > 511) { + errDeepTree(); + return stack[511].node; + } + return stack[stackPos].node; + } + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getFormPointer() + */ + @Override + public T getFormPointer() { + return formPointer; + } + + /** + * Returns the headPointer. + * + * @return the headPointer + */ + @Override + public T getHeadPointer() { + return headPointer; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElements() + */ + @Override + public StackNode<T>[] getListOfActiveFormattingElements() { + return listOfActiveFormattingElements; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getStack() + */ + @Override + public StackNode<T>[] getStack() { + return stack; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStack() + */ + @Override + public int[] getTemplateModeStack() { + return templateModeStack; + } + + /** + * Returns the mode. + * + * @return the mode + */ + @Override + public int getMode() { + return mode; + } + + /** + * Returns the originalMode. + * + * @return the originalMode + */ + @Override + public int getOriginalMode() { + return originalMode; + } + + /** + * Returns the framesetOk. + * + * @return the framesetOk + */ + @Override + public boolean isFramesetOk() { + return framesetOk; + } + + /** + * Returns the needToDropLF. + * + * @return the needToDropLF + */ + @Override + public boolean isNeedToDropLF() { + return needToDropLF; + } + + /** + * Returns the quirks. + * + * @return the quirks + */ + @Override + public boolean isQuirks() { + return quirks; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElementsLength() + */ + @Override + public int getListOfActiveFormattingElementsLength() { + return listPtr + 1; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getStackLength() + */ + @Override + public int getStackLength() { + return currentPtr + 1; + } + + /** + * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStackLength() + */ + @Override + public int getTemplateModeStackLength() { + return templateModePtr + 1; + } + + /** + * Complains about an over-deep tree. Theoretically this should just be + * a warning, but in practice authors should take this as an error. + * + * @throws SAXException + */ + private void errDeepTree() throws SAXException { + err("The document tree is more than 513 elements deep, which causes Firefox and Chrome to flatten the tree."); + } + + /** + * Reports a stray start tag. + * @param name the name of the stray tag + * + * @throws SAXException + */ + private void errStrayStartTag(@Local String name) throws SAXException { + err("Stray start tag \u201C" + name + "\u201D."); + } + + /** + * Reports a stray end tag. + * @param name the name of the stray tag + * + * @throws SAXException + */ + private void errStrayEndTag(@Local String name) throws SAXException { + err("Stray end tag \u201C" + name + "\u201D."); + } + + /** + * Reports a state when elements expected to be closed were not. + * + * @param eltPos the position of the start tag on the stack of the element + * being closed. + * @param name the name of the end tag + * + * @throws SAXException + */ + private void errUnclosedElements(int eltPos, @Local String name) throws SAXException { + errNoCheck("End tag \u201C" + name + "\u201D seen, but there were open elements."); + errListUnclosedStartTags(eltPos); + } + + /** + * Reports a state when elements expected to be closed ahead of an implied + * end tag but were not. + * + * @param eltPos the position of the start tag on the stack of the element + * being closed. + * @param name the name of the end tag + * + * @throws SAXException + */ + private void errUnclosedElementsImplied(int eltPos, String name) throws SAXException { + errNoCheck("End tag \u201C" + name + "\u201D implied, but there were open elements."); + errListUnclosedStartTags(eltPos); + } + + /** + * Reports a state when elements expected to be closed ahead of an implied + * table cell close. + * + * @param eltPos the position of the start tag on the stack of the element + * being closed. + * @throws SAXException + */ + private void errUnclosedElementsCell(int eltPos) throws SAXException { + errNoCheck("A table cell was implicitly closed, but there were open elements."); + errListUnclosedStartTags(eltPos); + } + + private void errStrayDoctype() throws SAXException { + err("Stray doctype."); + } + + private void errAlmostStandardsDoctype() throws SAXException { + if (!forceNoQuirks) { + err("Almost standards mode doctype. Expected \u201C<!DOCTYPE html>\u201D."); + } + } + + private void errQuirkyDoctype() throws SAXException { + if (!forceNoQuirks) { + err("Quirky doctype. Expected \u201C<!DOCTYPE html>\u201D."); + } + } + + private void errNonSpaceInTrailer() throws SAXException { + err("Non-space character in page trailer."); + } + + private void errNonSpaceAfterFrameset() throws SAXException { + err("Non-space after \u201Cframeset\u201D."); + } + + private void errNonSpaceInFrameset() throws SAXException { + err("Non-space in \u201Cframeset\u201D."); + } + + private void errNonSpaceAfterBody() throws SAXException { + err("Non-space character after body."); + } + + private void errNonSpaceInColgroupInFragment() throws SAXException { + err("Non-space in \u201Ccolgroup\u201D when parsing fragment."); + } + + private void errNonSpaceInNoscriptInHead() throws SAXException { + err("Non-space character inside \u201Cnoscript\u201D inside \u201Chead\u201D."); + } + + private void errFooBetweenHeadAndBody(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("\u201C" + name + "\u201D element between \u201Chead\u201D and \u201Cbody\u201D."); + } + + private void errStartTagWithoutDoctype() throws SAXException { + if (!forceNoQuirks) { + err("Start tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); + } + } + + private void errNoSelectInTableScope() throws SAXException { + err("No \u201Cselect\u201D in table scope."); + } + + private void errStartSelectWhereEndSelectExpected() throws SAXException { + err("\u201Cselect\u201D start tag where end tag expected."); + } + + private void errStartTagWithSelectOpen(@Local String name) + throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("\u201C" + name + + "\u201D start tag with \u201Cselect\u201D open."); + } + + private void errBadStartTagInNoscriptInHead(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("Bad start tag in \u201C" + name + + "\u201D in \u201Cnoscript\u201D in \u201Chead\u201D."); + } + + private void errImage() throws SAXException { + err("Saw a start tag \u201Cimage\u201D."); + } + + private void errFooSeenWhenFooOpen(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("Start tag \u201C" + name + "\u201D seen but an element of the same type was already open."); + } + + private void errHeadingWhenHeadingOpen() throws SAXException { + err("Heading cannot be a child of another heading."); + } + + private void errFramesetStart() throws SAXException { + err("\u201Cframeset\u201D start tag seen."); + } + + private void errNoCellToClose() throws SAXException { + err("No cell to close."); + } + + private void errStartTagInTable(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("Start tag \u201C" + name + + "\u201D seen in \u201Ctable\u201D."); + } + + private void errFormWhenFormOpen() throws SAXException { + err("Saw a \u201Cform\u201D start tag, but there was already an active \u201Cform\u201D element. Nested forms are not allowed. Ignoring the tag."); + } + + private void errTableSeenWhileTableOpen() throws SAXException { + err("Start tag for \u201Ctable\u201D seen but the previous \u201Ctable\u201D is still open."); + } + + private void errStartTagInTableBody(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("\u201C" + name + "\u201D start tag in table body."); + } + + private void errEndTagSeenWithoutDoctype() throws SAXException { + if (!forceNoQuirks) { + err("End tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); + } + } + + private void errEndTagAfterBody() throws SAXException { + err("Saw an end tag after \u201Cbody\u201D had been closed."); + } + + private void errEndTagSeenWithSelectOpen(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("\u201C" + name + + "\u201D end tag with \u201Cselect\u201D open."); + } + + private void errGarbageInColgroup() throws SAXException { + err("Garbage in \u201Ccolgroup\u201D fragment."); + } + + private void errEndTagBr() throws SAXException { + err("End tag \u201Cbr\u201D."); + } + + private void errNoElementToCloseButEndTagSeen(@Local String name) + throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("No \u201C" + name + "\u201D element in scope but a \u201C" + + name + "\u201D end tag seen."); + } + + private void errHtmlStartTagInForeignContext(@Local String name) + throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("HTML start tag \u201C" + name + + "\u201D in a foreign namespace context."); + } + + private void errNoTableRowToClose() throws SAXException { + err("No table row to close."); + } + + private void errNonSpaceInTable() throws SAXException { + err("Misplaced non-space characters inside a table."); + } + + private void errUnclosedChildrenInRuby() throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("Unclosed children in \u201Cruby\u201D."); + } + + private void errStartTagSeenWithoutRuby(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("Start tag \u201C" + + name + + "\u201D seen without a \u201Cruby\u201D element being open."); + } + + private void errSelfClosing() throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("Self-closing syntax (\u201C/>\u201D) used on a non-void HTML element. Ignoring the slash and treating as a start tag."); + } + + private void errNoCheckUnclosedElementsOnStack() throws SAXException { + errNoCheck("Unclosed elements on stack."); + } + + private void errEndTagDidNotMatchCurrentOpenElement(@Local String name, + @Local String currOpenName) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("End tag \u201C" + + name + + "\u201D did not match the name of the current open element (\u201C" + + currOpenName + "\u201D)."); + } + + private void errEndTagViolatesNestingRules(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("End tag \u201C" + name + "\u201D violates nesting rules."); + } + + private void errEofWithUnclosedElements() throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("End of file seen and there were open elements."); + // just report all remaining unclosed elements + errListUnclosedStartTags(0); + } + + /** + * Reports arriving at/near end of document with unclosed elements remaining. + * + * @param message + * the message + * @throws SAXException + */ + private void errEndWithUnclosedElements(@Local String name) throws SAXException { + if (errorHandler == null) { + return; + } + errNoCheck("End tag for \u201C" + + name + + "\u201D seen, but there were unclosed elements."); + // just report all remaining unclosed elements + errListUnclosedStartTags(0); + } +} diff --git a/parser/html/javasrc/UTF16Buffer.java b/parser/html/javasrc/UTF16Buffer.java new file mode 100644 index 0000000000..ec79185ec2 --- /dev/null +++ b/parser/html/javasrc/UTF16Buffer.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2008-2010 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. + */ + +package nu.validator.htmlparser.impl; + +import nu.validator.htmlparser.annotation.NoLength; + +/** + * An UTF-16 buffer that knows the start and end indeces of its unconsumed + * content. + * + * @version $Id$ + * @author hsivonen + */ +public final class UTF16Buffer { + + /** + * The backing store of the buffer. May be larger than the logical content + * of this <code>UTF16Buffer</code>. + */ + private final @NoLength char[] buffer; + + /** + * The index of the first unconsumed character in the backing buffer. + */ + private int start; + + /** + * The index of the slot immediately after the last character in the backing + * buffer that is part of the logical content of this + * <code>UTF16Buffer</code>. + */ + private int end; + + //[NOCPP[ + + /** + * Constructor for wrapping an existing UTF-16 code unit array. + * + * @param buffer + * the backing buffer + * @param start + * the index of the first character to consume + * @param end + * the index immediately after the last character to consume + */ + public UTF16Buffer(@NoLength char[] buffer, int start, int end) { + this.buffer = buffer; + this.start = start; + this.end = end; + } + + // ]NOCPP] + + /** + * Returns the start index. + * + * @return the start index + */ + public int getStart() { + return start; + } + + /** + * Sets the start index. + * + * @param start + * the start index + */ + public void setStart(int start) { + this.start = start; + } + + /** + * Returns the backing buffer. + * + * @return the backing buffer + */ + public @NoLength char[] getBuffer() { + return buffer; + } + + /** + * Returns the end index. + * + * @return the end index + */ + public int getEnd() { + return end; + } + + /** + * Checks if the buffer has data left. + * + * @return <code>true</code> if there's data left + */ + public boolean hasMore() { + return start < end; + } + + /** + * Returns <code>end - start</code>. + * + * @return <code>end - start</code> + */ + public int getLength() { + return end - start; + } + + /** + * Adjusts the start index to skip over the first character if it is a line + * feed and the previous character was a carriage return. + * + * @param lastWasCR + * whether the previous character was a carriage return + */ + public void adjust(boolean lastWasCR) { + if (lastWasCR && buffer[start] == '\n') { + start++; + } + } + + /** + * Sets the end index. + * + * @param end + * the end index + */ + public void setEnd(int end) { + this.end = end; + } +} diff --git a/parser/html/moz.build b/parser/html/moz.build new file mode 100644 index 0000000000..12fe8c8ada --- /dev/null +++ b/parser/html/moz.build @@ -0,0 +1,92 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +XPIDL_SOURCES += ["nsIParserUtils.idl"] + +XPIDL_MODULE = "html5" + +EXPORTS += [ + "jArray.h", + "nsAHtml5TreeBuilderState.h", + "nsAHtml5TreeOpSink.h", + "nsHtml5ArrayCopy.h", + "nsHtml5AtomTable.h", + "nsHtml5AttributeEntry.h", + "nsHtml5AttributeName.h", + "nsHtml5ByteReadable.h", + "nsHtml5ContentCreatorFunction.h", + "nsHtml5DependentUTF16Buffer.h", + "nsHtml5DocumentBuilder.h", + "nsHtml5DocumentMode.h", + "nsHtml5HtmlAttributes.h", + "nsHtml5Macros.h", + "nsHtml5Module.h", + "nsHtml5NamedCharacters.h", + "nsHtml5NamedCharactersAccel.h", + "nsHtml5OplessBuilder.h", + "nsHtml5OwningUTF16Buffer.h", + "nsHtml5Parser.h", + "nsHtml5PlainTextUtils.h", + "nsHtml5Portability.h", + "nsHtml5Speculation.h", + "nsHtml5SpeculativeLoad.h", + "nsHtml5StreamListener.h", + "nsHtml5StreamParser.h", + "nsHtml5StreamParserPtr.h", + "nsHtml5StreamParserReleaser.h", + "nsHtml5String.h", + "nsHtml5StringParser.h", + "nsHtml5SVGLoadDispatcher.h", + "nsHtml5TreeOperation.h", + "nsHtml5TreeOpExecutor.h", + "nsHtml5TreeOpStage.h", + "nsHtml5UTF16Buffer.h", + "nsHtml5UTF16BufferHSupplement.h", + "nsHtml5ViewSourceUtils.h", + "nsIContentHandle.h", + "nsParserUtils.h", +] + +UNIFIED_SOURCES += [ + "nsHtml5AtomTable.cpp", + "nsHtml5AttributeName.cpp", + "nsHtml5DependentUTF16Buffer.cpp", + "nsHtml5DocumentBuilder.cpp", + "nsHtml5ElementName.cpp", + "nsHtml5Highlighter.cpp", + "nsHtml5HtmlAttributes.cpp", + "nsHtml5Module.cpp", + "nsHtml5NamedCharacters.cpp", + "nsHtml5NamedCharactersAccel.cpp", + "nsHtml5OplessBuilder.cpp", + "nsHtml5OwningUTF16Buffer.cpp", + "nsHtml5Parser.cpp", + "nsHtml5PlainTextUtils.cpp", + "nsHtml5Portability.cpp", + "nsHtml5Speculation.cpp", + "nsHtml5SpeculativeLoad.cpp", + "nsHtml5StackNode.cpp", + "nsHtml5StateSnapshot.cpp", + "nsHtml5StreamListener.cpp", + "nsHtml5StreamParser.cpp", + "nsHtml5String.cpp", + "nsHtml5StringParser.cpp", + "nsHtml5SVGLoadDispatcher.cpp", + "nsHtml5Tokenizer.cpp", + "nsHtml5TreeBuilder.cpp", + "nsHtml5TreeOperation.cpp", + "nsHtml5TreeOpExecutor.cpp", + "nsHtml5TreeOpStage.cpp", + "nsHtml5UTF16Buffer.cpp", + "nsHtml5ViewSourceUtils.cpp", + "nsParserUtils.cpp", +] + +FINAL_LIBRARY = "xul" + +LOCAL_INCLUDES += [ + "/dom/base", +] diff --git a/parser/html/nsAHtml5TreeBuilderState.h b/parser/html/nsAHtml5TreeBuilderState.h new file mode 100644 index 0000000000..0de332b93c --- /dev/null +++ b/parser/html/nsAHtml5TreeBuilderState.h @@ -0,0 +1,52 @@ +/* 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/. */ + +#ifndef nsAHtml5TreeBuilderState_h +#define nsAHtml5TreeBuilderState_h + +#include <cstdint> +#include "nsIContentHandle.h" + +template <class T, class L> +class jArray; +class nsHtml5StackNode; + +/** + * Interface for exposing the internal state of the HTML5 tree builder. + * For more documentation, please see + * https://hg.mozilla.org/projects/htmlparser/file/tip/src/nu/validator/htmlparser/impl/StateSnapshot.java + */ +class nsAHtml5TreeBuilderState { + public: + virtual jArray<nsHtml5StackNode*, int32_t> getStack() = 0; + + virtual jArray<nsHtml5StackNode*, int32_t> + getListOfActiveFormattingElements() = 0; + + virtual jArray<int32_t, int32_t> getTemplateModeStack() = 0; + + virtual int32_t getStackLength() = 0; + + virtual int32_t getListOfActiveFormattingElementsLength() = 0; + + virtual int32_t getTemplateModeStackLength() = 0; + + virtual nsIContentHandle* getFormPointer() = 0; + + virtual nsIContentHandle* getHeadPointer() = 0; + + virtual int32_t getMode() = 0; + + virtual int32_t getOriginalMode() = 0; + + virtual bool isFramesetOk() = 0; + + virtual bool isNeedToDropLF() = 0; + + virtual bool isQuirks() = 0; + + virtual ~nsAHtml5TreeBuilderState() {} +}; + +#endif /* nsAHtml5TreeBuilderState_h */ diff --git a/parser/html/nsAHtml5TreeOpSink.h b/parser/html/nsAHtml5TreeOpSink.h new file mode 100644 index 0000000000..a09971a2e8 --- /dev/null +++ b/parser/html/nsAHtml5TreeOpSink.h @@ -0,0 +1,29 @@ +/* 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/. */ + +#ifndef nsAHtml5TreeOpSink_h +#define nsAHtml5TreeOpSink_h + +#include "nsTArrayForwardDeclare.h" + +class nsHtml5TreeOperation; + +/** + * The purpose of this interface is to connect a tree op executor + * (main-thread case), a tree op stage (non-speculative off-the-main-thread + * case) or a speculation (speculative case). + */ +class nsAHtml5TreeOpSink { + public: + /** + * Flush the operations from the tree operations from the argument + * queue into this sink unconditionally. + * + * Returns `true` on success and `false` on OOM. + */ + [[nodiscard]] virtual bool MoveOpsFrom( + nsTArray<nsHtml5TreeOperation>& aOpQueue) = 0; +}; + +#endif /* nsAHtml5TreeOpSink_h */ diff --git a/parser/html/nsHtml5ArrayCopy.h b/parser/html/nsHtml5ArrayCopy.h new file mode 100644 index 0000000000..78c2d9c1b3 --- /dev/null +++ b/parser/html/nsHtml5ArrayCopy.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008 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. + */ + +#ifndef nsHtml5ArrayCopy_h +#define nsHtml5ArrayCopy_h + +class nsHtml5StackNode; + +// Unfortunately, these don't work as template functions because the arguments +// would need coercion from a template class, which complicates things. +class nsHtml5ArrayCopy { + public: + static inline void arraycopy(char16_t* source, int32_t sourceOffset, + char16_t* target, int32_t targetOffset, + int32_t length) { + memcpy(&(target[targetOffset]), &(source[sourceOffset]), + size_t(length) * sizeof(char16_t)); + } + + static inline void arraycopy(char16_t* source, char16_t* target, + int32_t length) { + memcpy(target, source, size_t(length) * sizeof(char16_t)); + } + + static inline void arraycopy(int32_t* source, int32_t* target, + int32_t length) { + memcpy(target, source, size_t(length) * sizeof(int32_t)); + } + + static inline void arraycopy(nsHtml5StackNode** source, + nsHtml5StackNode** target, int32_t length) { + memcpy(target, source, size_t(length) * sizeof(nsHtml5StackNode*)); + } + + static inline void arraycopy(nsHtml5StackNode** arr, int32_t sourceOffset, + int32_t targetOffset, int32_t length) { + memmove(&(arr[targetOffset]), &(arr[sourceOffset]), + size_t(length) * sizeof(nsHtml5StackNode*)); + } +}; +#endif // nsHtml5ArrayCopy_h diff --git a/parser/html/nsHtml5AtomTable.cpp b/parser/html/nsHtml5AtomTable.cpp new file mode 100644 index 0000000000..06bad88bf4 --- /dev/null +++ b/parser/html/nsHtml5AtomTable.cpp @@ -0,0 +1,32 @@ +/* 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/. */ + +#include "nsHtml5AtomTable.h" +#include "nsThreadUtils.h" + +nsHtml5AtomTable::nsHtml5AtomTable() : mRecentlyUsedParserAtoms{} { +#ifdef DEBUG + mPermittedLookupEventTarget = mozilla::GetCurrentSerialEventTarget(); +#endif +} + +nsHtml5AtomTable::~nsHtml5AtomTable() {} + +nsAtom* nsHtml5AtomTable::GetAtom(const nsAString& aKey) { +#ifdef DEBUG + MOZ_ASSERT(mPermittedLookupEventTarget->IsOnCurrentThread()); +#endif + + uint32_t index = mozilla::HashString(aKey) % RECENTLY_USED_PARSER_ATOMS_SIZE; + if (nsAtom* atom = mRecentlyUsedParserAtoms[index]) { + if (atom->Equals(aKey)) { + return atom; + } + } + + RefPtr<nsAtom> atom = NS_Atomize(aKey); + nsAtom* ret = atom.get(); + mRecentlyUsedParserAtoms[index] = std::move(atom); + return ret; +} diff --git a/parser/html/nsHtml5AtomTable.h b/parser/html/nsHtml5AtomTable.h new file mode 100644 index 0000000000..4130f05745 --- /dev/null +++ b/parser/html/nsHtml5AtomTable.h @@ -0,0 +1,91 @@ +/* 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/. */ + +#ifndef nsHtml5AtomTable_h +#define nsHtml5AtomTable_h + +#include "nsHashKeys.h" +#include "nsTHashtable.h" +#include "nsAtom.h" +#include "nsISerialEventTarget.h" + +#define RECENTLY_USED_PARSER_ATOMS_SIZE 31 + +/** + * nsHtml5AtomTable provides non-locking lookup and creation of atoms for + * nsHtml5Parser or nsHtml5StreamParser. + * + * The hashtable holds dynamically allocated atoms that are private to an + * instance of nsHtml5Parser or nsHtml5StreamParser. (Static atoms are used on + * interned nsHtml5ElementNames and interned nsHtml5AttributeNames. Also, when + * the doctype name is 'html', that identifier needs to be represented as a + * static atom.) + * + * Each instance of nsHtml5Parser has a single instance of nsHtml5AtomTable, + * and each instance of nsHtml5StreamParser has a single instance of + * nsHtml5AtomTable. Dynamic atoms obtained from an nsHtml5AtomTable are valid + * for == comparison with each other or with atoms declared in nsHtml5Atoms + * within the nsHtml5Tokenizer and the nsHtml5TreeBuilder instances owned by + * the same nsHtml5Parser/nsHtml5StreamParser instance that owns the + * nsHtml5AtomTable instance. + * + * Dynamic atoms (atoms whose IsStatic() returns false) obtained from + * nsHtml5AtomTable must be re-obtained from another atom table when there's a + * need to migrate atoms from an nsHtml5Parser to its nsHtml5StreamParser + * (re-obtain from the other nsHtml5AtomTable), from an nsHtml5Parser to its + * owner nsHtml5Parser (re-obtain from the other nsHtml5AtomTable) or from the + * parser to the DOM (re-obtain from the application-wide atom table). To + * re-obtain an atom from another atom table, obtain a string from the atom + * using ToString(nsAString&) and look up an atom in the other table using that + * string. + * + * An instance of nsHtml5AtomTable that belongs to an nsHtml5Parser is only + * accessed from the main thread. An instance of nsHtml5AtomTable that belongs + * to an nsHtml5StreamParser is accessed both from the main thread and from the + * thread that executes the runnables of the nsHtml5StreamParser instance. + * However, the threads never access the nsHtml5AtomTable instance concurrently + * in the nsHtml5StreamParser case. + * + * Methods on the atoms obtained from nsHtml5AtomTable may be called on any + * thread, although they only need to be called on the main thread or on the + * thread working for the nsHtml5StreamParser when nsHtml5AtomTable belongs to + * an nsHtml5StreamParser. + * + * Dynamic atoms obtained from nsHtml5AtomTable are deleted when the + * nsHtml5AtomTable itself is destructed, which happens when the owner + * nsHtml5Parser or nsHtml5StreamParser is destructed. + */ +class nsHtml5AtomTable { + public: + nsHtml5AtomTable(); + ~nsHtml5AtomTable(); + + // NOTE: We rely on mRecentlyUsedParserAtoms keeping alive the returned atom, + // but the caller is responsible to take a reference before calling GetAtom + // again. + nsAtom* GetAtom(const nsAString& aKey); + + /** + * Empties the table. + */ + void Clear() { + for (uint32_t i = 0; i < RECENTLY_USED_PARSER_ATOMS_SIZE; ++i) { + mRecentlyUsedParserAtoms[i] = nullptr; + } + } + +#ifdef DEBUG + void SetPermittedLookupEventTarget(nsISerialEventTarget* aEventTarget) { + mPermittedLookupEventTarget = aEventTarget; + } +#endif + + private: + RefPtr<nsAtom> mRecentlyUsedParserAtoms[RECENTLY_USED_PARSER_ATOMS_SIZE]; +#ifdef DEBUG + nsCOMPtr<nsISerialEventTarget> mPermittedLookupEventTarget; +#endif +}; + +#endif // nsHtml5AtomTable_h diff --git a/parser/html/nsHtml5AttributeEntry.h b/parser/html/nsHtml5AttributeEntry.h new file mode 100644 index 0000000000..6fbca7f1cb --- /dev/null +++ b/parser/html/nsHtml5AttributeEntry.h @@ -0,0 +1,70 @@ +/* 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/. */ + +#ifndef nsHtml5AttributeEntry_h +#define nsHtml5AttributeEntry_h + +#include "nsHtml5AttributeName.h" + +class nsHtml5AttributeEntry final { + public: + nsHtml5AttributeEntry(nsHtml5AttributeName* aName, nsHtml5String aValue, + int32_t aLine) + : mLine(aLine), mValue(aValue) { + // Let's hope the compiler coalesces the following as appropriate. + mLocals[0] = aName->getLocal(0); + mLocals[1] = aName->getLocal(1); + mLocals[2] = aName->getLocal(2); + mPrefixes[0] = aName->getPrefix(0); + mPrefixes[1] = aName->getPrefix(1); + mPrefixes[2] = aName->getPrefix(2); + mUris[0] = aName->getUri(0); + mUris[1] = aName->getUri(1); + mUris[2] = aName->getUri(2); + } + + // Isindex-only so doesn't need to deal with SVG and MathML + nsHtml5AttributeEntry(nsAtom* aName, nsHtml5String aValue, int32_t aLine) + : mLine(aLine), mValue(aValue) { + // Let's hope the compiler coalesces the following as appropriate. + mLocals[0] = aName; + mLocals[1] = aName; + mLocals[2] = aName; + mPrefixes[0] = nullptr; + mPrefixes[1] = nullptr; + mPrefixes[2] = nullptr; + mUris[0] = kNameSpaceID_None; + mUris[1] = kNameSpaceID_None; + mUris[2] = kNameSpaceID_None; + } + + inline nsAtom* GetLocal(int32_t aMode) { return mLocals[aMode]; } + + inline nsAtom* GetPrefix(int32_t aMode) { return mPrefixes[aMode]; } + + inline int32_t GetUri(int32_t aMode) { return mUris[aMode]; } + + inline nsHtml5String GetValue() { return mValue; } + + inline int32_t GetLine() { return mLine; } + + inline void ReleaseValue() { mValue.Release(); } + + inline nsHtml5AttributeEntry Clone() { + // Copy the memory + nsHtml5AttributeEntry clone(*this); + // Increment refcount for value + clone.mValue = this->mValue.Clone(); + return clone; + } + + private: + RefPtr<nsAtom> mLocals[3]; + RefPtr<nsAtom> mPrefixes[3]; + int32_t mUris[3]; + int32_t mLine; + nsHtml5String mValue; +}; + +#endif // nsHtml5AttributeEntry_h diff --git a/parser/html/nsHtml5AttributeName.cpp b/parser/html/nsHtml5AttributeName.cpp new file mode 100644 index 0000000000..00ef41cef0 --- /dev/null +++ b/parser/html/nsHtml5AttributeName.cpp @@ -0,0 +1,2875 @@ +/* + * Copyright (c) 2008-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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit AttributeName.java instead and regenerate. + */ + +#define nsHtml5AttributeName_cpp__ + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +#include "nsHtml5ElementName.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5Portability.h" + +#include "nsHtml5AttributeName.h" + +int32_t* nsHtml5AttributeName::ALL_NO_NS = 0; +int32_t* nsHtml5AttributeName::XMLNS_NS = 0; +int32_t* nsHtml5AttributeName::XML_NS = 0; +int32_t* nsHtml5AttributeName::XLINK_NS = 0; +nsStaticAtom** nsHtml5AttributeName::ALL_NO_PREFIX = 0; +nsStaticAtom** nsHtml5AttributeName::XMLNS_PREFIX = 0; +nsStaticAtom** nsHtml5AttributeName::XLINK_PREFIX = 0; +nsStaticAtom** nsHtml5AttributeName::XML_PREFIX = 0; +RefPtr<nsAtom>* nsHtml5AttributeName::SVG_DIFFERENT(nsAtom* name, + nsAtom* camel) { + RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4]; + arr[0] = name; + arr[1] = name; + arr[2] = camel; + return arr; +} + +RefPtr<nsAtom>* nsHtml5AttributeName::MATH_DIFFERENT(nsAtom* name, + nsAtom* camel) { + RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4]; + arr[0] = name; + arr[1] = camel; + arr[2] = name; + return arr; +} + +RefPtr<nsAtom>* nsHtml5AttributeName::COLONIFIED_LOCAL(nsAtom* name, + nsAtom* suffix) { + RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4]; + arr[0] = name; + arr[1] = suffix; + arr[2] = suffix; + return arr; +} + +RefPtr<nsAtom>* nsHtml5AttributeName::SAME_LOCAL(nsAtom* name) { + RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4]; + arr[0] = name; + arr[1] = name; + arr[2] = name; + return arr; +} + +nsHtml5AttributeName::nsHtml5AttributeName(int32_t* uri, RefPtr<nsAtom>* local, + nsStaticAtom** prefix) + : uri(uri), local(local), prefix(prefix), custom(false) { + MOZ_COUNT_CTOR(nsHtml5AttributeName); +} + +nsHtml5AttributeName::nsHtml5AttributeName() + : uri(nsHtml5AttributeName::ALL_NO_NS), + local(nsHtml5AttributeName::SAME_LOCAL(nullptr)), + prefix(ALL_NO_PREFIX), + custom(true) { + MOZ_COUNT_CTOR(nsHtml5AttributeName); +} + +nsHtml5AttributeName* nsHtml5AttributeName::createAttributeName(nsAtom* name) { + return new nsHtml5AttributeName(nsHtml5AttributeName::ALL_NO_NS, + nsHtml5AttributeName::SAME_LOCAL(name), + ALL_NO_PREFIX); +} + +nsHtml5AttributeName::~nsHtml5AttributeName() { + MOZ_COUNT_DTOR(nsHtml5AttributeName); + delete[] local; +} + +int32_t nsHtml5AttributeName::getUri(int32_t mode) { return uri[mode]; } + +nsAtom* nsHtml5AttributeName::getLocal(int32_t mode) { return local[mode]; } + +nsStaticAtom* nsHtml5AttributeName::getPrefix(int32_t mode) { + return prefix[mode]; +} + +bool nsHtml5AttributeName::equalsAnother(nsHtml5AttributeName* another) { + return this->getLocal(nsHtml5AttributeName::HTML) == + another->getLocal(nsHtml5AttributeName::HTML); +} + +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DUR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_END = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IN2 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOW = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MAX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REV = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SRC = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_D = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_R = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_X = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Y = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Z = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K1 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_X1 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Y1 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K2 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_X2 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Y2 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K3 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K4 = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XML_SPACE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XML_LANG = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_GRAB = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_VALUEMAX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_LABELLEDBY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DESCRIBEDBY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DISABLED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_CHECKED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SELECTED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DROPEFFECT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_REQUIRED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_EXPANDED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_PRESSED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_LEVEL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_CHANNEL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_HIDDEN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SECRET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_POSINSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_ATOMIC = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_INVALID = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_TEMPLATEID = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_VALUEMIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_MULTISELECTABLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_CONTROLS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_MULTILINE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_READONLY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_OWNS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_ACTIVEDESCENDANT = + nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_RELEVANT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DATATYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_VALUENOW = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SORT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_AUTOCOMPLETE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_FLOWTO = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_BUSY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_LIVE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_HASPOPUP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SETSIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLEAR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DISABLED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEFAULT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DATA = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EQUALCOLUMNS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EQUALROWS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HSPACE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ISMAP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOCAL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LSPACE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MOVABLELIMITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOTATION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDATAAVAILABLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONPASTE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RSPACE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWALIGN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROTATE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SEPARATOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SEPARATORS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VSPACE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XCHANNELSELECTOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_YCHANNELSELECTOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENABLE_BACKGROUND = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDBLCLICK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONABORT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CALCMODE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHECKED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FENCE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSCROLL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONACTIVATE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPACITY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPACING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPECULAREXPONENT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPECULARCONSTANT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BORDER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ID = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GRADIENTTRANSFORM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GRADIENTUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HIDDEN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HEADERS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOADING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_READONLY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RENDERING_INTENT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SEED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SRCDOC = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STDDEVIATION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SANDBOX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WORD_SPACING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCENTUNDER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCEPT_CHARSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCESSKEY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCENT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCEPT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BEVELLED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASEFREQUENCY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASELINE_SHIFT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASEPROFILE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASELINE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CODE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CODETYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CODEBASE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CITE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEFER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DATETIME = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIRECTION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EDGEMODE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EDGE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENTERKEYHINT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FACE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INDEX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INTERCEPT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INTEGRITY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LINEBREAK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LABEL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LINETHICKNESS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MODE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NAME = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NORESIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFOREUNLOAD = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONREPEAT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OBJECT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSELECT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORDER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OTHER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONRESET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONREADYSTATECHANGE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMESSAGE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEGIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFOREPRINT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORIENT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORIENTATION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFORECOPY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSELECTSTART = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFOREPASTE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONKEYPRESS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONKEYUP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFORECUT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONKEYDOWN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONRESIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPEAT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REFERRERPOLICY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RULES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPEATCOUNT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPEATDUR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SELECTED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SIZES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SUPERSCRIPTSHIFT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STRETCHY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCHEME = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPREADMETHOD = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SELECTION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIFFUSECONSTANT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HREF = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HREFLANG = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONAFTERPRINT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PROFILE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SURFACESCALE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XREF = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALIGN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALIGNMENT_BASELINE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALIGNMENTSCOPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DRAGGABLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HEIGHT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IMAGESIZES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IMAGESRCSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IMAGE_RENDERING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LANGUAGE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LANG = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LARGEOP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LONGDESC = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LENGTHADJUST = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARGINHEIGHT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARGINWIDTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORIGIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TARGET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TARGETX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TARGETY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARCHIVE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HIGH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LIGHTING_COLOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHBACKGROUND = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_METHOD = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHVARIANT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHCOLOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHSIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOSHADE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCHANGE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATHLENGTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALTIMG = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACTIONTYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACTION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACTIVE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ADDITIVE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BEGIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DOMINANT_BASELINE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIVISOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEFINITIONURL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LIMITINGCONEANGLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MEDIA = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MANIFEST = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFINISH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPTIMUM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RADIOGROUP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RADIUS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCRIPTLEVEL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCRIPTSIZEMULTIPLIER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCRIPTMINSIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TABINDEX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALIGN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VISIBILITY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BACKGROUND = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LINK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKER_MID = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKERHEIGHT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKER_END = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MASK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKER_START = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKERWIDTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MASKUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKERUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MASKCONTENTUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AMPLITUDE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CELLSPACING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CELLPADDING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DECLARE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILL_RULE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILL_OPACITY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MAXLENGTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCLICK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBLUR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPLACE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWLINES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCALE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STYLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TABLEVALUES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TITLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AZIMUTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FORMAT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FRAMEBORDER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FRAME = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FRAMESPACING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FROM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FORM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PROMPT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PRIMITIVEUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SYMMETRIC = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SUMMARY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_USEMAP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ZOOMANDPAN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ASYNC = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALINK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ICON = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KERNELMATRIX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KERNING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KERNELUNITLENGTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONUNLOAD = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPEN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONINVALID = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONEND = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONINPUT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTER_EVENTS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTSATX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTSATY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTSATZ = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPAN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STANDBY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TRANSFORM_ORIGIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TRANSFORM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VLINK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WHEN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_HREF = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_TITLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_ROLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_ARCROLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XMLNS_XLINK = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XMLNS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_TYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_SHOW = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_ACTUATE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOPLAY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOCOMPLETE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOFOCUS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOCAPITALIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BGCOLOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_PROFILE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_RENDERING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_INTERPOLATION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_INTERPOLATION_FILTERS = + nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENCODING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EXPONENT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FLOOD_COLOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FLOOD_OPACITY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LQUOTE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NUMOCTAVES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOMODULE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONLOAD = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEWHEEL = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEENTER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEOVER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFOCUSIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCONTEXTMENU = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONZOOM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCOPY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSELEAVE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEMOVE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEUP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFOCUS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEOUT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFOCUSOUT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEDOWN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TO = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RQUOTE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_LINECAP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_DASHARRAY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_DASHOFFSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_LINEJOIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_MITERLIMIT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCROLLING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_WIDTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_OPACITY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COMPACT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIP_RULE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIP_PATH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIPPATHUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DISPLAY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DISPLAYSTYLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GLYPH_ORIENTATION_VERTICAL = + nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GLYPH_ORIENTATION_HORIZONTAL = + nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GLYPHREF = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HTTP_EQUIV = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYPOINTS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOOP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PROPERTY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCOPED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STEP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SHAPE_RENDERING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCOPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SHAPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SLOPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STOP_COLOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STOP_OPACITY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEMPLATE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WRAP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ABBR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ATTRIBUTENAME = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ATTRIBUTETYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHAR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COORDS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHAROFF = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHARSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOWRAP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOHREF = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAG = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGENTER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGOVER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGEND = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDROP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGDROP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONERROR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPERATOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OVERFLOW = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGSTART = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGLEAVE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STARTOFFSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_START = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AXIS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BIAS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLSPAN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLASSID = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CROSSORIGIN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CURSOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLOSURE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLOSE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLASS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYSYSTEM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYSPLINES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOWSRC = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MAXSIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MINSIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OFFSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PRESERVEALPHA = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PRESERVEASPECTRATIO = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWSPAN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWSPACING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SRCSET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SUBSCRIPTSHIFT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VERSION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALTTEXT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTENTEDITABLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTROLS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTENT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTEXTMENU = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEPTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENCTYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_STRETCH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILTER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTWEIGHT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_WEIGHT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTSTYLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_STYLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTFAMILY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_FAMILY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_VARIANT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_SIZE_ADJUST = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILTERUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTSIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_SIZE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYTIMES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LETTER_SPACING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LIST = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MULTIPLE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSTOP = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSTART = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POSTER = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERNTRANSFORM = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERNUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERNCONTENTUNITS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RESTART = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STITCHTILES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SYSTEMLANGUAGE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT_RENDERING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT_DECORATION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT_ANCHOR = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXTLENGTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WRITING_MODE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WIDTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCUMULATE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNSPAN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNLINES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNALIGN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNSPACING = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNWIDTH = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GROUPALIGN = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INPUTMODE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSUBMIT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCUT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REQUIRED = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REQUIREDFEATURES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RESULT = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REQUIREDEXTENSIONS = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALUES = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALUETYPE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALUE = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ELEVATION = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VIEWTARGET = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VIEWBOX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REFX = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RY = nullptr; +nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REFY = nullptr; +nsHtml5AttributeName** nsHtml5AttributeName::ATTRIBUTE_NAMES = 0; +static int32_t const ATTRIBUTE_HASHES_DATA[] = { + 1867462756, 1748971848, 1966442279, 1681174213, 1785053243, 1916286197, + 2004846654, 1680165421, 1723336432, 1754899031, 1816104145, 1905628916, + 1924629705, 1988784439, 2024647008, 71827457, 1680282148, 1689324870, + 1747295467, 1754579720, 1756889417, 1803561214, 1848600826, 1884295780, + 1910441627, 1922607670, 1939976792, 1975062341, 2000752725, 2009079867, + 2073034754, 57205395, 911736834, 1680181996, 1680368221, 1685882101, + 1704526375, 1736416327, 1747906667, 1751755561, 1754698327, 1756360955, + 1773606972, 1787365531, 1805715690, 1823574314, 1854497001, 1874270021, + 1898415413, 1906423097, 1915025672, 1921977416, 1923088386, 1933369607, + 1941550652, 1972904518, 1983398182, 1991625270, 2001710298, 2007021895, + 2016810187, 2060474743, 2082471938, 53006051, 60345635, 885522434, + 1680095865, 1680165533, 1680229115, 1680343801, 1680437801, 1682440540, + 1687620127, 1692408896, 1721189160, 1733874289, 1740096054, 1747479606, + 1748503880, 1749549708, 1753550036, 1754644293, 1754835516, 1756147974, + 1756762256, 1767725700, 1781007934, 1786775671, 1791068279, 1804081401, + 1814560070, 1820727381, 1824159037, 1854366938, 1865910331, 1872343590, + 1884079398, 1890996553, 1903612236, 1906408542, 1908462185, 1910503637, + 1915757815, 1917857531, 1922413307, 1922677495, 1924517489, 1932959284, + 1934970504, 1941435445, 1965512429, 1972656710, 1972922984, 1983157559, + 1984430082, 1990107683, 2000096287, 2001634458, 2001826027, 2006459190, + 2008401563, 2010716309, 2019887833, 2026893641, 2065694722, 2081423362, + 2089811970, 52488851, 55077603, 59825747, 68157441, 878182402, + 901775362, 1037879561, 1680159327, 1680165437, 1680165692, 1680198203, + 1680231247, 1680315086, 1680345965, 1680413393, 1680452349, 1681879063, + 1683805446, 1686731997, 1689048326, 1689839946, 1699185409, 1714763319, + 1721347639, 1731048742, 1734182982, 1739583824, 1740130375, 1747309881, + 1747800157, 1748021284, 1748566068, 1749350104, 1751507685, 1753049109, + 1754434872, 1754612424, 1754647074, 1754794646, 1754860061, 1754927689, + 1756219733, 1756704824, 1756836998, 1757421892, 1771569964, 1780879045, + 1784574102, 1786622296, 1786851500, 1788842244, 1797886599, 1804054854, + 1804405895, 1814517574, 1814656840, 1816178925, 1821958888, 1823829083, + 1825437894, 1854285018, 1854466380, 1854497008, 1866496199, 1871251689, + 1873656984, 1874788501, 1884246821, 1889569526, 1891937366, 1900544002, + 1903759600, 1905754853, 1906419001, 1907701479, 1909819252, 1910441773, + 1910527802, 1915341049, 1916247343, 1917295176, 1921061206, 1922400908, + 1922566877, 1922665179, 1922679610, 1924443742, 1924583073, 1924773438, + 1933123337, 1934917290, 1937336473, 1941286708, 1941440197, 1943317364, + 1966384692, 1972151670, 1972744954, 1972908839, 1972996699, 1982254612, + 1983290011, 1983432389, 1987422362, 1989522022, 1991220282, 1993343287, + 2000160071, 2001527900, 2001669449, 2001732764, 2001898809, 2005342360, + 2006824246, 2007064819, 2009041198, 2009231684, 2016711994, 2017010843, + 2023342821, 2024794274, 2034765641, 2065170434, 2066743298, 2075005220, + 2081947650, 2083520514, 2091784484, 50917059, 52489043, 53537523, + 56685811, 57210387, 59830867, 60817409, 71303169, 72351745, + 884998146, 894959618, 902299650, 928514050, 1038063816, 1680140893, + 1680159328, 1680165436, 1680165487, 1680165613, 1680181850, 1680185931, + 1680198381, 1680230940, 1680251485, 1680311085, 1680323325, 1680345685, + 1680347981, 1680411449, 1680433915, 1680446153, 1680511804, 1681733672, + 1681969220, 1682587945, 1684319541, 1685902598, 1687164232, 1687751191, + 1689130184, 1689788441, 1691145478, 1692933184, 1704262346, 1714745560, + 1716303957, 1721305962, 1723309623, 1723336528, 1732771842, 1733919469, + 1734404167, 1739561208, 1739927860, 1740119884, 1742183484, 1747299630, + 1747446838, 1747792072, 1747839118, 1747939528, 1748306996, 1748552744, + 1748869205, 1749027145, 1749399124, 1749856356, 1751679545, 1752985897, + 1753297133, 1754214628, 1754546894, 1754606246, 1754643237, 1754645079, + 1754647353, 1754792749, 1754798923, 1754858317, 1754872618, 1754907227, + 1754958648, 1756190926, 1756302628, 1756471625, 1756737685, 1756804936, + 1756874572, 1757053236, 1765800271, 1767875272, 1772032615, 1776114564, + 1780975314, 1782518297, 1785051290, 1785174319, 1786740932, 1786821704, + 1787193500, 1788254870, 1790814502, 1791070327, 1801312388, 1804036350, + 1804069019, 1804235064, 1804978712, 1805715716, 1814558026, 1814656326, + 1814986837, 1816144023, 1820262641, 1820928104, 1822002839, 1823580230, + 1823841492, 1824377064, 1825677514, 1853862084, 1854302364, 1854464212, + 1854474395, 1854497003, 1864698185, 1865910347, 1867448617, 1867620412, + 1872034503, 1873590471, 1874261045, 1874698443, 1881750231, 1884142379, + 1884267068, 1884343396, 1889633006, 1891186903, 1894552650, 1898428101, + 1902640276, 1903659239, 1905541832, 1905672729, 1905902311, 1906408598, + 1906421049, 1907660596, 1908316832, 1909438149, 1910328970, 1910441770, + 1910487243, 1910507338, 1910572893, 1915295948, 1915394254, 1916210285, + 1916278099, 1916337499, 1917327080, 1917953597, 1921894426, 1922319046, + 1922413292, 1922470745, 1922567078, 1922665052, 1922671417, 1922679386, + 1922699851, 1924206934, 1924462384, 1924570799, 1924585254, 1924738716, + 1932870919, 1932986153, 1933145837, 1933508940, 1934917372, 1935597338, + 1937777860, 1941253366, 1941409583, 1941438085, 1941454586, 1942026440, + 1965349396, 1965561677, 1966439670, 1966454567, 1972196486, 1972744939, + 1972863609, 1972904522, 1972909592, 1972962123, 1974849131, 1980235778, + 1982640164, 1983266615, 1983347764, 1983416119, 1983461061, 1987410233, + 1988132214, 1988788535, 1990062797, 1991021879, 1991392548, 1991643278, + 1999273799, 2000125224, 2000162011, 2001210183, 2001578182, 2001634459, + 2001669450, 2001710299, 2001814704, 2001898808, 2004199576, 2004957380, + 2005925890, 2006516551, 2007019632, 2007064812, 2008084807, 2008408414, + 2009071951, 2009141482, 2010452700, 2015950026, 2016787611, 2016910397, + 2018908874, 2023146024, 2024616088, 2024763702, 2026741958, 2026975253, + 2060302634}; +staticJArray<int32_t, int32_t> nsHtml5AttributeName::ATTRIBUTE_HASHES = { + ATTRIBUTE_HASHES_DATA, MOZ_ARRAY_LENGTH(ATTRIBUTE_HASHES_DATA)}; +void nsHtml5AttributeName::initializeStatics() { + ALL_NO_NS = new int32_t[3]; + ALL_NO_NS[0] = kNameSpaceID_None; + ALL_NO_NS[1] = kNameSpaceID_None; + ALL_NO_NS[2] = kNameSpaceID_None; + XMLNS_NS = new int32_t[3]; + XMLNS_NS[0] = kNameSpaceID_None; + XMLNS_NS[1] = kNameSpaceID_XMLNS; + XMLNS_NS[2] = kNameSpaceID_XMLNS; + XML_NS = new int32_t[3]; + XML_NS[0] = kNameSpaceID_None; + XML_NS[1] = kNameSpaceID_XML; + XML_NS[2] = kNameSpaceID_XML; + XLINK_NS = new int32_t[3]; + XLINK_NS[0] = kNameSpaceID_None; + XLINK_NS[1] = kNameSpaceID_XLink; + XLINK_NS[2] = kNameSpaceID_XLink; + ALL_NO_PREFIX = new nsStaticAtom*[3]; + ALL_NO_PREFIX[0] = nullptr; + ALL_NO_PREFIX[1] = nullptr; + ALL_NO_PREFIX[2] = nullptr; + XMLNS_PREFIX = new nsStaticAtom*[3]; + XMLNS_PREFIX[0] = nullptr; + XMLNS_PREFIX[1] = nsGkAtoms::xmlns; + XMLNS_PREFIX[2] = nsGkAtoms::xmlns; + XLINK_PREFIX = new nsStaticAtom*[3]; + XLINK_PREFIX[0] = nullptr; + XLINK_PREFIX[1] = nsGkAtoms::xlink; + XLINK_PREFIX[2] = nsGkAtoms::xlink; + XML_PREFIX = new nsStaticAtom*[3]; + XML_PREFIX[0] = nullptr; + XML_PREFIX[1] = nsGkAtoms::xml; + XML_PREFIX[2] = nsGkAtoms::xml; + ATTR_ALT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alt), + ALL_NO_PREFIX); + ATTR_DIR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dir), + ALL_NO_PREFIX); + ATTR_DUR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dur), + ALL_NO_PREFIX); + ATTR_END = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::end), + ALL_NO_PREFIX); + ATTR_FOR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_for), + ALL_NO_PREFIX); + ATTR_IN2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::in2), + ALL_NO_PREFIX); + ATTR_LOW = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::low), + ALL_NO_PREFIX); + ATTR_MIN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::min), + ALL_NO_PREFIX); + ATTR_MAX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::max), + ALL_NO_PREFIX); + ATTR_REL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rel), + ALL_NO_PREFIX); + ATTR_REV = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rev), + ALL_NO_PREFIX); + ATTR_SRC = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::src), + ALL_NO_PREFIX); + ATTR_D = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::d), + ALL_NO_PREFIX); + ATTR_R = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::r), + ALL_NO_PREFIX); + ATTR_X = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::x), + ALL_NO_PREFIX); + ATTR_Y = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::y), + ALL_NO_PREFIX); + ATTR_Z = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::z), + ALL_NO_PREFIX); + ATTR_K1 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k1), + ALL_NO_PREFIX); + ATTR_X1 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::x1), + ALL_NO_PREFIX); + ATTR_Y1 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::y1), + ALL_NO_PREFIX); + ATTR_K2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k2), + ALL_NO_PREFIX); + ATTR_X2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::x2), + ALL_NO_PREFIX); + ATTR_Y2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::y2), + ALL_NO_PREFIX); + ATTR_K3 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k3), + ALL_NO_PREFIX); + ATTR_K4 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k4), + ALL_NO_PREFIX); + ATTR_XML_SPACE = new nsHtml5AttributeName( + XML_NS, COLONIFIED_LOCAL(nsGkAtoms::xml_space, nsGkAtoms::space), + XML_PREFIX); + ATTR_XML_LANG = new nsHtml5AttributeName( + XML_NS, COLONIFIED_LOCAL(nsGkAtoms::xml_lang, nsGkAtoms::lang), + XML_PREFIX); + ATTR_ARIA_GRAB = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_grab), ALL_NO_PREFIX); + ATTR_ARIA_VALUEMAX = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_valuemax), ALL_NO_PREFIX); + ATTR_ARIA_LABELLEDBY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_labelledby), ALL_NO_PREFIX); + ATTR_ARIA_DESCRIBEDBY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_describedby), ALL_NO_PREFIX); + ATTR_ARIA_DISABLED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_disabled), ALL_NO_PREFIX); + ATTR_ARIA_CHECKED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_checked), ALL_NO_PREFIX); + ATTR_ARIA_SELECTED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_selected), ALL_NO_PREFIX); + ATTR_ARIA_DROPEFFECT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_dropeffect), ALL_NO_PREFIX); + ATTR_ARIA_REQUIRED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_required), ALL_NO_PREFIX); + ATTR_ARIA_EXPANDED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_expanded), ALL_NO_PREFIX); + ATTR_ARIA_PRESSED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_pressed), ALL_NO_PREFIX); + ATTR_ARIA_LEVEL = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_level), ALL_NO_PREFIX); + ATTR_ARIA_CHANNEL = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_channel), ALL_NO_PREFIX); + ATTR_ARIA_HIDDEN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_hidden), ALL_NO_PREFIX); + ATTR_ARIA_SECRET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_secret), ALL_NO_PREFIX); + ATTR_ARIA_POSINSET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_posinset), ALL_NO_PREFIX); + ATTR_ARIA_ATOMIC = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_atomic), ALL_NO_PREFIX); + ATTR_ARIA_INVALID = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_invalid), ALL_NO_PREFIX); + ATTR_ARIA_TEMPLATEID = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_templateid), ALL_NO_PREFIX); + ATTR_ARIA_VALUEMIN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_valuemin), ALL_NO_PREFIX); + ATTR_ARIA_MULTISELECTABLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_multiselectable), ALL_NO_PREFIX); + ATTR_ARIA_CONTROLS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_controls), ALL_NO_PREFIX); + ATTR_ARIA_MULTILINE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_multiline), ALL_NO_PREFIX); + ATTR_ARIA_READONLY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_readonly), ALL_NO_PREFIX); + ATTR_ARIA_OWNS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_owns), ALL_NO_PREFIX); + ATTR_ARIA_ACTIVEDESCENDANT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_activedescendant), ALL_NO_PREFIX); + ATTR_ARIA_RELEVANT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_relevant), ALL_NO_PREFIX); + ATTR_ARIA_DATATYPE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_datatype), ALL_NO_PREFIX); + ATTR_ARIA_VALUENOW = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_valuenow), ALL_NO_PREFIX); + ATTR_ARIA_SORT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_sort), ALL_NO_PREFIX); + ATTR_ARIA_AUTOCOMPLETE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_autocomplete), ALL_NO_PREFIX); + ATTR_ARIA_FLOWTO = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_flowto), ALL_NO_PREFIX); + ATTR_ARIA_BUSY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_busy), ALL_NO_PREFIX); + ATTR_ARIA_LIVE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_live), ALL_NO_PREFIX); + ATTR_ARIA_HASPOPUP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_haspopup), ALL_NO_PREFIX); + ATTR_ARIA_SETSIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_setsize), ALL_NO_PREFIX); + ATTR_CLEAR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clear), + ALL_NO_PREFIX); + ATTR_DISABLED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::disabled), ALL_NO_PREFIX); + ATTR_DEFAULT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_default), ALL_NO_PREFIX); + ATTR_DATA = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::data), + ALL_NO_PREFIX); + ATTR_EQUALCOLUMNS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::equalcolumns_), ALL_NO_PREFIX); + ATTR_EQUALROWS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::equalrows_), ALL_NO_PREFIX); + ATTR_HSPACE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::hspace), ALL_NO_PREFIX); + ATTR_ISMAP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ismap), + ALL_NO_PREFIX); + ATTR_LOCAL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::local), + ALL_NO_PREFIX); + ATTR_LSPACE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lspace_), ALL_NO_PREFIX); + ATTR_MOVABLELIMITS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::movablelimits_), ALL_NO_PREFIX); + ATTR_NOTATION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::notation_), ALL_NO_PREFIX); + ATTR_ONDATAAVAILABLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondataavailable), ALL_NO_PREFIX); + ATTR_ONPASTE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onpaste), ALL_NO_PREFIX); + ATTR_RSPACE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rspace_), ALL_NO_PREFIX); + ATTR_ROWALIGN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowalign_), ALL_NO_PREFIX); + ATTR_ROTATE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rotate), ALL_NO_PREFIX); + ATTR_SEPARATOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::separator_), ALL_NO_PREFIX); + ATTR_SEPARATORS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::separators_), ALL_NO_PREFIX); + ATTR_VSPACE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::vspace), ALL_NO_PREFIX); + ATTR_XCHANNELSELECTOR = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::xchannelselector, nsGkAtoms::xChannelSelector), + ALL_NO_PREFIX); + ATTR_YCHANNELSELECTOR = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::ychannelselector, nsGkAtoms::yChannelSelector), + ALL_NO_PREFIX); + ATTR_ENABLE_BACKGROUND = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::enable_background), ALL_NO_PREFIX); + ATTR_ONDBLCLICK = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondblclick), ALL_NO_PREFIX); + ATTR_ONABORT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onabort), ALL_NO_PREFIX); + ATTR_CALCMODE = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::calcmode, nsGkAtoms::calcMode), + ALL_NO_PREFIX); + ATTR_CHECKED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::checked), ALL_NO_PREFIX); + ATTR_FENCE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fence_), ALL_NO_PREFIX); + ATTR_ONSCROLL = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onscroll), ALL_NO_PREFIX); + ATTR_ONACTIVATE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onactivate), ALL_NO_PREFIX); + ATTR_OPACITY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::opacity), ALL_NO_PREFIX); + ATTR_SPACING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::spacing), ALL_NO_PREFIX); + ATTR_SPECULAREXPONENT = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::specularexponent, nsGkAtoms::specularExponent), + ALL_NO_PREFIX); + ATTR_SPECULARCONSTANT = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::specularconstant, nsGkAtoms::specularConstant), + ALL_NO_PREFIX); + ATTR_BORDER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::border), ALL_NO_PREFIX); + ATTR_ID = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::id), + ALL_NO_PREFIX); + ATTR_GRADIENTTRANSFORM = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::gradienttransform, nsGkAtoms::gradientTransform), + ALL_NO_PREFIX); + ATTR_GRADIENTUNITS = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::gradientunits, nsGkAtoms::gradientUnits), + ALL_NO_PREFIX); + ATTR_HIDDEN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::hidden), ALL_NO_PREFIX); + ATTR_HEADERS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::headers), ALL_NO_PREFIX); + ATTR_LOADING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::loading), ALL_NO_PREFIX); + ATTR_READONLY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::readonly), ALL_NO_PREFIX); + ATTR_RENDERING_INTENT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rendering_intent), ALL_NO_PREFIX); + ATTR_SEED = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::seed), + ALL_NO_PREFIX); + ATTR_SRCDOC = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::srcdoc), ALL_NO_PREFIX); + ATTR_STDDEVIATION = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::stddeviation, nsGkAtoms::stdDeviation), + ALL_NO_PREFIX); + ATTR_SANDBOX = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::sandbox), ALL_NO_PREFIX); + ATTR_WORD_SPACING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::word_spacing), ALL_NO_PREFIX); + ATTR_ACCENTUNDER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accentunder_), ALL_NO_PREFIX); + ATTR_ACCEPT_CHARSET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::acceptcharset), ALL_NO_PREFIX); + ATTR_ACCESSKEY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accesskey), ALL_NO_PREFIX); + ATTR_ACCENT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accent_), ALL_NO_PREFIX); + ATTR_ACCEPT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accept), ALL_NO_PREFIX); + ATTR_BEVELLED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::bevelled_), ALL_NO_PREFIX); + ATTR_BASEFREQUENCY = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::basefrequency, nsGkAtoms::baseFrequency), + ALL_NO_PREFIX); + ATTR_BASELINE_SHIFT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::baseline_shift), ALL_NO_PREFIX); + ATTR_BASEPROFILE = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::baseprofile, nsGkAtoms::baseProfile), + ALL_NO_PREFIX); + ATTR_BASELINE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::baseline), ALL_NO_PREFIX); + ATTR_BASE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::base), + ALL_NO_PREFIX); + ATTR_CODE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::code), + ALL_NO_PREFIX); + ATTR_CODETYPE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::codetype), ALL_NO_PREFIX); + ATTR_CODEBASE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::codebase), ALL_NO_PREFIX); + ATTR_CITE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cite), + ALL_NO_PREFIX); + ATTR_DEFER = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::defer), + ALL_NO_PREFIX); + ATTR_DATETIME = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::datetime), ALL_NO_PREFIX); + ATTR_DIRECTION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::direction), ALL_NO_PREFIX); + ATTR_EDGEMODE = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::edgemode, nsGkAtoms::edgeMode), + ALL_NO_PREFIX); + ATTR_EDGE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::edge_), + ALL_NO_PREFIX); + ATTR_ENTERKEYHINT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::enterkeyhint), ALL_NO_PREFIX); + ATTR_FACE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::face), + ALL_NO_PREFIX); + ATTR_INDEX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::index), + ALL_NO_PREFIX); + ATTR_INTERCEPT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::intercept), ALL_NO_PREFIX); + ATTR_INTEGRITY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::integrity), ALL_NO_PREFIX); + ATTR_LINEBREAK = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::linebreak_), ALL_NO_PREFIX); + ATTR_LABEL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::label), + ALL_NO_PREFIX); + ATTR_LINETHICKNESS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::linethickness_), ALL_NO_PREFIX); + ATTR_MODE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mode), + ALL_NO_PREFIX); + ATTR_NAME = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::name), + ALL_NO_PREFIX); + ATTR_NORESIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::noresize), ALL_NO_PREFIX); + ATTR_ONBEFOREUNLOAD = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforeunload), ALL_NO_PREFIX); + ATTR_ONREPEAT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onrepeat), ALL_NO_PREFIX); + ATTR_OBJECT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::object), ALL_NO_PREFIX); + ATTR_ONSELECT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onselect), ALL_NO_PREFIX); + ATTR_ORDER = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::order), + ALL_NO_PREFIX); + ATTR_OTHER = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::other), + ALL_NO_PREFIX); + ATTR_ONRESET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onreset), ALL_NO_PREFIX); + ATTR_ONREADYSTATECHANGE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onreadystatechange), ALL_NO_PREFIX); + ATTR_ONMESSAGE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmessage), ALL_NO_PREFIX); + ATTR_ONBEGIN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbegin), ALL_NO_PREFIX); + ATTR_ONBEFOREPRINT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforeprint), ALL_NO_PREFIX); + ATTR_ORIENT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::orient), ALL_NO_PREFIX); + ATTR_ORIENTATION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::orientation), ALL_NO_PREFIX); + ATTR_ONBEFORECOPY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforecopy), ALL_NO_PREFIX); + ATTR_ONSELECTSTART = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onselectstart), ALL_NO_PREFIX); + ATTR_ONBEFOREPASTE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforepaste), ALL_NO_PREFIX); + ATTR_ONKEYPRESS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onkeypress), ALL_NO_PREFIX); + ATTR_ONKEYUP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onkeyup), ALL_NO_PREFIX); + ATTR_ONBEFORECUT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforecut), ALL_NO_PREFIX); + ATTR_ONKEYDOWN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onkeydown), ALL_NO_PREFIX); + ATTR_ONRESIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onresize), ALL_NO_PREFIX); + ATTR_REPEAT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::repeat), ALL_NO_PREFIX); + ATTR_REFERRERPOLICY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::referrerpolicy), ALL_NO_PREFIX); + ATTR_RULES = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rules), + ALL_NO_PREFIX); + ATTR_ROLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::role), + ALL_NO_PREFIX); + ATTR_REPEATCOUNT = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::repeatcount, nsGkAtoms::repeatCount), + ALL_NO_PREFIX); + ATTR_REPEATDUR = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::repeatdur, nsGkAtoms::repeatDur), + ALL_NO_PREFIX); + ATTR_SELECTED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::selected), ALL_NO_PREFIX); + ATTR_SIZES = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::sizes), + ALL_NO_PREFIX); + ATTR_SUPERSCRIPTSHIFT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::superscriptshift_), ALL_NO_PREFIX); + ATTR_STRETCHY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stretchy_), ALL_NO_PREFIX); + ATTR_SCHEME = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scheme), ALL_NO_PREFIX); + ATTR_SPREADMETHOD = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::spreadmethod, nsGkAtoms::spreadMethod), + ALL_NO_PREFIX); + ATTR_SELECTION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::selection_), ALL_NO_PREFIX); + ATTR_SIZE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::size), + ALL_NO_PREFIX); + ATTR_TYPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::type), + ALL_NO_PREFIX); + ATTR_DIFFUSECONSTANT = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::diffuseconstant, nsGkAtoms::diffuseConstant), + ALL_NO_PREFIX); + ATTR_HREF = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::href), + ALL_NO_PREFIX); + ATTR_HREFLANG = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::hreflang), ALL_NO_PREFIX); + ATTR_ONAFTERPRINT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onafterprint), ALL_NO_PREFIX); + ATTR_PROFILE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::profile), ALL_NO_PREFIX); + ATTR_SURFACESCALE = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::surfacescale, nsGkAtoms::surfaceScale), + ALL_NO_PREFIX); + ATTR_XREF = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::xref_), + ALL_NO_PREFIX); + ATTR_ALIGN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::align), + ALL_NO_PREFIX); + ATTR_ALIGNMENT_BASELINE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alignment_baseline), ALL_NO_PREFIX); + ATTR_ALIGNMENTSCOPE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alignmentscope_), ALL_NO_PREFIX); + ATTR_DRAGGABLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::draggable), ALL_NO_PREFIX); + ATTR_HEIGHT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::height), ALL_NO_PREFIX); + ATTR_IMAGESIZES = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::imagesizes), ALL_NO_PREFIX); + ATTR_IMAGESRCSET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::imagesrcset), ALL_NO_PREFIX); + ATTR_IMAGE_RENDERING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::image_rendering), ALL_NO_PREFIX); + ATTR_LANGUAGE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::language), ALL_NO_PREFIX); + ATTR_LANG = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lang), + ALL_NO_PREFIX); + ATTR_LARGEOP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::largeop_), ALL_NO_PREFIX); + ATTR_LONGDESC = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::longdesc), ALL_NO_PREFIX); + ATTR_LENGTHADJUST = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::lengthadjust, nsGkAtoms::lengthAdjust), + ALL_NO_PREFIX); + ATTR_MARGINHEIGHT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marginheight), ALL_NO_PREFIX); + ATTR_MARGINWIDTH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marginwidth), ALL_NO_PREFIX); + ATTR_ORIGIN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::origin), ALL_NO_PREFIX); + ATTR_PING = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ping), + ALL_NO_PREFIX); + ATTR_TARGET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::target), ALL_NO_PREFIX); + ATTR_TARGETX = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::targetx, nsGkAtoms::targetX), + ALL_NO_PREFIX); + ATTR_TARGETY = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::targety, nsGkAtoms::targetY), + ALL_NO_PREFIX); + ATTR_ARCHIVE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::archive), ALL_NO_PREFIX); + ATTR_HIGH = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::high), + ALL_NO_PREFIX); + ATTR_LIGHTING_COLOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lighting_color), ALL_NO_PREFIX); + ATTR_MATHBACKGROUND = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathbackground_), ALL_NO_PREFIX); + ATTR_METHOD = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::method), ALL_NO_PREFIX); + ATTR_MATHVARIANT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathvariant_), ALL_NO_PREFIX); + ATTR_MATHCOLOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathcolor_), ALL_NO_PREFIX); + ATTR_MATHSIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathsize_), ALL_NO_PREFIX); + ATTR_NOSHADE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::noshade), ALL_NO_PREFIX); + ATTR_ONCHANGE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onchange), ALL_NO_PREFIX); + ATTR_PATHLENGTH = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pathlength, nsGkAtoms::pathLength), + ALL_NO_PREFIX); + ATTR_PATH = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::path), + ALL_NO_PREFIX); + ATTR_ALTIMG = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::altimg_), ALL_NO_PREFIX); + ATTR_ACTIONTYPE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::actiontype_), ALL_NO_PREFIX); + ATTR_ACTION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::action), ALL_NO_PREFIX); + ATTR_ACTIVE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::active), ALL_NO_PREFIX); + ATTR_ADDITIVE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::additive), ALL_NO_PREFIX); + ATTR_BEGIN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::begin), + ALL_NO_PREFIX); + ATTR_DOMINANT_BASELINE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dominant_baseline), ALL_NO_PREFIX); + ATTR_DIVISOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::divisor), ALL_NO_PREFIX); + ATTR_DEFINITIONURL = new nsHtml5AttributeName( + ALL_NO_NS, + MATH_DIFFERENT(nsGkAtoms::definitionurl, nsGkAtoms::definitionURL_), + ALL_NO_PREFIX); + ATTR_LIMITINGCONEANGLE = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::limitingconeangle, nsGkAtoms::limitingConeAngle), + ALL_NO_PREFIX); + ATTR_MEDIA = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::media), + ALL_NO_PREFIX); + ATTR_MANIFEST = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::manifest), ALL_NO_PREFIX); + ATTR_ONFINISH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfinish), ALL_NO_PREFIX); + ATTR_OPTIMUM = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::optimum), ALL_NO_PREFIX); + ATTR_RADIOGROUP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::radiogroup), ALL_NO_PREFIX); + ATTR_RADIUS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::radius), ALL_NO_PREFIX); + ATTR_SCRIPTLEVEL = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scriptlevel_), ALL_NO_PREFIX); + ATTR_SCRIPTSIZEMULTIPLIER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scriptsizemultiplier_), ALL_NO_PREFIX); + ATTR_SCRIPTMINSIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scriptminsize_), ALL_NO_PREFIX); + ATTR_TABINDEX = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::tabindex), ALL_NO_PREFIX); + ATTR_VALIGN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::valign), ALL_NO_PREFIX); + ATTR_VISIBILITY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::visibility), ALL_NO_PREFIX); + ATTR_BACKGROUND = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::background), ALL_NO_PREFIX); + ATTR_LINK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::link), + ALL_NO_PREFIX); + ATTR_MARKER_MID = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marker_mid), ALL_NO_PREFIX); + ATTR_MARKERHEIGHT = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::markerheight, nsGkAtoms::markerHeight), + ALL_NO_PREFIX); + ATTR_MARKER_END = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marker_end), ALL_NO_PREFIX); + ATTR_MASK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mask), + ALL_NO_PREFIX); + ATTR_MARKER_START = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marker_start), ALL_NO_PREFIX); + ATTR_MARKERWIDTH = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::markerwidth, nsGkAtoms::markerWidth), + ALL_NO_PREFIX); + ATTR_MASKUNITS = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::maskunits, nsGkAtoms::maskUnits), + ALL_NO_PREFIX); + ATTR_MARKERUNITS = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::markerunits, nsGkAtoms::markerUnits), + ALL_NO_PREFIX); + ATTR_MASKCONTENTUNITS = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::maskcontentunits, nsGkAtoms::maskContentUnits), + ALL_NO_PREFIX); + ATTR_AMPLITUDE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::amplitude), ALL_NO_PREFIX); + ATTR_CELLSPACING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cellspacing), ALL_NO_PREFIX); + ATTR_CELLPADDING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cellpadding), ALL_NO_PREFIX); + ATTR_DECLARE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::declare), ALL_NO_PREFIX); + ATTR_FILL_RULE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fill_rule), ALL_NO_PREFIX); + ATTR_FILL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fill), + ALL_NO_PREFIX); + ATTR_FILL_OPACITY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fill_opacity), ALL_NO_PREFIX); + ATTR_MAXLENGTH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::maxlength), ALL_NO_PREFIX); + ATTR_ONCLICK = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onclick), ALL_NO_PREFIX); + ATTR_ONBLUR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onblur), ALL_NO_PREFIX); + ATTR_REPLACE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::replace), ALL_NO_PREFIX); + ATTR_ROWLINES = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowlines_), ALL_NO_PREFIX); + ATTR_SCALE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scale), + ALL_NO_PREFIX); + ATTR_STYLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::style), + ALL_NO_PREFIX); + ATTR_TABLEVALUES = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::tablevalues, nsGkAtoms::tableValues), + ALL_NO_PREFIX); + ATTR_TITLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::title), + ALL_NO_PREFIX); + ATTR_AZIMUTH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::azimuth), ALL_NO_PREFIX); + ATTR_FORMAT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::format), ALL_NO_PREFIX); + ATTR_FRAMEBORDER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::frameborder), ALL_NO_PREFIX); + ATTR_FRAME = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::frame), + ALL_NO_PREFIX); + ATTR_FRAMESPACING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::framespacing_), ALL_NO_PREFIX); + ATTR_FROM = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::from), + ALL_NO_PREFIX); + ATTR_FORM = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::form), + ALL_NO_PREFIX); + ATTR_PROMPT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::prompt), ALL_NO_PREFIX); + ATTR_PRIMITIVEUNITS = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::primitiveunits, nsGkAtoms::primitiveUnits), + ALL_NO_PREFIX); + ATTR_SYMMETRIC = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::symmetric_), ALL_NO_PREFIX); + ATTR_SUMMARY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::summary), ALL_NO_PREFIX); + ATTR_USEMAP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::usemap), ALL_NO_PREFIX); + ATTR_ZOOMANDPAN = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::zoomandpan, nsGkAtoms::zoomAndPan), + ALL_NO_PREFIX); + ATTR_ASYNC = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::async), + ALL_NO_PREFIX); + ATTR_ALINK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alink), + ALL_NO_PREFIX); + ATTR_IN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::in), + ALL_NO_PREFIX); + ATTR_ICON = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::icon), + ALL_NO_PREFIX); + ATTR_KERNELMATRIX = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::kernelmatrix, nsGkAtoms::kernelMatrix), + ALL_NO_PREFIX); + ATTR_KERNING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::kerning), ALL_NO_PREFIX); + ATTR_KERNELUNITLENGTH = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::kernelunitlength, nsGkAtoms::kernelUnitLength), + ALL_NO_PREFIX); + ATTR_ONUNLOAD = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onunload), ALL_NO_PREFIX); + ATTR_OPEN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::open), + ALL_NO_PREFIX); + ATTR_ONINVALID = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oninvalid), ALL_NO_PREFIX); + ATTR_ONEND = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onend), + ALL_NO_PREFIX); + ATTR_ONINPUT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oninput), ALL_NO_PREFIX); + ATTR_POINTER_EVENTS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::pointer_events), ALL_NO_PREFIX); + ATTR_POINTS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::points), ALL_NO_PREFIX); + ATTR_POINTSATX = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pointsatx, nsGkAtoms::pointsAtX), + ALL_NO_PREFIX); + ATTR_POINTSATY = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pointsaty, nsGkAtoms::pointsAtY), + ALL_NO_PREFIX); + ATTR_POINTSATZ = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pointsatz, nsGkAtoms::pointsAtZ), + ALL_NO_PREFIX); + ATTR_SPAN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::span), + ALL_NO_PREFIX); + ATTR_STANDBY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::standby), ALL_NO_PREFIX); + ATTR_TRANSFORM_ORIGIN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::transform_origin), ALL_NO_PREFIX); + ATTR_TRANSFORM = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::transform), ALL_NO_PREFIX); + ATTR_VLINK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::vlink), + ALL_NO_PREFIX); + ATTR_WHEN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::when), + ALL_NO_PREFIX); + ATTR_XLINK_HREF = new nsHtml5AttributeName( + XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_href, nsGkAtoms::href), + XLINK_PREFIX); + ATTR_XLINK_TITLE = new nsHtml5AttributeName( + XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_title, nsGkAtoms::title), + XLINK_PREFIX); + ATTR_XLINK_ROLE = new nsHtml5AttributeName( + XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_role, nsGkAtoms::role), + XLINK_PREFIX); + ATTR_XLINK_ARCROLE = new nsHtml5AttributeName( + XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_arcrole, nsGkAtoms::arcrole), + XLINK_PREFIX); + ATTR_XMLNS_XLINK = new nsHtml5AttributeName( + XMLNS_NS, COLONIFIED_LOCAL(nsGkAtoms::xmlns_xlink, nsGkAtoms::xlink), + XMLNS_PREFIX); + ATTR_XMLNS = new nsHtml5AttributeName(XMLNS_NS, SAME_LOCAL(nsGkAtoms::xmlns), + ALL_NO_PREFIX); + ATTR_XLINK_TYPE = new nsHtml5AttributeName( + XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_type, nsGkAtoms::type), + XLINK_PREFIX); + ATTR_XLINK_SHOW = new nsHtml5AttributeName( + XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_show, nsGkAtoms::show), + XLINK_PREFIX); + ATTR_XLINK_ACTUATE = new nsHtml5AttributeName( + XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_actuate, nsGkAtoms::actuate), + XLINK_PREFIX); + ATTR_AUTOPLAY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autoplay), ALL_NO_PREFIX); + ATTR_AUTOCOMPLETE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autocomplete), ALL_NO_PREFIX); + ATTR_AUTOFOCUS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autofocus), ALL_NO_PREFIX); + ATTR_AUTOCAPITALIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autocapitalize), ALL_NO_PREFIX); + ATTR_BGCOLOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::bgcolor), ALL_NO_PREFIX); + ATTR_COLOR_PROFILE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colorProfile), ALL_NO_PREFIX); + ATTR_COLOR_RENDERING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::color_rendering), ALL_NO_PREFIX); + ATTR_COLOR_INTERPOLATION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colorInterpolation), ALL_NO_PREFIX); + ATTR_COLOR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::color), + ALL_NO_PREFIX); + ATTR_COLOR_INTERPOLATION_FILTERS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colorInterpolationFilters), + ALL_NO_PREFIX); + ATTR_ENCODING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::encoding), ALL_NO_PREFIX); + ATTR_EXPONENT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::exponent), ALL_NO_PREFIX); + ATTR_FLOOD_COLOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::flood_color), ALL_NO_PREFIX); + ATTR_FLOOD_OPACITY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::flood_opacity), ALL_NO_PREFIX); + ATTR_LQUOTE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lquote_), ALL_NO_PREFIX); + ATTR_NUMOCTAVES = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::numoctaves, nsGkAtoms::numOctaves), + ALL_NO_PREFIX); + ATTR_NOMODULE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::nomodule), ALL_NO_PREFIX); + ATTR_ONLOAD = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onload), ALL_NO_PREFIX); + ATTR_ONMOUSEWHEEL = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmousewheel), ALL_NO_PREFIX); + ATTR_ONMOUSEENTER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseenter), ALL_NO_PREFIX); + ATTR_ONMOUSEOVER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseover), ALL_NO_PREFIX); + ATTR_ONFOCUSIN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfocusin), ALL_NO_PREFIX); + ATTR_ONCONTEXTMENU = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oncontextmenu), ALL_NO_PREFIX); + ATTR_ONZOOM = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onzoom), ALL_NO_PREFIX); + ATTR_ONCOPY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oncopy), ALL_NO_PREFIX); + ATTR_ONMOUSELEAVE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseleave), ALL_NO_PREFIX); + ATTR_ONMOUSEMOVE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmousemove), ALL_NO_PREFIX); + ATTR_ONMOUSEUP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseup), ALL_NO_PREFIX); + ATTR_ONFOCUS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfocus), ALL_NO_PREFIX); + ATTR_ONMOUSEOUT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseout), ALL_NO_PREFIX); + ATTR_ONFOCUSOUT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfocusout), ALL_NO_PREFIX); + ATTR_ONMOUSEDOWN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmousedown), ALL_NO_PREFIX); + ATTR_TO = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::to), + ALL_NO_PREFIX); + ATTR_RQUOTE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rquote_), ALL_NO_PREFIX); + ATTR_STROKE_LINECAP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_linecap), ALL_NO_PREFIX); + ATTR_STROKE_DASHARRAY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_dasharray), ALL_NO_PREFIX); + ATTR_STROKE_DASHOFFSET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_dashoffset), ALL_NO_PREFIX); + ATTR_STROKE_LINEJOIN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_linejoin), ALL_NO_PREFIX); + ATTR_STROKE_MITERLIMIT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_miterlimit), ALL_NO_PREFIX); + ATTR_STROKE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke), ALL_NO_PREFIX); + ATTR_SCROLLING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scrolling), ALL_NO_PREFIX); + ATTR_STROKE_WIDTH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_width), ALL_NO_PREFIX); + ATTR_STROKE_OPACITY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_opacity), ALL_NO_PREFIX); + ATTR_COMPACT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::compact), ALL_NO_PREFIX); + ATTR_CLIP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clip), + ALL_NO_PREFIX); + ATTR_CLIP_RULE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clip_rule), ALL_NO_PREFIX); + ATTR_CLIP_PATH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clip_path), ALL_NO_PREFIX); + ATTR_CLIPPATHUNITS = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::clippathunits, nsGkAtoms::clipPathUnits), + ALL_NO_PREFIX); + ATTR_DISPLAY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::display), ALL_NO_PREFIX); + ATTR_DISPLAYSTYLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::displaystyle_), ALL_NO_PREFIX); + ATTR_GLYPH_ORIENTATION_VERTICAL = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::glyph_orientation_vertical), + ALL_NO_PREFIX); + ATTR_GLYPH_ORIENTATION_HORIZONTAL = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::glyph_orientation_horizontal), + ALL_NO_PREFIX); + ATTR_GLYPHREF = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::glyphref, nsGkAtoms::glyphRef), + ALL_NO_PREFIX); + ATTR_HTTP_EQUIV = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::httpEquiv), ALL_NO_PREFIX); + ATTR_KEYPOINTS = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::keypoints, nsGkAtoms::keyPoints), + ALL_NO_PREFIX); + ATTR_LOOP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::loop), + ALL_NO_PREFIX); + ATTR_PROPERTY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::property), ALL_NO_PREFIX); + ATTR_SCOPED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scoped), ALL_NO_PREFIX); + ATTR_STEP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::step), + ALL_NO_PREFIX); + ATTR_SHAPE_RENDERING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::shape_rendering), ALL_NO_PREFIX); + ATTR_SCOPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scope), + ALL_NO_PREFIX); + ATTR_SHAPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::shape), + ALL_NO_PREFIX); + ATTR_SLOPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::slope), + ALL_NO_PREFIX); + ATTR_STOP_COLOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stop_color), ALL_NO_PREFIX); + ATTR_STOP_OPACITY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stop_opacity), ALL_NO_PREFIX); + ATTR_TEMPLATE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_template), ALL_NO_PREFIX); + ATTR_WRAP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::wrap), + ALL_NO_PREFIX); + ATTR_ABBR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::abbr), + ALL_NO_PREFIX); + ATTR_ATTRIBUTENAME = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::attributename, nsGkAtoms::attributeName), + ALL_NO_PREFIX); + ATTR_ATTRIBUTETYPE = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::attributetype, nsGkAtoms::attributeType), + ALL_NO_PREFIX); + ATTR_CHAR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_char), + ALL_NO_PREFIX); + ATTR_COORDS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::coords), ALL_NO_PREFIX); + ATTR_CHAROFF = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::charoff), ALL_NO_PREFIX); + ATTR_CHARSET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::charset), ALL_NO_PREFIX); + ATTR_NOWRAP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::nowrap), ALL_NO_PREFIX); + ATTR_NOHREF = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::nohref), ALL_NO_PREFIX); + ATTR_ONDRAG = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondrag), ALL_NO_PREFIX); + ATTR_ONDRAGENTER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragenter), ALL_NO_PREFIX); + ATTR_ONDRAGOVER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragover), ALL_NO_PREFIX); + ATTR_ONDRAGEND = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragend), ALL_NO_PREFIX); + ATTR_ONDROP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondrop), ALL_NO_PREFIX); + ATTR_ONDRAGDROP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragdrop), ALL_NO_PREFIX); + ATTR_ONERROR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onerror), ALL_NO_PREFIX); + ATTR_OPERATOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_operator), ALL_NO_PREFIX); + ATTR_OVERFLOW = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::overflow), ALL_NO_PREFIX); + ATTR_ONDRAGSTART = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragstart), ALL_NO_PREFIX); + ATTR_ONDRAGLEAVE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragleave), ALL_NO_PREFIX); + ATTR_STARTOFFSET = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::startoffset, nsGkAtoms::startOffset), + ALL_NO_PREFIX); + ATTR_START = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::start), + ALL_NO_PREFIX); + ATTR_AS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::as), + ALL_NO_PREFIX); + ATTR_AXIS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::axis), + ALL_NO_PREFIX); + ATTR_BIAS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::bias), + ALL_NO_PREFIX); + ATTR_COLSPAN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colspan), ALL_NO_PREFIX); + ATTR_CLASSID = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::classid), ALL_NO_PREFIX); + ATTR_CROSSORIGIN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::crossorigin), ALL_NO_PREFIX); + ATTR_COLS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cols), + ALL_NO_PREFIX); + ATTR_CURSOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cursor), ALL_NO_PREFIX); + ATTR_CLOSURE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::closure_), ALL_NO_PREFIX); + ATTR_CLOSE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::close), + ALL_NO_PREFIX); + ATTR_CLASS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_class), ALL_NO_PREFIX); + ATTR_IS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::is), + ALL_NO_PREFIX); + ATTR_KEYSYSTEM = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::keysystem), ALL_NO_PREFIX); + ATTR_KEYSPLINES = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::keysplines, nsGkAtoms::keySplines), + ALL_NO_PREFIX); + ATTR_LOWSRC = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lowsrc), ALL_NO_PREFIX); + ATTR_MAXSIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::maxsize_), ALL_NO_PREFIX); + ATTR_MINSIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::minsize_), ALL_NO_PREFIX); + ATTR_OFFSET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::offset), ALL_NO_PREFIX); + ATTR_PRESERVEALPHA = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::preservealpha, nsGkAtoms::preserveAlpha), + ALL_NO_PREFIX); + ATTR_PRESERVEASPECTRATIO = + new nsHtml5AttributeName(ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::preserveaspectratio, + nsGkAtoms::preserveAspectRatio), + ALL_NO_PREFIX); + ATTR_ROWSPAN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowspan), ALL_NO_PREFIX); + ATTR_ROWSPACING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowspacing_), ALL_NO_PREFIX); + ATTR_ROWS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rows), + ALL_NO_PREFIX); + ATTR_SRCSET = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::srcset), ALL_NO_PREFIX); + ATTR_SUBSCRIPTSHIFT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::subscriptshift_), ALL_NO_PREFIX); + ATTR_VERSION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::version), ALL_NO_PREFIX); + ATTR_ALTTEXT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alttext), ALL_NO_PREFIX); + ATTR_CONTENTEDITABLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::contenteditable), ALL_NO_PREFIX); + ATTR_CONTROLS = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::controls), ALL_NO_PREFIX); + ATTR_CONTENT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::content), ALL_NO_PREFIX); + ATTR_CONTEXTMENU = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::contextmenu), ALL_NO_PREFIX); + ATTR_DEPTH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::depth_), ALL_NO_PREFIX); + ATTR_ENCTYPE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::enctype), ALL_NO_PREFIX); + ATTR_FONT_STRETCH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_stretch), ALL_NO_PREFIX); + ATTR_FILTER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::filter), ALL_NO_PREFIX); + ATTR_FONTWEIGHT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontweight_), ALL_NO_PREFIX); + ATTR_FONT_WEIGHT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontWeight), ALL_NO_PREFIX); + ATTR_FONTSTYLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontstyle_), ALL_NO_PREFIX); + ATTR_FONT_STYLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_style), ALL_NO_PREFIX); + ATTR_FONTFAMILY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontfamily_), ALL_NO_PREFIX); + ATTR_FONT_FAMILY = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_family), ALL_NO_PREFIX); + ATTR_FONT_VARIANT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_variant), ALL_NO_PREFIX); + ATTR_FONT_SIZE_ADJUST = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_size_adjust), ALL_NO_PREFIX); + ATTR_FILTERUNITS = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::filterunits, nsGkAtoms::filterUnits), + ALL_NO_PREFIX); + ATTR_FONTSIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontsize_), ALL_NO_PREFIX); + ATTR_FONT_SIZE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_size), ALL_NO_PREFIX); + ATTR_KEYTIMES = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::keytimes, nsGkAtoms::keyTimes), + ALL_NO_PREFIX); + ATTR_LETTER_SPACING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::letter_spacing), ALL_NO_PREFIX); + ATTR_LIST = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::list_), + ALL_NO_PREFIX); + ATTR_MULTIPLE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::multiple), ALL_NO_PREFIX); + ATTR_RT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rt), + ALL_NO_PREFIX); + ATTR_ONSTOP = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onstop), ALL_NO_PREFIX); + ATTR_ONSTART = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onstart), ALL_NO_PREFIX); + ATTR_POSTER = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::poster), ALL_NO_PREFIX); + ATTR_PATTERNTRANSFORM = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::patterntransform, nsGkAtoms::patternTransform), + ALL_NO_PREFIX); + ATTR_PATTERN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::pattern), ALL_NO_PREFIX); + ATTR_PATTERNUNITS = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::patternunits, nsGkAtoms::patternUnits), + ALL_NO_PREFIX); + ATTR_PATTERNCONTENTUNITS = + new nsHtml5AttributeName(ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::patterncontentunits, + nsGkAtoms::patternContentUnits), + ALL_NO_PREFIX); + ATTR_RESTART = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::restart), ALL_NO_PREFIX); + ATTR_STITCHTILES = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::stitchtiles, nsGkAtoms::stitchTiles), + ALL_NO_PREFIX); + ATTR_SYSTEMLANGUAGE = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::systemlanguage, nsGkAtoms::systemLanguage), + ALL_NO_PREFIX); + ATTR_TEXT_RENDERING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text_rendering), ALL_NO_PREFIX); + ATTR_TEXT_DECORATION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text_decoration), ALL_NO_PREFIX); + ATTR_TEXT_ANCHOR = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text_anchor), ALL_NO_PREFIX); + ATTR_TEXTLENGTH = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::textlength, nsGkAtoms::textLength), + ALL_NO_PREFIX); + ATTR_TEXT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text), + ALL_NO_PREFIX); + ATTR_WRITING_MODE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::writing_mode), ALL_NO_PREFIX); + ATTR_WIDTH = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::width), + ALL_NO_PREFIX); + ATTR_ACCUMULATE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accumulate), ALL_NO_PREFIX); + ATTR_COLUMNSPAN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnspan_), ALL_NO_PREFIX); + ATTR_COLUMNLINES = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnlines_), ALL_NO_PREFIX); + ATTR_COLUMNALIGN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnalign_), ALL_NO_PREFIX); + ATTR_COLUMNSPACING = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnspacing_), ALL_NO_PREFIX); + ATTR_COLUMNWIDTH = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnwidth_), ALL_NO_PREFIX); + ATTR_GROUPALIGN = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::groupalign_), ALL_NO_PREFIX); + ATTR_INPUTMODE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::inputmode), ALL_NO_PREFIX); + ATTR_ONSUBMIT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onsubmit), ALL_NO_PREFIX); + ATTR_ONCUT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oncut), + ALL_NO_PREFIX); + ATTR_REQUIRED = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::required), ALL_NO_PREFIX); + ATTR_REQUIREDFEATURES = new nsHtml5AttributeName( + ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::requiredfeatures, nsGkAtoms::requiredFeatures), + ALL_NO_PREFIX); + ATTR_RESULT = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::result), ALL_NO_PREFIX); + ATTR_REQUIREDEXTENSIONS = + new nsHtml5AttributeName(ALL_NO_NS, + SVG_DIFFERENT(nsGkAtoms::requiredextensions, + nsGkAtoms::requiredExtensions), + ALL_NO_PREFIX); + ATTR_VALUES = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::values), ALL_NO_PREFIX); + ATTR_VALUETYPE = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::valuetype), ALL_NO_PREFIX); + ATTR_VALUE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::value), + ALL_NO_PREFIX); + ATTR_ELEVATION = new nsHtml5AttributeName( + ALL_NO_NS, SAME_LOCAL(nsGkAtoms::elevation), ALL_NO_PREFIX); + ATTR_VIEWTARGET = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::viewtarget, nsGkAtoms::viewTarget), + ALL_NO_PREFIX); + ATTR_VIEWBOX = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::viewbox, nsGkAtoms::viewBox), + ALL_NO_PREFIX); + ATTR_CX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cx), + ALL_NO_PREFIX); + ATTR_DX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dx), + ALL_NO_PREFIX); + ATTR_FX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fx), + ALL_NO_PREFIX); + ATTR_RX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rx), + ALL_NO_PREFIX); + ATTR_REFX = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::refx, nsGkAtoms::refX), + ALL_NO_PREFIX); + ATTR_BY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::by), + ALL_NO_PREFIX); + ATTR_CY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cy), + ALL_NO_PREFIX); + ATTR_DY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dy), + ALL_NO_PREFIX); + ATTR_FY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fy), + ALL_NO_PREFIX); + ATTR_RY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ry), + ALL_NO_PREFIX); + ATTR_REFY = new nsHtml5AttributeName( + ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::refy, nsGkAtoms::refY), + ALL_NO_PREFIX); + ATTRIBUTE_NAMES = new nsHtml5AttributeName*[499]; + ATTRIBUTE_NAMES[0] = ATTR_FILL; + ATTRIBUTE_NAMES[1] = ATTR_DATETIME; + ATTRIBUTE_NAMES[2] = ATTR_CHAROFF; + ATTRIBUTE_NAMES[3] = ATTR_CLEAR; + ATTRIBUTE_NAMES[4] = ATTR_IMAGESRCSET; + ATTRIBUTE_NAMES[5] = ATTR_COLOR; + ATTRIBUTE_NAMES[6] = ATTR_LETTER_SPACING; + ATTRIBUTE_NAMES[7] = ATTR_ARIA_DISABLED; + ATTRIBUTE_NAMES[8] = ATTR_SPECULAREXPONENT; + ATTRIBUTE_NAMES[9] = ATTR_ONKEYUP; + ATTRIBUTE_NAMES[10] = ATTR_DOMINANT_BASELINE; + ATTRIBUTE_NAMES[11] = ATTR_OPEN; + ATTRIBUTE_NAMES[12] = ATTR_SCROLLING; + ATTRIBUTE_NAMES[13] = ATTR_MAXSIZE; + ATTRIBUTE_NAMES[14] = ATTR_REQUIREDFEATURES; + ATTRIBUTE_NAMES[15] = ATTR_Y; + ATTRIBUTE_NAMES[16] = ATTR_ARIA_MULTISELECTABLE; + ATTRIBUTE_NAMES[17] = ATTR_ROTATE; + ATTRIBUTE_NAMES[18] = ATTR_ACCENTUNDER; + ATTRIBUTE_NAMES[19] = ATTR_ONREPEAT; + ATTRIBUTE_NAMES[20] = ATTR_SELECTION; + ATTRIBUTE_NAMES[21] = ATTR_LIGHTING_COLOR; + ATTRIBUTE_NAMES[22] = ATTR_BACKGROUND; + ATTRIBUTE_NAMES[23] = ATTR_FROM; + ATTRIBUTE_NAMES[24] = ATTR_XLINK_TITLE; + ATTRIBUTE_NAMES[25] = ATTR_ONCOPY; + ATTRIBUTE_NAMES[26] = ATTR_PROPERTY; + ATTRIBUTE_NAMES[27] = ATTR_START; + ATTRIBUTE_NAMES[28] = ATTR_DEPTH; + ATTRIBUTE_NAMES[29] = ATTR_TEXT_ANCHOR; + ATTRIBUTE_NAMES[30] = ATTR_RX; + ATTRIBUTE_NAMES[31] = ATTR_MIN; + ATTRIBUTE_NAMES[32] = ATTR_K3; + ATTRIBUTE_NAMES[33] = ATTR_ARIA_CHANNEL; + ATTRIBUTE_NAMES[34] = ATTR_ARIA_VALUENOW; + ATTRIBUTE_NAMES[35] = ATTR_LOCAL; + ATTRIBUTE_NAMES[36] = ATTR_ONABORT; + ATTRIBUTE_NAMES[37] = ATTR_LOADING; + ATTRIBUTE_NAMES[38] = ATTR_BASEPROFILE; + ATTRIBUTE_NAMES[39] = ATTR_INTEGRITY; + ATTRIBUTE_NAMES[40] = ATTR_ONBEGIN; + ATTRIBUTE_NAMES[41] = ATTR_REPEATCOUNT; + ATTRIBUTE_NAMES[42] = ATTR_SURFACESCALE; + ATTRIBUTE_NAMES[43] = ATTR_MARGINWIDTH; + ATTRIBUTE_NAMES[44] = ATTR_PATHLENGTH; + ATTRIBUTE_NAMES[45] = ATTR_RADIOGROUP; + ATTRIBUTE_NAMES[46] = ATTR_MASKUNITS; + ATTRIBUTE_NAMES[47] = ATTR_STYLE; + ATTRIBUTE_NAMES[48] = ATTR_ASYNC; + ATTRIBUTE_NAMES[49] = ATTR_POINTSATZ; + ATTRIBUTE_NAMES[50] = ATTR_AUTOPLAY; + ATTRIBUTE_NAMES[51] = ATTR_NOMODULE; + ATTRIBUTE_NAMES[52] = ATTR_TO; + ATTRIBUTE_NAMES[53] = ATTR_DISPLAY; + ATTRIBUTE_NAMES[54] = ATTR_STOP_OPACITY; + ATTRIBUTE_NAMES[55] = ATTR_ONDROP; + ATTRIBUTE_NAMES[56] = ATTR_CURSOR; + ATTRIBUTE_NAMES[57] = ATTR_SRCSET; + ATTRIBUTE_NAMES[58] = ATTR_FONTFAMILY; + ATTRIBUTE_NAMES[59] = ATTR_PATTERN; + ATTRIBUTE_NAMES[60] = ATTR_COLUMNALIGN; + ATTRIBUTE_NAMES[61] = ATTR_VIEWBOX; + ATTRIBUTE_NAMES[62] = ATTR_DY; + ATTRIBUTE_NAMES[63] = ATTR_END; + ATTRIBUTE_NAMES[64] = ATTR_SRC; + ATTRIBUTE_NAMES[65] = ATTR_Y1; + ATTRIBUTE_NAMES[66] = ATTR_ARIA_GRAB; + ATTRIBUTE_NAMES[67] = ATTR_ARIA_REQUIRED; + ATTRIBUTE_NAMES[68] = ATTR_ARIA_ATOMIC; + ATTRIBUTE_NAMES[69] = ATTR_ARIA_OWNS; + ATTRIBUTE_NAMES[70] = ATTR_ARIA_BUSY; + ATTRIBUTE_NAMES[71] = ATTR_EQUALCOLUMNS; + ATTRIBUTE_NAMES[72] = ATTR_ONDATAAVAILABLE; + ATTRIBUTE_NAMES[73] = ATTR_XCHANNELSELECTOR; + ATTRIBUTE_NAMES[74] = ATTR_ONSCROLL; + ATTRIBUTE_NAMES[75] = ATTR_GRADIENTTRANSFORM; + ATTRIBUTE_NAMES[76] = ATTR_SRCDOC; + ATTRIBUTE_NAMES[77] = ATTR_ACCEPT; + ATTRIBUTE_NAMES[78] = ATTR_CODETYPE; + ATTRIBUTE_NAMES[79] = ATTR_ENTERKEYHINT; + ATTRIBUTE_NAMES[80] = ATTR_MODE; + ATTRIBUTE_NAMES[81] = ATTR_OTHER; + ATTRIBUTE_NAMES[82] = ATTR_ONBEFORECOPY; + ATTRIBUTE_NAMES[83] = ATTR_REPEAT; + ATTRIBUTE_NAMES[84] = ATTR_SUPERSCRIPTSHIFT; + ATTRIBUTE_NAMES[85] = ATTR_HREF; + ATTRIBUTE_NAMES[86] = ATTR_ALIGNMENTSCOPE; + ATTRIBUTE_NAMES[87] = ATTR_LARGEOP; + ATTRIBUTE_NAMES[88] = ATTR_TARGETX; + ATTRIBUTE_NAMES[89] = ATTR_MATHCOLOR; + ATTRIBUTE_NAMES[90] = ATTR_ACTION; + ATTRIBUTE_NAMES[91] = ATTR_MEDIA; + ATTRIBUTE_NAMES[92] = ATTR_SCRIPTMINSIZE; + ATTRIBUTE_NAMES[93] = ATTR_MARKER_END; + ATTRIBUTE_NAMES[94] = ATTR_CELLSPACING; + ATTRIBUTE_NAMES[95] = ATTR_ONBLUR; + ATTRIBUTE_NAMES[96] = ATTR_FORMAT; + ATTRIBUTE_NAMES[97] = ATTR_SYMMETRIC; + ATTRIBUTE_NAMES[98] = ATTR_KERNELMATRIX; + ATTRIBUTE_NAMES[99] = ATTR_POINTER_EVENTS; + ATTRIBUTE_NAMES[100] = ATTR_TRANSFORM; + ATTRIBUTE_NAMES[101] = ATTR_XMLNS; + ATTRIBUTE_NAMES[102] = ATTR_BGCOLOR; + ATTRIBUTE_NAMES[103] = ATTR_FLOOD_COLOR; + ATTRIBUTE_NAMES[104] = ATTR_ONMOUSEOVER; + ATTRIBUTE_NAMES[105] = ATTR_ONFOCUS; + ATTRIBUTE_NAMES[106] = ATTR_STROKE_DASHOFFSET; + ATTRIBUTE_NAMES[107] = ATTR_CLIP; + ATTRIBUTE_NAMES[108] = ATTR_GLYPHREF; + ATTRIBUTE_NAMES[109] = ATTR_SCOPE; + ATTRIBUTE_NAMES[110] = ATTR_ATTRIBUTENAME; + ATTRIBUTE_NAMES[111] = ATTR_ONDRAG; + ATTRIBUTE_NAMES[112] = ATTR_OVERFLOW; + ATTRIBUTE_NAMES[113] = ATTR_COLSPAN; + ATTRIBUTE_NAMES[114] = ATTR_IS; + ATTRIBUTE_NAMES[115] = ATTR_PRESERVEASPECTRATIO; + ATTRIBUTE_NAMES[116] = ATTR_CONTENTEDITABLE; + ATTRIBUTE_NAMES[117] = ATTR_FONTWEIGHT; + ATTRIBUTE_NAMES[118] = ATTR_FILTERUNITS; + ATTRIBUTE_NAMES[119] = ATTR_ONSTOP; + ATTRIBUTE_NAMES[120] = ATTR_STITCHTILES; + ATTRIBUTE_NAMES[121] = ATTR_WIDTH; + ATTRIBUTE_NAMES[122] = ATTR_INPUTMODE; + ATTRIBUTE_NAMES[123] = ATTR_VALUETYPE; + ATTRIBUTE_NAMES[124] = ATTR_DX; + ATTRIBUTE_NAMES[125] = ATTR_BY; + ATTRIBUTE_NAMES[126] = ATTR_RY; + ATTRIBUTE_NAMES[127] = ATTR_DIR; + ATTRIBUTE_NAMES[128] = ATTR_IN2; + ATTRIBUTE_NAMES[129] = ATTR_REL; + ATTRIBUTE_NAMES[130] = ATTR_R; + ATTRIBUTE_NAMES[131] = ATTR_K1; + ATTRIBUTE_NAMES[132] = ATTR_X2; + ATTRIBUTE_NAMES[133] = ATTR_XML_SPACE; + ATTRIBUTE_NAMES[134] = ATTR_ARIA_LABELLEDBY; + ATTRIBUTE_NAMES[135] = ATTR_ARIA_SELECTED; + ATTRIBUTE_NAMES[136] = ATTR_ARIA_PRESSED; + ATTRIBUTE_NAMES[137] = ATTR_ARIA_SECRET; + ATTRIBUTE_NAMES[138] = ATTR_ARIA_TEMPLATEID; + ATTRIBUTE_NAMES[139] = ATTR_ARIA_MULTILINE; + ATTRIBUTE_NAMES[140] = ATTR_ARIA_RELEVANT; + ATTRIBUTE_NAMES[141] = ATTR_ARIA_AUTOCOMPLETE; + ATTRIBUTE_NAMES[142] = ATTR_ARIA_HASPOPUP; + ATTRIBUTE_NAMES[143] = ATTR_DEFAULT; + ATTRIBUTE_NAMES[144] = ATTR_HSPACE; + ATTRIBUTE_NAMES[145] = ATTR_MOVABLELIMITS; + ATTRIBUTE_NAMES[146] = ATTR_RSPACE; + ATTRIBUTE_NAMES[147] = ATTR_SEPARATORS; + ATTRIBUTE_NAMES[148] = ATTR_ENABLE_BACKGROUND; + ATTRIBUTE_NAMES[149] = ATTR_CHECKED; + ATTRIBUTE_NAMES[150] = ATTR_OPACITY; + ATTRIBUTE_NAMES[151] = ATTR_BORDER; + ATTRIBUTE_NAMES[152] = ATTR_HIDDEN; + ATTRIBUTE_NAMES[153] = ATTR_RENDERING_INTENT; + ATTRIBUTE_NAMES[154] = ATTR_SANDBOX; + ATTRIBUTE_NAMES[155] = ATTR_ACCESSKEY; + ATTRIBUTE_NAMES[156] = ATTR_BASEFREQUENCY; + ATTRIBUTE_NAMES[157] = ATTR_BASE; + ATTRIBUTE_NAMES[158] = ATTR_CITE; + ATTRIBUTE_NAMES[159] = ATTR_EDGEMODE; + ATTRIBUTE_NAMES[160] = ATTR_INDEX; + ATTRIBUTE_NAMES[161] = ATTR_LABEL; + ATTRIBUTE_NAMES[162] = ATTR_NORESIZE; + ATTRIBUTE_NAMES[163] = ATTR_ONSELECT; + ATTRIBUTE_NAMES[164] = ATTR_ONREADYSTATECHANGE; + ATTRIBUTE_NAMES[165] = ATTR_ORIENT; + ATTRIBUTE_NAMES[166] = ATTR_ONBEFOREPASTE; + ATTRIBUTE_NAMES[167] = ATTR_ONKEYDOWN; + ATTRIBUTE_NAMES[168] = ATTR_RULES; + ATTRIBUTE_NAMES[169] = ATTR_SELECTED; + ATTRIBUTE_NAMES[170] = ATTR_SCHEME; + ATTRIBUTE_NAMES[171] = ATTR_TYPE; + ATTRIBUTE_NAMES[172] = ATTR_ONAFTERPRINT; + ATTRIBUTE_NAMES[173] = ATTR_ALIGN; + ATTRIBUTE_NAMES[174] = ATTR_HEIGHT; + ATTRIBUTE_NAMES[175] = ATTR_LANGUAGE; + ATTRIBUTE_NAMES[176] = ATTR_LENGTHADJUST; + ATTRIBUTE_NAMES[177] = ATTR_PING; + ATTRIBUTE_NAMES[178] = ATTR_ARCHIVE; + ATTRIBUTE_NAMES[179] = ATTR_METHOD; + ATTRIBUTE_NAMES[180] = ATTR_NOSHADE; + ATTRIBUTE_NAMES[181] = ATTR_ALTIMG; + ATTRIBUTE_NAMES[182] = ATTR_ADDITIVE; + ATTRIBUTE_NAMES[183] = ATTR_DEFINITIONURL; + ATTRIBUTE_NAMES[184] = ATTR_ONFINISH; + ATTRIBUTE_NAMES[185] = ATTR_SCRIPTLEVEL; + ATTRIBUTE_NAMES[186] = ATTR_VALIGN; + ATTRIBUTE_NAMES[187] = ATTR_MARKER_MID; + ATTRIBUTE_NAMES[188] = ATTR_MARKER_START; + ATTRIBUTE_NAMES[189] = ATTR_MASKCONTENTUNITS; + ATTRIBUTE_NAMES[190] = ATTR_DECLARE; + ATTRIBUTE_NAMES[191] = ATTR_MAXLENGTH; + ATTRIBUTE_NAMES[192] = ATTR_ROWLINES; + ATTRIBUTE_NAMES[193] = ATTR_TITLE; + ATTRIBUTE_NAMES[194] = ATTR_FRAME; + ATTRIBUTE_NAMES[195] = ATTR_PROMPT; + ATTRIBUTE_NAMES[196] = ATTR_USEMAP; + ATTRIBUTE_NAMES[197] = ATTR_IN; + ATTRIBUTE_NAMES[198] = ATTR_KERNELUNITLENGTH; + ATTRIBUTE_NAMES[199] = ATTR_ONEND; + ATTRIBUTE_NAMES[200] = ATTR_POINTSATX; + ATTRIBUTE_NAMES[201] = ATTR_STANDBY; + ATTRIBUTE_NAMES[202] = ATTR_WHEN; + ATTRIBUTE_NAMES[203] = ATTR_XLINK_ARCROLE; + ATTRIBUTE_NAMES[204] = ATTR_XLINK_SHOW; + ATTRIBUTE_NAMES[205] = ATTR_AUTOFOCUS; + ATTRIBUTE_NAMES[206] = ATTR_COLOR_RENDERING; + ATTRIBUTE_NAMES[207] = ATTR_ENCODING; + ATTRIBUTE_NAMES[208] = ATTR_LQUOTE; + ATTRIBUTE_NAMES[209] = ATTR_ONMOUSEWHEEL; + ATTRIBUTE_NAMES[210] = ATTR_ONCONTEXTMENU; + ATTRIBUTE_NAMES[211] = ATTR_ONMOUSEMOVE; + ATTRIBUTE_NAMES[212] = ATTR_ONFOCUSOUT; + ATTRIBUTE_NAMES[213] = ATTR_STROKE_LINECAP; + ATTRIBUTE_NAMES[214] = ATTR_STROKE_MITERLIMIT; + ATTRIBUTE_NAMES[215] = ATTR_STROKE_OPACITY; + ATTRIBUTE_NAMES[216] = ATTR_CLIP_PATH; + ATTRIBUTE_NAMES[217] = ATTR_GLYPH_ORIENTATION_VERTICAL; + ATTRIBUTE_NAMES[218] = ATTR_KEYPOINTS; + ATTRIBUTE_NAMES[219] = ATTR_STEP; + ATTRIBUTE_NAMES[220] = ATTR_SLOPE; + ATTRIBUTE_NAMES[221] = ATTR_WRAP; + ATTRIBUTE_NAMES[222] = ATTR_CHAR; + ATTRIBUTE_NAMES[223] = ATTR_NOWRAP; + ATTRIBUTE_NAMES[224] = ATTR_ONDRAGOVER; + ATTRIBUTE_NAMES[225] = ATTR_ONERROR; + ATTRIBUTE_NAMES[226] = ATTR_ONDRAGLEAVE; + ATTRIBUTE_NAMES[227] = ATTR_AXIS; + ATTRIBUTE_NAMES[228] = ATTR_CROSSORIGIN; + ATTRIBUTE_NAMES[229] = ATTR_CLOSE; + ATTRIBUTE_NAMES[230] = ATTR_KEYSPLINES; + ATTRIBUTE_NAMES[231] = ATTR_OFFSET; + ATTRIBUTE_NAMES[232] = ATTR_ROWSPACING; + ATTRIBUTE_NAMES[233] = ATTR_VERSION; + ATTRIBUTE_NAMES[234] = ATTR_CONTENT; + ATTRIBUTE_NAMES[235] = ATTR_FONT_STRETCH; + ATTRIBUTE_NAMES[236] = ATTR_FONTSTYLE; + ATTRIBUTE_NAMES[237] = ATTR_FONT_VARIANT; + ATTRIBUTE_NAMES[238] = ATTR_FONT_SIZE; + ATTRIBUTE_NAMES[239] = ATTR_MULTIPLE; + ATTRIBUTE_NAMES[240] = ATTR_POSTER; + ATTRIBUTE_NAMES[241] = ATTR_PATTERNCONTENTUNITS; + ATTRIBUTE_NAMES[242] = ATTR_TEXT_RENDERING; + ATTRIBUTE_NAMES[243] = ATTR_TEXT; + ATTRIBUTE_NAMES[244] = ATTR_COLUMNSPAN; + ATTRIBUTE_NAMES[245] = ATTR_COLUMNWIDTH; + ATTRIBUTE_NAMES[246] = ATTR_ONCUT; + ATTRIBUTE_NAMES[247] = ATTR_REQUIREDEXTENSIONS; + ATTRIBUTE_NAMES[248] = ATTR_ELEVATION; + ATTRIBUTE_NAMES[249] = ATTR_CX; + ATTRIBUTE_NAMES[250] = ATTR_FX; + ATTRIBUTE_NAMES[251] = ATTR_REFX; + ATTRIBUTE_NAMES[252] = ATTR_CY; + ATTRIBUTE_NAMES[253] = ATTR_FY; + ATTRIBUTE_NAMES[254] = ATTR_REFY; + ATTRIBUTE_NAMES[255] = ATTR_ALT; + ATTRIBUTE_NAMES[256] = ATTR_DUR; + ATTRIBUTE_NAMES[257] = ATTR_FOR; + ATTRIBUTE_NAMES[258] = ATTR_LOW; + ATTRIBUTE_NAMES[259] = ATTR_MAX; + ATTRIBUTE_NAMES[260] = ATTR_REV; + ATTRIBUTE_NAMES[261] = ATTR_D; + ATTRIBUTE_NAMES[262] = ATTR_X; + ATTRIBUTE_NAMES[263] = ATTR_Z; + ATTRIBUTE_NAMES[264] = ATTR_X1; + ATTRIBUTE_NAMES[265] = ATTR_K2; + ATTRIBUTE_NAMES[266] = ATTR_Y2; + ATTRIBUTE_NAMES[267] = ATTR_K4; + ATTRIBUTE_NAMES[268] = ATTR_XML_LANG; + ATTRIBUTE_NAMES[269] = ATTR_ARIA_VALUEMAX; + ATTRIBUTE_NAMES[270] = ATTR_ARIA_DESCRIBEDBY; + ATTRIBUTE_NAMES[271] = ATTR_ARIA_CHECKED; + ATTRIBUTE_NAMES[272] = ATTR_ARIA_DROPEFFECT; + ATTRIBUTE_NAMES[273] = ATTR_ARIA_EXPANDED; + ATTRIBUTE_NAMES[274] = ATTR_ARIA_LEVEL; + ATTRIBUTE_NAMES[275] = ATTR_ARIA_HIDDEN; + ATTRIBUTE_NAMES[276] = ATTR_ARIA_POSINSET; + ATTRIBUTE_NAMES[277] = ATTR_ARIA_INVALID; + ATTRIBUTE_NAMES[278] = ATTR_ARIA_VALUEMIN; + ATTRIBUTE_NAMES[279] = ATTR_ARIA_CONTROLS; + ATTRIBUTE_NAMES[280] = ATTR_ARIA_READONLY; + ATTRIBUTE_NAMES[281] = ATTR_ARIA_ACTIVEDESCENDANT; + ATTRIBUTE_NAMES[282] = ATTR_ARIA_DATATYPE; + ATTRIBUTE_NAMES[283] = ATTR_ARIA_SORT; + ATTRIBUTE_NAMES[284] = ATTR_ARIA_FLOWTO; + ATTRIBUTE_NAMES[285] = ATTR_ARIA_LIVE; + ATTRIBUTE_NAMES[286] = ATTR_ARIA_SETSIZE; + ATTRIBUTE_NAMES[287] = ATTR_DISABLED; + ATTRIBUTE_NAMES[288] = ATTR_DATA; + ATTRIBUTE_NAMES[289] = ATTR_EQUALROWS; + ATTRIBUTE_NAMES[290] = ATTR_ISMAP; + ATTRIBUTE_NAMES[291] = ATTR_LSPACE; + ATTRIBUTE_NAMES[292] = ATTR_NOTATION; + ATTRIBUTE_NAMES[293] = ATTR_ONPASTE; + ATTRIBUTE_NAMES[294] = ATTR_ROWALIGN; + ATTRIBUTE_NAMES[295] = ATTR_SEPARATOR; + ATTRIBUTE_NAMES[296] = ATTR_VSPACE; + ATTRIBUTE_NAMES[297] = ATTR_YCHANNELSELECTOR; + ATTRIBUTE_NAMES[298] = ATTR_ONDBLCLICK; + ATTRIBUTE_NAMES[299] = ATTR_CALCMODE; + ATTRIBUTE_NAMES[300] = ATTR_FENCE; + ATTRIBUTE_NAMES[301] = ATTR_ONACTIVATE; + ATTRIBUTE_NAMES[302] = ATTR_SPACING; + ATTRIBUTE_NAMES[303] = ATTR_SPECULARCONSTANT; + ATTRIBUTE_NAMES[304] = ATTR_ID; + ATTRIBUTE_NAMES[305] = ATTR_GRADIENTUNITS; + ATTRIBUTE_NAMES[306] = ATTR_HEADERS; + ATTRIBUTE_NAMES[307] = ATTR_READONLY; + ATTRIBUTE_NAMES[308] = ATTR_SEED; + ATTRIBUTE_NAMES[309] = ATTR_STDDEVIATION; + ATTRIBUTE_NAMES[310] = ATTR_WORD_SPACING; + ATTRIBUTE_NAMES[311] = ATTR_ACCEPT_CHARSET; + ATTRIBUTE_NAMES[312] = ATTR_ACCENT; + ATTRIBUTE_NAMES[313] = ATTR_BEVELLED; + ATTRIBUTE_NAMES[314] = ATTR_BASELINE_SHIFT; + ATTRIBUTE_NAMES[315] = ATTR_BASELINE; + ATTRIBUTE_NAMES[316] = ATTR_CODE; + ATTRIBUTE_NAMES[317] = ATTR_CODEBASE; + ATTRIBUTE_NAMES[318] = ATTR_DEFER; + ATTRIBUTE_NAMES[319] = ATTR_DIRECTION; + ATTRIBUTE_NAMES[320] = ATTR_EDGE; + ATTRIBUTE_NAMES[321] = ATTR_FACE; + ATTRIBUTE_NAMES[322] = ATTR_INTERCEPT; + ATTRIBUTE_NAMES[323] = ATTR_LINEBREAK; + ATTRIBUTE_NAMES[324] = ATTR_LINETHICKNESS; + ATTRIBUTE_NAMES[325] = ATTR_NAME; + ATTRIBUTE_NAMES[326] = ATTR_ONBEFOREUNLOAD; + ATTRIBUTE_NAMES[327] = ATTR_OBJECT; + ATTRIBUTE_NAMES[328] = ATTR_ORDER; + ATTRIBUTE_NAMES[329] = ATTR_ONRESET; + ATTRIBUTE_NAMES[330] = ATTR_ONMESSAGE; + ATTRIBUTE_NAMES[331] = ATTR_ONBEFOREPRINT; + ATTRIBUTE_NAMES[332] = ATTR_ORIENTATION; + ATTRIBUTE_NAMES[333] = ATTR_ONSELECTSTART; + ATTRIBUTE_NAMES[334] = ATTR_ONKEYPRESS; + ATTRIBUTE_NAMES[335] = ATTR_ONBEFORECUT; + ATTRIBUTE_NAMES[336] = ATTR_ONRESIZE; + ATTRIBUTE_NAMES[337] = ATTR_REFERRERPOLICY; + ATTRIBUTE_NAMES[338] = ATTR_ROLE; + ATTRIBUTE_NAMES[339] = ATTR_REPEATDUR; + ATTRIBUTE_NAMES[340] = ATTR_SIZES; + ATTRIBUTE_NAMES[341] = ATTR_STRETCHY; + ATTRIBUTE_NAMES[342] = ATTR_SPREADMETHOD; + ATTRIBUTE_NAMES[343] = ATTR_SIZE; + ATTRIBUTE_NAMES[344] = ATTR_DIFFUSECONSTANT; + ATTRIBUTE_NAMES[345] = ATTR_HREFLANG; + ATTRIBUTE_NAMES[346] = ATTR_PROFILE; + ATTRIBUTE_NAMES[347] = ATTR_XREF; + ATTRIBUTE_NAMES[348] = ATTR_ALIGNMENT_BASELINE; + ATTRIBUTE_NAMES[349] = ATTR_DRAGGABLE; + ATTRIBUTE_NAMES[350] = ATTR_IMAGESIZES; + ATTRIBUTE_NAMES[351] = ATTR_IMAGE_RENDERING; + ATTRIBUTE_NAMES[352] = ATTR_LANG; + ATTRIBUTE_NAMES[353] = ATTR_LONGDESC; + ATTRIBUTE_NAMES[354] = ATTR_MARGINHEIGHT; + ATTRIBUTE_NAMES[355] = ATTR_ORIGIN; + ATTRIBUTE_NAMES[356] = ATTR_TARGET; + ATTRIBUTE_NAMES[357] = ATTR_TARGETY; + ATTRIBUTE_NAMES[358] = ATTR_HIGH; + ATTRIBUTE_NAMES[359] = ATTR_MATHBACKGROUND; + ATTRIBUTE_NAMES[360] = ATTR_MATHVARIANT; + ATTRIBUTE_NAMES[361] = ATTR_MATHSIZE; + ATTRIBUTE_NAMES[362] = ATTR_ONCHANGE; + ATTRIBUTE_NAMES[363] = ATTR_PATH; + ATTRIBUTE_NAMES[364] = ATTR_ACTIONTYPE; + ATTRIBUTE_NAMES[365] = ATTR_ACTIVE; + ATTRIBUTE_NAMES[366] = ATTR_BEGIN; + ATTRIBUTE_NAMES[367] = ATTR_DIVISOR; + ATTRIBUTE_NAMES[368] = ATTR_LIMITINGCONEANGLE; + ATTRIBUTE_NAMES[369] = ATTR_MANIFEST; + ATTRIBUTE_NAMES[370] = ATTR_OPTIMUM; + ATTRIBUTE_NAMES[371] = ATTR_RADIUS; + ATTRIBUTE_NAMES[372] = ATTR_SCRIPTSIZEMULTIPLIER; + ATTRIBUTE_NAMES[373] = ATTR_TABINDEX; + ATTRIBUTE_NAMES[374] = ATTR_VISIBILITY; + ATTRIBUTE_NAMES[375] = ATTR_LINK; + ATTRIBUTE_NAMES[376] = ATTR_MARKERHEIGHT; + ATTRIBUTE_NAMES[377] = ATTR_MASK; + ATTRIBUTE_NAMES[378] = ATTR_MARKERWIDTH; + ATTRIBUTE_NAMES[379] = ATTR_MARKERUNITS; + ATTRIBUTE_NAMES[380] = ATTR_AMPLITUDE; + ATTRIBUTE_NAMES[381] = ATTR_CELLPADDING; + ATTRIBUTE_NAMES[382] = ATTR_FILL_RULE; + ATTRIBUTE_NAMES[383] = ATTR_FILL_OPACITY; + ATTRIBUTE_NAMES[384] = ATTR_ONCLICK; + ATTRIBUTE_NAMES[385] = ATTR_REPLACE; + ATTRIBUTE_NAMES[386] = ATTR_SCALE; + ATTRIBUTE_NAMES[387] = ATTR_TABLEVALUES; + ATTRIBUTE_NAMES[388] = ATTR_AZIMUTH; + ATTRIBUTE_NAMES[389] = ATTR_FRAMEBORDER; + ATTRIBUTE_NAMES[390] = ATTR_FRAMESPACING; + ATTRIBUTE_NAMES[391] = ATTR_FORM; + ATTRIBUTE_NAMES[392] = ATTR_PRIMITIVEUNITS; + ATTRIBUTE_NAMES[393] = ATTR_SUMMARY; + ATTRIBUTE_NAMES[394] = ATTR_ZOOMANDPAN; + ATTRIBUTE_NAMES[395] = ATTR_ALINK; + ATTRIBUTE_NAMES[396] = ATTR_ICON; + ATTRIBUTE_NAMES[397] = ATTR_KERNING; + ATTRIBUTE_NAMES[398] = ATTR_ONUNLOAD; + ATTRIBUTE_NAMES[399] = ATTR_ONINVALID; + ATTRIBUTE_NAMES[400] = ATTR_ONINPUT; + ATTRIBUTE_NAMES[401] = ATTR_POINTS; + ATTRIBUTE_NAMES[402] = ATTR_POINTSATY; + ATTRIBUTE_NAMES[403] = ATTR_SPAN; + ATTRIBUTE_NAMES[404] = ATTR_TRANSFORM_ORIGIN; + ATTRIBUTE_NAMES[405] = ATTR_VLINK; + ATTRIBUTE_NAMES[406] = ATTR_XLINK_HREF; + ATTRIBUTE_NAMES[407] = ATTR_XLINK_ROLE; + ATTRIBUTE_NAMES[408] = ATTR_XMLNS_XLINK; + ATTRIBUTE_NAMES[409] = ATTR_XLINK_TYPE; + ATTRIBUTE_NAMES[410] = ATTR_XLINK_ACTUATE; + ATTRIBUTE_NAMES[411] = ATTR_AUTOCOMPLETE; + ATTRIBUTE_NAMES[412] = ATTR_AUTOCAPITALIZE; + ATTRIBUTE_NAMES[413] = ATTR_COLOR_PROFILE; + ATTRIBUTE_NAMES[414] = ATTR_COLOR_INTERPOLATION; + ATTRIBUTE_NAMES[415] = ATTR_COLOR_INTERPOLATION_FILTERS; + ATTRIBUTE_NAMES[416] = ATTR_EXPONENT; + ATTRIBUTE_NAMES[417] = ATTR_FLOOD_OPACITY; + ATTRIBUTE_NAMES[418] = ATTR_NUMOCTAVES; + ATTRIBUTE_NAMES[419] = ATTR_ONLOAD; + ATTRIBUTE_NAMES[420] = ATTR_ONMOUSEENTER; + ATTRIBUTE_NAMES[421] = ATTR_ONFOCUSIN; + ATTRIBUTE_NAMES[422] = ATTR_ONZOOM; + ATTRIBUTE_NAMES[423] = ATTR_ONMOUSELEAVE; + ATTRIBUTE_NAMES[424] = ATTR_ONMOUSEUP; + ATTRIBUTE_NAMES[425] = ATTR_ONMOUSEOUT; + ATTRIBUTE_NAMES[426] = ATTR_ONMOUSEDOWN; + ATTRIBUTE_NAMES[427] = ATTR_RQUOTE; + ATTRIBUTE_NAMES[428] = ATTR_STROKE_DASHARRAY; + ATTRIBUTE_NAMES[429] = ATTR_STROKE_LINEJOIN; + ATTRIBUTE_NAMES[430] = ATTR_STROKE; + ATTRIBUTE_NAMES[431] = ATTR_STROKE_WIDTH; + ATTRIBUTE_NAMES[432] = ATTR_COMPACT; + ATTRIBUTE_NAMES[433] = ATTR_CLIP_RULE; + ATTRIBUTE_NAMES[434] = ATTR_CLIPPATHUNITS; + ATTRIBUTE_NAMES[435] = ATTR_DISPLAYSTYLE; + ATTRIBUTE_NAMES[436] = ATTR_GLYPH_ORIENTATION_HORIZONTAL; + ATTRIBUTE_NAMES[437] = ATTR_HTTP_EQUIV; + ATTRIBUTE_NAMES[438] = ATTR_LOOP; + ATTRIBUTE_NAMES[439] = ATTR_SCOPED; + ATTRIBUTE_NAMES[440] = ATTR_SHAPE_RENDERING; + ATTRIBUTE_NAMES[441] = ATTR_SHAPE; + ATTRIBUTE_NAMES[442] = ATTR_STOP_COLOR; + ATTRIBUTE_NAMES[443] = ATTR_TEMPLATE; + ATTRIBUTE_NAMES[444] = ATTR_ABBR; + ATTRIBUTE_NAMES[445] = ATTR_ATTRIBUTETYPE; + ATTRIBUTE_NAMES[446] = ATTR_COORDS; + ATTRIBUTE_NAMES[447] = ATTR_CHARSET; + ATTRIBUTE_NAMES[448] = ATTR_NOHREF; + ATTRIBUTE_NAMES[449] = ATTR_ONDRAGENTER; + ATTRIBUTE_NAMES[450] = ATTR_ONDRAGEND; + ATTRIBUTE_NAMES[451] = ATTR_ONDRAGDROP; + ATTRIBUTE_NAMES[452] = ATTR_OPERATOR; + ATTRIBUTE_NAMES[453] = ATTR_ONDRAGSTART; + ATTRIBUTE_NAMES[454] = ATTR_STARTOFFSET; + ATTRIBUTE_NAMES[455] = ATTR_AS; + ATTRIBUTE_NAMES[456] = ATTR_BIAS; + ATTRIBUTE_NAMES[457] = ATTR_CLASSID; + ATTRIBUTE_NAMES[458] = ATTR_COLS; + ATTRIBUTE_NAMES[459] = ATTR_CLOSURE; + ATTRIBUTE_NAMES[460] = ATTR_CLASS; + ATTRIBUTE_NAMES[461] = ATTR_KEYSYSTEM; + ATTRIBUTE_NAMES[462] = ATTR_LOWSRC; + ATTRIBUTE_NAMES[463] = ATTR_MINSIZE; + ATTRIBUTE_NAMES[464] = ATTR_PRESERVEALPHA; + ATTRIBUTE_NAMES[465] = ATTR_ROWSPAN; + ATTRIBUTE_NAMES[466] = ATTR_ROWS; + ATTRIBUTE_NAMES[467] = ATTR_SUBSCRIPTSHIFT; + ATTRIBUTE_NAMES[468] = ATTR_ALTTEXT; + ATTRIBUTE_NAMES[469] = ATTR_CONTROLS; + ATTRIBUTE_NAMES[470] = ATTR_CONTEXTMENU; + ATTRIBUTE_NAMES[471] = ATTR_ENCTYPE; + ATTRIBUTE_NAMES[472] = ATTR_FILTER; + ATTRIBUTE_NAMES[473] = ATTR_FONT_WEIGHT; + ATTRIBUTE_NAMES[474] = ATTR_FONT_STYLE; + ATTRIBUTE_NAMES[475] = ATTR_FONT_FAMILY; + ATTRIBUTE_NAMES[476] = ATTR_FONT_SIZE_ADJUST; + ATTRIBUTE_NAMES[477] = ATTR_FONTSIZE; + ATTRIBUTE_NAMES[478] = ATTR_KEYTIMES; + ATTRIBUTE_NAMES[479] = ATTR_LIST; + ATTRIBUTE_NAMES[480] = ATTR_RT; + ATTRIBUTE_NAMES[481] = ATTR_ONSTART; + ATTRIBUTE_NAMES[482] = ATTR_PATTERNTRANSFORM; + ATTRIBUTE_NAMES[483] = ATTR_PATTERNUNITS; + ATTRIBUTE_NAMES[484] = ATTR_RESTART; + ATTRIBUTE_NAMES[485] = ATTR_SYSTEMLANGUAGE; + ATTRIBUTE_NAMES[486] = ATTR_TEXT_DECORATION; + ATTRIBUTE_NAMES[487] = ATTR_TEXTLENGTH; + ATTRIBUTE_NAMES[488] = ATTR_WRITING_MODE; + ATTRIBUTE_NAMES[489] = ATTR_ACCUMULATE; + ATTRIBUTE_NAMES[490] = ATTR_COLUMNLINES; + ATTRIBUTE_NAMES[491] = ATTR_COLUMNSPACING; + ATTRIBUTE_NAMES[492] = ATTR_GROUPALIGN; + ATTRIBUTE_NAMES[493] = ATTR_ONSUBMIT; + ATTRIBUTE_NAMES[494] = ATTR_REQUIRED; + ATTRIBUTE_NAMES[495] = ATTR_RESULT; + ATTRIBUTE_NAMES[496] = ATTR_VALUES; + ATTRIBUTE_NAMES[497] = ATTR_VALUE; + ATTRIBUTE_NAMES[498] = ATTR_VIEWTARGET; +} + +void nsHtml5AttributeName::releaseStatics() { + delete[] ALL_NO_NS; + delete[] XMLNS_NS; + delete[] XML_NS; + delete[] XLINK_NS; + delete[] ALL_NO_PREFIX; + delete[] XMLNS_PREFIX; + delete[] XLINK_PREFIX; + delete[] XML_PREFIX; + delete ATTR_ALT; + delete ATTR_DIR; + delete ATTR_DUR; + delete ATTR_END; + delete ATTR_FOR; + delete ATTR_IN2; + delete ATTR_LOW; + delete ATTR_MIN; + delete ATTR_MAX; + delete ATTR_REL; + delete ATTR_REV; + delete ATTR_SRC; + delete ATTR_D; + delete ATTR_R; + delete ATTR_X; + delete ATTR_Y; + delete ATTR_Z; + delete ATTR_K1; + delete ATTR_X1; + delete ATTR_Y1; + delete ATTR_K2; + delete ATTR_X2; + delete ATTR_Y2; + delete ATTR_K3; + delete ATTR_K4; + delete ATTR_XML_SPACE; + delete ATTR_XML_LANG; + delete ATTR_ARIA_GRAB; + delete ATTR_ARIA_VALUEMAX; + delete ATTR_ARIA_LABELLEDBY; + delete ATTR_ARIA_DESCRIBEDBY; + delete ATTR_ARIA_DISABLED; + delete ATTR_ARIA_CHECKED; + delete ATTR_ARIA_SELECTED; + delete ATTR_ARIA_DROPEFFECT; + delete ATTR_ARIA_REQUIRED; + delete ATTR_ARIA_EXPANDED; + delete ATTR_ARIA_PRESSED; + delete ATTR_ARIA_LEVEL; + delete ATTR_ARIA_CHANNEL; + delete ATTR_ARIA_HIDDEN; + delete ATTR_ARIA_SECRET; + delete ATTR_ARIA_POSINSET; + delete ATTR_ARIA_ATOMIC; + delete ATTR_ARIA_INVALID; + delete ATTR_ARIA_TEMPLATEID; + delete ATTR_ARIA_VALUEMIN; + delete ATTR_ARIA_MULTISELECTABLE; + delete ATTR_ARIA_CONTROLS; + delete ATTR_ARIA_MULTILINE; + delete ATTR_ARIA_READONLY; + delete ATTR_ARIA_OWNS; + delete ATTR_ARIA_ACTIVEDESCENDANT; + delete ATTR_ARIA_RELEVANT; + delete ATTR_ARIA_DATATYPE; + delete ATTR_ARIA_VALUENOW; + delete ATTR_ARIA_SORT; + delete ATTR_ARIA_AUTOCOMPLETE; + delete ATTR_ARIA_FLOWTO; + delete ATTR_ARIA_BUSY; + delete ATTR_ARIA_LIVE; + delete ATTR_ARIA_HASPOPUP; + delete ATTR_ARIA_SETSIZE; + delete ATTR_CLEAR; + delete ATTR_DISABLED; + delete ATTR_DEFAULT; + delete ATTR_DATA; + delete ATTR_EQUALCOLUMNS; + delete ATTR_EQUALROWS; + delete ATTR_HSPACE; + delete ATTR_ISMAP; + delete ATTR_LOCAL; + delete ATTR_LSPACE; + delete ATTR_MOVABLELIMITS; + delete ATTR_NOTATION; + delete ATTR_ONDATAAVAILABLE; + delete ATTR_ONPASTE; + delete ATTR_RSPACE; + delete ATTR_ROWALIGN; + delete ATTR_ROTATE; + delete ATTR_SEPARATOR; + delete ATTR_SEPARATORS; + delete ATTR_VSPACE; + delete ATTR_XCHANNELSELECTOR; + delete ATTR_YCHANNELSELECTOR; + delete ATTR_ENABLE_BACKGROUND; + delete ATTR_ONDBLCLICK; + delete ATTR_ONABORT; + delete ATTR_CALCMODE; + delete ATTR_CHECKED; + delete ATTR_FENCE; + delete ATTR_ONSCROLL; + delete ATTR_ONACTIVATE; + delete ATTR_OPACITY; + delete ATTR_SPACING; + delete ATTR_SPECULAREXPONENT; + delete ATTR_SPECULARCONSTANT; + delete ATTR_BORDER; + delete ATTR_ID; + delete ATTR_GRADIENTTRANSFORM; + delete ATTR_GRADIENTUNITS; + delete ATTR_HIDDEN; + delete ATTR_HEADERS; + delete ATTR_LOADING; + delete ATTR_READONLY; + delete ATTR_RENDERING_INTENT; + delete ATTR_SEED; + delete ATTR_SRCDOC; + delete ATTR_STDDEVIATION; + delete ATTR_SANDBOX; + delete ATTR_WORD_SPACING; + delete ATTR_ACCENTUNDER; + delete ATTR_ACCEPT_CHARSET; + delete ATTR_ACCESSKEY; + delete ATTR_ACCENT; + delete ATTR_ACCEPT; + delete ATTR_BEVELLED; + delete ATTR_BASEFREQUENCY; + delete ATTR_BASELINE_SHIFT; + delete ATTR_BASEPROFILE; + delete ATTR_BASELINE; + delete ATTR_BASE; + delete ATTR_CODE; + delete ATTR_CODETYPE; + delete ATTR_CODEBASE; + delete ATTR_CITE; + delete ATTR_DEFER; + delete ATTR_DATETIME; + delete ATTR_DIRECTION; + delete ATTR_EDGEMODE; + delete ATTR_EDGE; + delete ATTR_ENTERKEYHINT; + delete ATTR_FACE; + delete ATTR_INDEX; + delete ATTR_INTERCEPT; + delete ATTR_INTEGRITY; + delete ATTR_LINEBREAK; + delete ATTR_LABEL; + delete ATTR_LINETHICKNESS; + delete ATTR_MODE; + delete ATTR_NAME; + delete ATTR_NORESIZE; + delete ATTR_ONBEFOREUNLOAD; + delete ATTR_ONREPEAT; + delete ATTR_OBJECT; + delete ATTR_ONSELECT; + delete ATTR_ORDER; + delete ATTR_OTHER; + delete ATTR_ONRESET; + delete ATTR_ONREADYSTATECHANGE; + delete ATTR_ONMESSAGE; + delete ATTR_ONBEGIN; + delete ATTR_ONBEFOREPRINT; + delete ATTR_ORIENT; + delete ATTR_ORIENTATION; + delete ATTR_ONBEFORECOPY; + delete ATTR_ONSELECTSTART; + delete ATTR_ONBEFOREPASTE; + delete ATTR_ONKEYPRESS; + delete ATTR_ONKEYUP; + delete ATTR_ONBEFORECUT; + delete ATTR_ONKEYDOWN; + delete ATTR_ONRESIZE; + delete ATTR_REPEAT; + delete ATTR_REFERRERPOLICY; + delete ATTR_RULES; + delete ATTR_ROLE; + delete ATTR_REPEATCOUNT; + delete ATTR_REPEATDUR; + delete ATTR_SELECTED; + delete ATTR_SIZES; + delete ATTR_SUPERSCRIPTSHIFT; + delete ATTR_STRETCHY; + delete ATTR_SCHEME; + delete ATTR_SPREADMETHOD; + delete ATTR_SELECTION; + delete ATTR_SIZE; + delete ATTR_TYPE; + delete ATTR_DIFFUSECONSTANT; + delete ATTR_HREF; + delete ATTR_HREFLANG; + delete ATTR_ONAFTERPRINT; + delete ATTR_PROFILE; + delete ATTR_SURFACESCALE; + delete ATTR_XREF; + delete ATTR_ALIGN; + delete ATTR_ALIGNMENT_BASELINE; + delete ATTR_ALIGNMENTSCOPE; + delete ATTR_DRAGGABLE; + delete ATTR_HEIGHT; + delete ATTR_IMAGESIZES; + delete ATTR_IMAGESRCSET; + delete ATTR_IMAGE_RENDERING; + delete ATTR_LANGUAGE; + delete ATTR_LANG; + delete ATTR_LARGEOP; + delete ATTR_LONGDESC; + delete ATTR_LENGTHADJUST; + delete ATTR_MARGINHEIGHT; + delete ATTR_MARGINWIDTH; + delete ATTR_ORIGIN; + delete ATTR_PING; + delete ATTR_TARGET; + delete ATTR_TARGETX; + delete ATTR_TARGETY; + delete ATTR_ARCHIVE; + delete ATTR_HIGH; + delete ATTR_LIGHTING_COLOR; + delete ATTR_MATHBACKGROUND; + delete ATTR_METHOD; + delete ATTR_MATHVARIANT; + delete ATTR_MATHCOLOR; + delete ATTR_MATHSIZE; + delete ATTR_NOSHADE; + delete ATTR_ONCHANGE; + delete ATTR_PATHLENGTH; + delete ATTR_PATH; + delete ATTR_ALTIMG; + delete ATTR_ACTIONTYPE; + delete ATTR_ACTION; + delete ATTR_ACTIVE; + delete ATTR_ADDITIVE; + delete ATTR_BEGIN; + delete ATTR_DOMINANT_BASELINE; + delete ATTR_DIVISOR; + delete ATTR_DEFINITIONURL; + delete ATTR_LIMITINGCONEANGLE; + delete ATTR_MEDIA; + delete ATTR_MANIFEST; + delete ATTR_ONFINISH; + delete ATTR_OPTIMUM; + delete ATTR_RADIOGROUP; + delete ATTR_RADIUS; + delete ATTR_SCRIPTLEVEL; + delete ATTR_SCRIPTSIZEMULTIPLIER; + delete ATTR_SCRIPTMINSIZE; + delete ATTR_TABINDEX; + delete ATTR_VALIGN; + delete ATTR_VISIBILITY; + delete ATTR_BACKGROUND; + delete ATTR_LINK; + delete ATTR_MARKER_MID; + delete ATTR_MARKERHEIGHT; + delete ATTR_MARKER_END; + delete ATTR_MASK; + delete ATTR_MARKER_START; + delete ATTR_MARKERWIDTH; + delete ATTR_MASKUNITS; + delete ATTR_MARKERUNITS; + delete ATTR_MASKCONTENTUNITS; + delete ATTR_AMPLITUDE; + delete ATTR_CELLSPACING; + delete ATTR_CELLPADDING; + delete ATTR_DECLARE; + delete ATTR_FILL_RULE; + delete ATTR_FILL; + delete ATTR_FILL_OPACITY; + delete ATTR_MAXLENGTH; + delete ATTR_ONCLICK; + delete ATTR_ONBLUR; + delete ATTR_REPLACE; + delete ATTR_ROWLINES; + delete ATTR_SCALE; + delete ATTR_STYLE; + delete ATTR_TABLEVALUES; + delete ATTR_TITLE; + delete ATTR_AZIMUTH; + delete ATTR_FORMAT; + delete ATTR_FRAMEBORDER; + delete ATTR_FRAME; + delete ATTR_FRAMESPACING; + delete ATTR_FROM; + delete ATTR_FORM; + delete ATTR_PROMPT; + delete ATTR_PRIMITIVEUNITS; + delete ATTR_SYMMETRIC; + delete ATTR_SUMMARY; + delete ATTR_USEMAP; + delete ATTR_ZOOMANDPAN; + delete ATTR_ASYNC; + delete ATTR_ALINK; + delete ATTR_IN; + delete ATTR_ICON; + delete ATTR_KERNELMATRIX; + delete ATTR_KERNING; + delete ATTR_KERNELUNITLENGTH; + delete ATTR_ONUNLOAD; + delete ATTR_OPEN; + delete ATTR_ONINVALID; + delete ATTR_ONEND; + delete ATTR_ONINPUT; + delete ATTR_POINTER_EVENTS; + delete ATTR_POINTS; + delete ATTR_POINTSATX; + delete ATTR_POINTSATY; + delete ATTR_POINTSATZ; + delete ATTR_SPAN; + delete ATTR_STANDBY; + delete ATTR_TRANSFORM_ORIGIN; + delete ATTR_TRANSFORM; + delete ATTR_VLINK; + delete ATTR_WHEN; + delete ATTR_XLINK_HREF; + delete ATTR_XLINK_TITLE; + delete ATTR_XLINK_ROLE; + delete ATTR_XLINK_ARCROLE; + delete ATTR_XMLNS_XLINK; + delete ATTR_XMLNS; + delete ATTR_XLINK_TYPE; + delete ATTR_XLINK_SHOW; + delete ATTR_XLINK_ACTUATE; + delete ATTR_AUTOPLAY; + delete ATTR_AUTOCOMPLETE; + delete ATTR_AUTOFOCUS; + delete ATTR_AUTOCAPITALIZE; + delete ATTR_BGCOLOR; + delete ATTR_COLOR_PROFILE; + delete ATTR_COLOR_RENDERING; + delete ATTR_COLOR_INTERPOLATION; + delete ATTR_COLOR; + delete ATTR_COLOR_INTERPOLATION_FILTERS; + delete ATTR_ENCODING; + delete ATTR_EXPONENT; + delete ATTR_FLOOD_COLOR; + delete ATTR_FLOOD_OPACITY; + delete ATTR_LQUOTE; + delete ATTR_NUMOCTAVES; + delete ATTR_NOMODULE; + delete ATTR_ONLOAD; + delete ATTR_ONMOUSEWHEEL; + delete ATTR_ONMOUSEENTER; + delete ATTR_ONMOUSEOVER; + delete ATTR_ONFOCUSIN; + delete ATTR_ONCONTEXTMENU; + delete ATTR_ONZOOM; + delete ATTR_ONCOPY; + delete ATTR_ONMOUSELEAVE; + delete ATTR_ONMOUSEMOVE; + delete ATTR_ONMOUSEUP; + delete ATTR_ONFOCUS; + delete ATTR_ONMOUSEOUT; + delete ATTR_ONFOCUSOUT; + delete ATTR_ONMOUSEDOWN; + delete ATTR_TO; + delete ATTR_RQUOTE; + delete ATTR_STROKE_LINECAP; + delete ATTR_STROKE_DASHARRAY; + delete ATTR_STROKE_DASHOFFSET; + delete ATTR_STROKE_LINEJOIN; + delete ATTR_STROKE_MITERLIMIT; + delete ATTR_STROKE; + delete ATTR_SCROLLING; + delete ATTR_STROKE_WIDTH; + delete ATTR_STROKE_OPACITY; + delete ATTR_COMPACT; + delete ATTR_CLIP; + delete ATTR_CLIP_RULE; + delete ATTR_CLIP_PATH; + delete ATTR_CLIPPATHUNITS; + delete ATTR_DISPLAY; + delete ATTR_DISPLAYSTYLE; + delete ATTR_GLYPH_ORIENTATION_VERTICAL; + delete ATTR_GLYPH_ORIENTATION_HORIZONTAL; + delete ATTR_GLYPHREF; + delete ATTR_HTTP_EQUIV; + delete ATTR_KEYPOINTS; + delete ATTR_LOOP; + delete ATTR_PROPERTY; + delete ATTR_SCOPED; + delete ATTR_STEP; + delete ATTR_SHAPE_RENDERING; + delete ATTR_SCOPE; + delete ATTR_SHAPE; + delete ATTR_SLOPE; + delete ATTR_STOP_COLOR; + delete ATTR_STOP_OPACITY; + delete ATTR_TEMPLATE; + delete ATTR_WRAP; + delete ATTR_ABBR; + delete ATTR_ATTRIBUTENAME; + delete ATTR_ATTRIBUTETYPE; + delete ATTR_CHAR; + delete ATTR_COORDS; + delete ATTR_CHAROFF; + delete ATTR_CHARSET; + delete ATTR_NOWRAP; + delete ATTR_NOHREF; + delete ATTR_ONDRAG; + delete ATTR_ONDRAGENTER; + delete ATTR_ONDRAGOVER; + delete ATTR_ONDRAGEND; + delete ATTR_ONDROP; + delete ATTR_ONDRAGDROP; + delete ATTR_ONERROR; + delete ATTR_OPERATOR; + delete ATTR_OVERFLOW; + delete ATTR_ONDRAGSTART; + delete ATTR_ONDRAGLEAVE; + delete ATTR_STARTOFFSET; + delete ATTR_START; + delete ATTR_AS; + delete ATTR_AXIS; + delete ATTR_BIAS; + delete ATTR_COLSPAN; + delete ATTR_CLASSID; + delete ATTR_CROSSORIGIN; + delete ATTR_COLS; + delete ATTR_CURSOR; + delete ATTR_CLOSURE; + delete ATTR_CLOSE; + delete ATTR_CLASS; + delete ATTR_IS; + delete ATTR_KEYSYSTEM; + delete ATTR_KEYSPLINES; + delete ATTR_LOWSRC; + delete ATTR_MAXSIZE; + delete ATTR_MINSIZE; + delete ATTR_OFFSET; + delete ATTR_PRESERVEALPHA; + delete ATTR_PRESERVEASPECTRATIO; + delete ATTR_ROWSPAN; + delete ATTR_ROWSPACING; + delete ATTR_ROWS; + delete ATTR_SRCSET; + delete ATTR_SUBSCRIPTSHIFT; + delete ATTR_VERSION; + delete ATTR_ALTTEXT; + delete ATTR_CONTENTEDITABLE; + delete ATTR_CONTROLS; + delete ATTR_CONTENT; + delete ATTR_CONTEXTMENU; + delete ATTR_DEPTH; + delete ATTR_ENCTYPE; + delete ATTR_FONT_STRETCH; + delete ATTR_FILTER; + delete ATTR_FONTWEIGHT; + delete ATTR_FONT_WEIGHT; + delete ATTR_FONTSTYLE; + delete ATTR_FONT_STYLE; + delete ATTR_FONTFAMILY; + delete ATTR_FONT_FAMILY; + delete ATTR_FONT_VARIANT; + delete ATTR_FONT_SIZE_ADJUST; + delete ATTR_FILTERUNITS; + delete ATTR_FONTSIZE; + delete ATTR_FONT_SIZE; + delete ATTR_KEYTIMES; + delete ATTR_LETTER_SPACING; + delete ATTR_LIST; + delete ATTR_MULTIPLE; + delete ATTR_RT; + delete ATTR_ONSTOP; + delete ATTR_ONSTART; + delete ATTR_POSTER; + delete ATTR_PATTERNTRANSFORM; + delete ATTR_PATTERN; + delete ATTR_PATTERNUNITS; + delete ATTR_PATTERNCONTENTUNITS; + delete ATTR_RESTART; + delete ATTR_STITCHTILES; + delete ATTR_SYSTEMLANGUAGE; + delete ATTR_TEXT_RENDERING; + delete ATTR_TEXT_DECORATION; + delete ATTR_TEXT_ANCHOR; + delete ATTR_TEXTLENGTH; + delete ATTR_TEXT; + delete ATTR_WRITING_MODE; + delete ATTR_WIDTH; + delete ATTR_ACCUMULATE; + delete ATTR_COLUMNSPAN; + delete ATTR_COLUMNLINES; + delete ATTR_COLUMNALIGN; + delete ATTR_COLUMNSPACING; + delete ATTR_COLUMNWIDTH; + delete ATTR_GROUPALIGN; + delete ATTR_INPUTMODE; + delete ATTR_ONSUBMIT; + delete ATTR_ONCUT; + delete ATTR_REQUIRED; + delete ATTR_REQUIREDFEATURES; + delete ATTR_RESULT; + delete ATTR_REQUIREDEXTENSIONS; + delete ATTR_VALUES; + delete ATTR_VALUETYPE; + delete ATTR_VALUE; + delete ATTR_ELEVATION; + delete ATTR_VIEWTARGET; + delete ATTR_VIEWBOX; + delete ATTR_CX; + delete ATTR_DX; + delete ATTR_FX; + delete ATTR_RX; + delete ATTR_REFX; + delete ATTR_BY; + delete ATTR_CY; + delete ATTR_DY; + delete ATTR_FY; + delete ATTR_RY; + delete ATTR_REFY; + delete[] ATTRIBUTE_NAMES; +} diff --git a/parser/html/nsHtml5AttributeName.h b/parser/html/nsHtml5AttributeName.h new file mode 100644 index 0000000000..a6efc82786 --- /dev/null +++ b/parser/html/nsHtml5AttributeName.h @@ -0,0 +1,688 @@ +/* + * Copyright (c) 2008-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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit AttributeName.java instead and regenerate. + */ + +#ifndef nsHtml5AttributeName_h +#define nsHtml5AttributeName_h + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +class nsHtml5StreamParser; + +class nsHtml5ElementName; +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5UTF16Buffer; +class nsHtml5StateSnapshot; +class nsHtml5Portability; + +class nsHtml5AttributeName { + public: + static int32_t* ALL_NO_NS; + + private: + static int32_t* XMLNS_NS; + static int32_t* XML_NS; + static int32_t* XLINK_NS; + + public: + static nsStaticAtom** ALL_NO_PREFIX; + + private: + static nsStaticAtom** XMLNS_PREFIX; + static nsStaticAtom** XLINK_PREFIX; + static nsStaticAtom** XML_PREFIX; + static RefPtr<nsAtom>* SVG_DIFFERENT(nsAtom* name, nsAtom* camel); + static RefPtr<nsAtom>* MATH_DIFFERENT(nsAtom* name, nsAtom* camel); + static RefPtr<nsAtom>* COLONIFIED_LOCAL(nsAtom* name, nsAtom* suffix); + + public: + static RefPtr<nsAtom>* SAME_LOCAL(nsAtom* name); + inline static int32_t levelOrderBinarySearch(jArray<int32_t, int32_t> data, + int32_t key) { + int32_t n = data.length; + int32_t i = 0; + while (i < n) { + int32_t val = data[i]; + if (val < key) { + i = 2 * i + 2; + } else if (val > key) { + i = 2 * i + 1; + } else { + return i; + } + } + return -1; + } + + inline static nsHtml5AttributeName* nameByBuffer(char16_t* buf, + int32_t length, + nsHtml5AtomTable* interner) { + uint32_t hash = nsHtml5AttributeName::bufToHash(buf, length); + jArray<int32_t, int32_t> hashes; + hashes = nsHtml5AttributeName::ATTRIBUTE_HASHES; + int32_t index = levelOrderBinarySearch(hashes, hash); + if (index < 0) { + return nullptr; + } + nsHtml5AttributeName* attributeName = + nsHtml5AttributeName::ATTRIBUTE_NAMES[index]; + nsAtom* name = attributeName->getLocal(0); + if (!nsHtml5Portability::localEqualsBuffer(name, buf, length)) { + return nullptr; + } + return attributeName; + } + + private: + inline static uint32_t bufToHash(char16_t* buf, int32_t length) { + uint32_t len = length; + uint32_t first = buf[0]; + first <<= 19; + uint32_t second = 1 << 23; + uint32_t third = 0; + uint32_t fourth = 0; + uint32_t fifth = 0; + uint32_t sixth = 0; + if (length >= 4) { + second = buf[length - 4]; + second <<= 4; + third = buf[1]; + third <<= 9; + fourth = buf[length - 2]; + fourth <<= 14; + fifth = buf[3]; + fifth <<= 24; + sixth = buf[length - 1]; + sixth <<= 11; + } else if (length == 3) { + second = buf[1]; + second <<= 4; + third = buf[2]; + third <<= 9; + } else if (length == 2) { + second = buf[1]; + second <<= 24; + } + return len + first + second + third + fourth + fifth + sixth; + } + + public: + static const int32_t HTML = 0; + + static const int32_t MATHML = 1; + + static const int32_t SVG = 2; + + private: + int32_t* uri; + RefPtr<nsAtom>* local; + nsStaticAtom** prefix; + bool custom; + nsHtml5AttributeName(int32_t* uri, RefPtr<nsAtom>* local, + nsStaticAtom** prefix); + + public: + nsHtml5AttributeName(); + inline bool isInterned() { return !custom; } + + inline void setNameForNonInterned(nsAtom* name) { + MOZ_ASSERT(custom); + local[0] = name; + local[1] = name; + local[2] = name; + } + + static nsHtml5AttributeName* createAttributeName(nsAtom* name); + ~nsHtml5AttributeName(); + int32_t getUri(int32_t mode); + nsAtom* getLocal(int32_t mode); + nsStaticAtom* getPrefix(int32_t mode); + bool equalsAnother(nsHtml5AttributeName* another); + static nsHtml5AttributeName* ATTR_ALT; + static nsHtml5AttributeName* ATTR_DIR; + static nsHtml5AttributeName* ATTR_DUR; + static nsHtml5AttributeName* ATTR_END; + static nsHtml5AttributeName* ATTR_FOR; + static nsHtml5AttributeName* ATTR_IN2; + static nsHtml5AttributeName* ATTR_LOW; + static nsHtml5AttributeName* ATTR_MIN; + static nsHtml5AttributeName* ATTR_MAX; + static nsHtml5AttributeName* ATTR_REL; + static nsHtml5AttributeName* ATTR_REV; + static nsHtml5AttributeName* ATTR_SRC; + static nsHtml5AttributeName* ATTR_D; + static nsHtml5AttributeName* ATTR_R; + static nsHtml5AttributeName* ATTR_X; + static nsHtml5AttributeName* ATTR_Y; + static nsHtml5AttributeName* ATTR_Z; + static nsHtml5AttributeName* ATTR_K1; + static nsHtml5AttributeName* ATTR_X1; + static nsHtml5AttributeName* ATTR_Y1; + static nsHtml5AttributeName* ATTR_K2; + static nsHtml5AttributeName* ATTR_X2; + static nsHtml5AttributeName* ATTR_Y2; + static nsHtml5AttributeName* ATTR_K3; + static nsHtml5AttributeName* ATTR_K4; + static nsHtml5AttributeName* ATTR_XML_SPACE; + static nsHtml5AttributeName* ATTR_XML_LANG; + static nsHtml5AttributeName* ATTR_ARIA_GRAB; + static nsHtml5AttributeName* ATTR_ARIA_VALUEMAX; + static nsHtml5AttributeName* ATTR_ARIA_LABELLEDBY; + static nsHtml5AttributeName* ATTR_ARIA_DESCRIBEDBY; + static nsHtml5AttributeName* ATTR_ARIA_DISABLED; + static nsHtml5AttributeName* ATTR_ARIA_CHECKED; + static nsHtml5AttributeName* ATTR_ARIA_SELECTED; + static nsHtml5AttributeName* ATTR_ARIA_DROPEFFECT; + static nsHtml5AttributeName* ATTR_ARIA_REQUIRED; + static nsHtml5AttributeName* ATTR_ARIA_EXPANDED; + static nsHtml5AttributeName* ATTR_ARIA_PRESSED; + static nsHtml5AttributeName* ATTR_ARIA_LEVEL; + static nsHtml5AttributeName* ATTR_ARIA_CHANNEL; + static nsHtml5AttributeName* ATTR_ARIA_HIDDEN; + static nsHtml5AttributeName* ATTR_ARIA_SECRET; + static nsHtml5AttributeName* ATTR_ARIA_POSINSET; + static nsHtml5AttributeName* ATTR_ARIA_ATOMIC; + static nsHtml5AttributeName* ATTR_ARIA_INVALID; + static nsHtml5AttributeName* ATTR_ARIA_TEMPLATEID; + static nsHtml5AttributeName* ATTR_ARIA_VALUEMIN; + static nsHtml5AttributeName* ATTR_ARIA_MULTISELECTABLE; + static nsHtml5AttributeName* ATTR_ARIA_CONTROLS; + static nsHtml5AttributeName* ATTR_ARIA_MULTILINE; + static nsHtml5AttributeName* ATTR_ARIA_READONLY; + static nsHtml5AttributeName* ATTR_ARIA_OWNS; + static nsHtml5AttributeName* ATTR_ARIA_ACTIVEDESCENDANT; + static nsHtml5AttributeName* ATTR_ARIA_RELEVANT; + static nsHtml5AttributeName* ATTR_ARIA_DATATYPE; + static nsHtml5AttributeName* ATTR_ARIA_VALUENOW; + static nsHtml5AttributeName* ATTR_ARIA_SORT; + static nsHtml5AttributeName* ATTR_ARIA_AUTOCOMPLETE; + static nsHtml5AttributeName* ATTR_ARIA_FLOWTO; + static nsHtml5AttributeName* ATTR_ARIA_BUSY; + static nsHtml5AttributeName* ATTR_ARIA_LIVE; + static nsHtml5AttributeName* ATTR_ARIA_HASPOPUP; + static nsHtml5AttributeName* ATTR_ARIA_SETSIZE; + static nsHtml5AttributeName* ATTR_CLEAR; + static nsHtml5AttributeName* ATTR_DISABLED; + static nsHtml5AttributeName* ATTR_DEFAULT; + static nsHtml5AttributeName* ATTR_DATA; + static nsHtml5AttributeName* ATTR_EQUALCOLUMNS; + static nsHtml5AttributeName* ATTR_EQUALROWS; + static nsHtml5AttributeName* ATTR_HSPACE; + static nsHtml5AttributeName* ATTR_ISMAP; + static nsHtml5AttributeName* ATTR_LOCAL; + static nsHtml5AttributeName* ATTR_LSPACE; + static nsHtml5AttributeName* ATTR_MOVABLELIMITS; + static nsHtml5AttributeName* ATTR_NOTATION; + static nsHtml5AttributeName* ATTR_ONDATAAVAILABLE; + static nsHtml5AttributeName* ATTR_ONPASTE; + static nsHtml5AttributeName* ATTR_RSPACE; + static nsHtml5AttributeName* ATTR_ROWALIGN; + static nsHtml5AttributeName* ATTR_ROTATE; + static nsHtml5AttributeName* ATTR_SEPARATOR; + static nsHtml5AttributeName* ATTR_SEPARATORS; + static nsHtml5AttributeName* ATTR_VSPACE; + static nsHtml5AttributeName* ATTR_XCHANNELSELECTOR; + static nsHtml5AttributeName* ATTR_YCHANNELSELECTOR; + static nsHtml5AttributeName* ATTR_ENABLE_BACKGROUND; + static nsHtml5AttributeName* ATTR_ONDBLCLICK; + static nsHtml5AttributeName* ATTR_ONABORT; + static nsHtml5AttributeName* ATTR_CALCMODE; + static nsHtml5AttributeName* ATTR_CHECKED; + static nsHtml5AttributeName* ATTR_FENCE; + static nsHtml5AttributeName* ATTR_ONSCROLL; + static nsHtml5AttributeName* ATTR_ONACTIVATE; + static nsHtml5AttributeName* ATTR_OPACITY; + static nsHtml5AttributeName* ATTR_SPACING; + static nsHtml5AttributeName* ATTR_SPECULAREXPONENT; + static nsHtml5AttributeName* ATTR_SPECULARCONSTANT; + static nsHtml5AttributeName* ATTR_BORDER; + static nsHtml5AttributeName* ATTR_ID; + static nsHtml5AttributeName* ATTR_GRADIENTTRANSFORM; + static nsHtml5AttributeName* ATTR_GRADIENTUNITS; + static nsHtml5AttributeName* ATTR_HIDDEN; + static nsHtml5AttributeName* ATTR_HEADERS; + static nsHtml5AttributeName* ATTR_LOADING; + static nsHtml5AttributeName* ATTR_READONLY; + static nsHtml5AttributeName* ATTR_RENDERING_INTENT; + static nsHtml5AttributeName* ATTR_SEED; + static nsHtml5AttributeName* ATTR_SRCDOC; + static nsHtml5AttributeName* ATTR_STDDEVIATION; + static nsHtml5AttributeName* ATTR_SANDBOX; + static nsHtml5AttributeName* ATTR_WORD_SPACING; + static nsHtml5AttributeName* ATTR_ACCENTUNDER; + static nsHtml5AttributeName* ATTR_ACCEPT_CHARSET; + static nsHtml5AttributeName* ATTR_ACCESSKEY; + static nsHtml5AttributeName* ATTR_ACCENT; + static nsHtml5AttributeName* ATTR_ACCEPT; + static nsHtml5AttributeName* ATTR_BEVELLED; + static nsHtml5AttributeName* ATTR_BASEFREQUENCY; + static nsHtml5AttributeName* ATTR_BASELINE_SHIFT; + static nsHtml5AttributeName* ATTR_BASEPROFILE; + static nsHtml5AttributeName* ATTR_BASELINE; + static nsHtml5AttributeName* ATTR_BASE; + static nsHtml5AttributeName* ATTR_CODE; + static nsHtml5AttributeName* ATTR_CODETYPE; + static nsHtml5AttributeName* ATTR_CODEBASE; + static nsHtml5AttributeName* ATTR_CITE; + static nsHtml5AttributeName* ATTR_DEFER; + static nsHtml5AttributeName* ATTR_DATETIME; + static nsHtml5AttributeName* ATTR_DIRECTION; + static nsHtml5AttributeName* ATTR_EDGEMODE; + static nsHtml5AttributeName* ATTR_EDGE; + static nsHtml5AttributeName* ATTR_ENTERKEYHINT; + static nsHtml5AttributeName* ATTR_FACE; + static nsHtml5AttributeName* ATTR_INDEX; + static nsHtml5AttributeName* ATTR_INTERCEPT; + static nsHtml5AttributeName* ATTR_INTEGRITY; + static nsHtml5AttributeName* ATTR_LINEBREAK; + static nsHtml5AttributeName* ATTR_LABEL; + static nsHtml5AttributeName* ATTR_LINETHICKNESS; + static nsHtml5AttributeName* ATTR_MODE; + static nsHtml5AttributeName* ATTR_NAME; + static nsHtml5AttributeName* ATTR_NORESIZE; + static nsHtml5AttributeName* ATTR_ONBEFOREUNLOAD; + static nsHtml5AttributeName* ATTR_ONREPEAT; + static nsHtml5AttributeName* ATTR_OBJECT; + static nsHtml5AttributeName* ATTR_ONSELECT; + static nsHtml5AttributeName* ATTR_ORDER; + static nsHtml5AttributeName* ATTR_OTHER; + static nsHtml5AttributeName* ATTR_ONRESET; + static nsHtml5AttributeName* ATTR_ONREADYSTATECHANGE; + static nsHtml5AttributeName* ATTR_ONMESSAGE; + static nsHtml5AttributeName* ATTR_ONBEGIN; + static nsHtml5AttributeName* ATTR_ONBEFOREPRINT; + static nsHtml5AttributeName* ATTR_ORIENT; + static nsHtml5AttributeName* ATTR_ORIENTATION; + static nsHtml5AttributeName* ATTR_ONBEFORECOPY; + static nsHtml5AttributeName* ATTR_ONSELECTSTART; + static nsHtml5AttributeName* ATTR_ONBEFOREPASTE; + static nsHtml5AttributeName* ATTR_ONKEYPRESS; + static nsHtml5AttributeName* ATTR_ONKEYUP; + static nsHtml5AttributeName* ATTR_ONBEFORECUT; + static nsHtml5AttributeName* ATTR_ONKEYDOWN; + static nsHtml5AttributeName* ATTR_ONRESIZE; + static nsHtml5AttributeName* ATTR_REPEAT; + static nsHtml5AttributeName* ATTR_REFERRERPOLICY; + static nsHtml5AttributeName* ATTR_RULES; + static nsHtml5AttributeName* ATTR_ROLE; + static nsHtml5AttributeName* ATTR_REPEATCOUNT; + static nsHtml5AttributeName* ATTR_REPEATDUR; + static nsHtml5AttributeName* ATTR_SELECTED; + static nsHtml5AttributeName* ATTR_SIZES; + static nsHtml5AttributeName* ATTR_SUPERSCRIPTSHIFT; + static nsHtml5AttributeName* ATTR_STRETCHY; + static nsHtml5AttributeName* ATTR_SCHEME; + static nsHtml5AttributeName* ATTR_SPREADMETHOD; + static nsHtml5AttributeName* ATTR_SELECTION; + static nsHtml5AttributeName* ATTR_SIZE; + static nsHtml5AttributeName* ATTR_TYPE; + static nsHtml5AttributeName* ATTR_DIFFUSECONSTANT; + static nsHtml5AttributeName* ATTR_HREF; + static nsHtml5AttributeName* ATTR_HREFLANG; + static nsHtml5AttributeName* ATTR_ONAFTERPRINT; + static nsHtml5AttributeName* ATTR_PROFILE; + static nsHtml5AttributeName* ATTR_SURFACESCALE; + static nsHtml5AttributeName* ATTR_XREF; + static nsHtml5AttributeName* ATTR_ALIGN; + static nsHtml5AttributeName* ATTR_ALIGNMENT_BASELINE; + static nsHtml5AttributeName* ATTR_ALIGNMENTSCOPE; + static nsHtml5AttributeName* ATTR_DRAGGABLE; + static nsHtml5AttributeName* ATTR_HEIGHT; + static nsHtml5AttributeName* ATTR_IMAGESIZES; + static nsHtml5AttributeName* ATTR_IMAGESRCSET; + static nsHtml5AttributeName* ATTR_IMAGE_RENDERING; + static nsHtml5AttributeName* ATTR_LANGUAGE; + static nsHtml5AttributeName* ATTR_LANG; + static nsHtml5AttributeName* ATTR_LARGEOP; + static nsHtml5AttributeName* ATTR_LONGDESC; + static nsHtml5AttributeName* ATTR_LENGTHADJUST; + static nsHtml5AttributeName* ATTR_MARGINHEIGHT; + static nsHtml5AttributeName* ATTR_MARGINWIDTH; + static nsHtml5AttributeName* ATTR_ORIGIN; + static nsHtml5AttributeName* ATTR_PING; + static nsHtml5AttributeName* ATTR_TARGET; + static nsHtml5AttributeName* ATTR_TARGETX; + static nsHtml5AttributeName* ATTR_TARGETY; + static nsHtml5AttributeName* ATTR_ARCHIVE; + static nsHtml5AttributeName* ATTR_HIGH; + static nsHtml5AttributeName* ATTR_LIGHTING_COLOR; + static nsHtml5AttributeName* ATTR_MATHBACKGROUND; + static nsHtml5AttributeName* ATTR_METHOD; + static nsHtml5AttributeName* ATTR_MATHVARIANT; + static nsHtml5AttributeName* ATTR_MATHCOLOR; + static nsHtml5AttributeName* ATTR_MATHSIZE; + static nsHtml5AttributeName* ATTR_NOSHADE; + static nsHtml5AttributeName* ATTR_ONCHANGE; + static nsHtml5AttributeName* ATTR_PATHLENGTH; + static nsHtml5AttributeName* ATTR_PATH; + static nsHtml5AttributeName* ATTR_ALTIMG; + static nsHtml5AttributeName* ATTR_ACTIONTYPE; + static nsHtml5AttributeName* ATTR_ACTION; + static nsHtml5AttributeName* ATTR_ACTIVE; + static nsHtml5AttributeName* ATTR_ADDITIVE; + static nsHtml5AttributeName* ATTR_BEGIN; + static nsHtml5AttributeName* ATTR_DOMINANT_BASELINE; + static nsHtml5AttributeName* ATTR_DIVISOR; + static nsHtml5AttributeName* ATTR_DEFINITIONURL; + static nsHtml5AttributeName* ATTR_LIMITINGCONEANGLE; + static nsHtml5AttributeName* ATTR_MEDIA; + static nsHtml5AttributeName* ATTR_MANIFEST; + static nsHtml5AttributeName* ATTR_ONFINISH; + static nsHtml5AttributeName* ATTR_OPTIMUM; + static nsHtml5AttributeName* ATTR_RADIOGROUP; + static nsHtml5AttributeName* ATTR_RADIUS; + static nsHtml5AttributeName* ATTR_SCRIPTLEVEL; + static nsHtml5AttributeName* ATTR_SCRIPTSIZEMULTIPLIER; + static nsHtml5AttributeName* ATTR_SCRIPTMINSIZE; + static nsHtml5AttributeName* ATTR_TABINDEX; + static nsHtml5AttributeName* ATTR_VALIGN; + static nsHtml5AttributeName* ATTR_VISIBILITY; + static nsHtml5AttributeName* ATTR_BACKGROUND; + static nsHtml5AttributeName* ATTR_LINK; + static nsHtml5AttributeName* ATTR_MARKER_MID; + static nsHtml5AttributeName* ATTR_MARKERHEIGHT; + static nsHtml5AttributeName* ATTR_MARKER_END; + static nsHtml5AttributeName* ATTR_MASK; + static nsHtml5AttributeName* ATTR_MARKER_START; + static nsHtml5AttributeName* ATTR_MARKERWIDTH; + static nsHtml5AttributeName* ATTR_MASKUNITS; + static nsHtml5AttributeName* ATTR_MARKERUNITS; + static nsHtml5AttributeName* ATTR_MASKCONTENTUNITS; + static nsHtml5AttributeName* ATTR_AMPLITUDE; + static nsHtml5AttributeName* ATTR_CELLSPACING; + static nsHtml5AttributeName* ATTR_CELLPADDING; + static nsHtml5AttributeName* ATTR_DECLARE; + static nsHtml5AttributeName* ATTR_FILL_RULE; + static nsHtml5AttributeName* ATTR_FILL; + static nsHtml5AttributeName* ATTR_FILL_OPACITY; + static nsHtml5AttributeName* ATTR_MAXLENGTH; + static nsHtml5AttributeName* ATTR_ONCLICK; + static nsHtml5AttributeName* ATTR_ONBLUR; + static nsHtml5AttributeName* ATTR_REPLACE; + static nsHtml5AttributeName* ATTR_ROWLINES; + static nsHtml5AttributeName* ATTR_SCALE; + static nsHtml5AttributeName* ATTR_STYLE; + static nsHtml5AttributeName* ATTR_TABLEVALUES; + static nsHtml5AttributeName* ATTR_TITLE; + static nsHtml5AttributeName* ATTR_AZIMUTH; + static nsHtml5AttributeName* ATTR_FORMAT; + static nsHtml5AttributeName* ATTR_FRAMEBORDER; + static nsHtml5AttributeName* ATTR_FRAME; + static nsHtml5AttributeName* ATTR_FRAMESPACING; + static nsHtml5AttributeName* ATTR_FROM; + static nsHtml5AttributeName* ATTR_FORM; + static nsHtml5AttributeName* ATTR_PROMPT; + static nsHtml5AttributeName* ATTR_PRIMITIVEUNITS; + static nsHtml5AttributeName* ATTR_SYMMETRIC; + static nsHtml5AttributeName* ATTR_SUMMARY; + static nsHtml5AttributeName* ATTR_USEMAP; + static nsHtml5AttributeName* ATTR_ZOOMANDPAN; + static nsHtml5AttributeName* ATTR_ASYNC; + static nsHtml5AttributeName* ATTR_ALINK; + static nsHtml5AttributeName* ATTR_IN; + static nsHtml5AttributeName* ATTR_ICON; + static nsHtml5AttributeName* ATTR_KERNELMATRIX; + static nsHtml5AttributeName* ATTR_KERNING; + static nsHtml5AttributeName* ATTR_KERNELUNITLENGTH; + static nsHtml5AttributeName* ATTR_ONUNLOAD; + static nsHtml5AttributeName* ATTR_OPEN; + static nsHtml5AttributeName* ATTR_ONINVALID; + static nsHtml5AttributeName* ATTR_ONEND; + static nsHtml5AttributeName* ATTR_ONINPUT; + static nsHtml5AttributeName* ATTR_POINTER_EVENTS; + static nsHtml5AttributeName* ATTR_POINTS; + static nsHtml5AttributeName* ATTR_POINTSATX; + static nsHtml5AttributeName* ATTR_POINTSATY; + static nsHtml5AttributeName* ATTR_POINTSATZ; + static nsHtml5AttributeName* ATTR_SPAN; + static nsHtml5AttributeName* ATTR_STANDBY; + static nsHtml5AttributeName* ATTR_TRANSFORM_ORIGIN; + static nsHtml5AttributeName* ATTR_TRANSFORM; + static nsHtml5AttributeName* ATTR_VLINK; + static nsHtml5AttributeName* ATTR_WHEN; + static nsHtml5AttributeName* ATTR_XLINK_HREF; + static nsHtml5AttributeName* ATTR_XLINK_TITLE; + static nsHtml5AttributeName* ATTR_XLINK_ROLE; + static nsHtml5AttributeName* ATTR_XLINK_ARCROLE; + static nsHtml5AttributeName* ATTR_XMLNS_XLINK; + static nsHtml5AttributeName* ATTR_XMLNS; + static nsHtml5AttributeName* ATTR_XLINK_TYPE; + static nsHtml5AttributeName* ATTR_XLINK_SHOW; + static nsHtml5AttributeName* ATTR_XLINK_ACTUATE; + static nsHtml5AttributeName* ATTR_AUTOPLAY; + static nsHtml5AttributeName* ATTR_AUTOCOMPLETE; + static nsHtml5AttributeName* ATTR_AUTOFOCUS; + static nsHtml5AttributeName* ATTR_AUTOCAPITALIZE; + static nsHtml5AttributeName* ATTR_BGCOLOR; + static nsHtml5AttributeName* ATTR_COLOR_PROFILE; + static nsHtml5AttributeName* ATTR_COLOR_RENDERING; + static nsHtml5AttributeName* ATTR_COLOR_INTERPOLATION; + static nsHtml5AttributeName* ATTR_COLOR; + static nsHtml5AttributeName* ATTR_COLOR_INTERPOLATION_FILTERS; + static nsHtml5AttributeName* ATTR_ENCODING; + static nsHtml5AttributeName* ATTR_EXPONENT; + static nsHtml5AttributeName* ATTR_FLOOD_COLOR; + static nsHtml5AttributeName* ATTR_FLOOD_OPACITY; + static nsHtml5AttributeName* ATTR_LQUOTE; + static nsHtml5AttributeName* ATTR_NUMOCTAVES; + static nsHtml5AttributeName* ATTR_NOMODULE; + static nsHtml5AttributeName* ATTR_ONLOAD; + static nsHtml5AttributeName* ATTR_ONMOUSEWHEEL; + static nsHtml5AttributeName* ATTR_ONMOUSEENTER; + static nsHtml5AttributeName* ATTR_ONMOUSEOVER; + static nsHtml5AttributeName* ATTR_ONFOCUSIN; + static nsHtml5AttributeName* ATTR_ONCONTEXTMENU; + static nsHtml5AttributeName* ATTR_ONZOOM; + static nsHtml5AttributeName* ATTR_ONCOPY; + static nsHtml5AttributeName* ATTR_ONMOUSELEAVE; + static nsHtml5AttributeName* ATTR_ONMOUSEMOVE; + static nsHtml5AttributeName* ATTR_ONMOUSEUP; + static nsHtml5AttributeName* ATTR_ONFOCUS; + static nsHtml5AttributeName* ATTR_ONMOUSEOUT; + static nsHtml5AttributeName* ATTR_ONFOCUSOUT; + static nsHtml5AttributeName* ATTR_ONMOUSEDOWN; + static nsHtml5AttributeName* ATTR_TO; + static nsHtml5AttributeName* ATTR_RQUOTE; + static nsHtml5AttributeName* ATTR_STROKE_LINECAP; + static nsHtml5AttributeName* ATTR_STROKE_DASHARRAY; + static nsHtml5AttributeName* ATTR_STROKE_DASHOFFSET; + static nsHtml5AttributeName* ATTR_STROKE_LINEJOIN; + static nsHtml5AttributeName* ATTR_STROKE_MITERLIMIT; + static nsHtml5AttributeName* ATTR_STROKE; + static nsHtml5AttributeName* ATTR_SCROLLING; + static nsHtml5AttributeName* ATTR_STROKE_WIDTH; + static nsHtml5AttributeName* ATTR_STROKE_OPACITY; + static nsHtml5AttributeName* ATTR_COMPACT; + static nsHtml5AttributeName* ATTR_CLIP; + static nsHtml5AttributeName* ATTR_CLIP_RULE; + static nsHtml5AttributeName* ATTR_CLIP_PATH; + static nsHtml5AttributeName* ATTR_CLIPPATHUNITS; + static nsHtml5AttributeName* ATTR_DISPLAY; + static nsHtml5AttributeName* ATTR_DISPLAYSTYLE; + static nsHtml5AttributeName* ATTR_GLYPH_ORIENTATION_VERTICAL; + static nsHtml5AttributeName* ATTR_GLYPH_ORIENTATION_HORIZONTAL; + static nsHtml5AttributeName* ATTR_GLYPHREF; + static nsHtml5AttributeName* ATTR_HTTP_EQUIV; + static nsHtml5AttributeName* ATTR_KEYPOINTS; + static nsHtml5AttributeName* ATTR_LOOP; + static nsHtml5AttributeName* ATTR_PROPERTY; + static nsHtml5AttributeName* ATTR_SCOPED; + static nsHtml5AttributeName* ATTR_STEP; + static nsHtml5AttributeName* ATTR_SHAPE_RENDERING; + static nsHtml5AttributeName* ATTR_SCOPE; + static nsHtml5AttributeName* ATTR_SHAPE; + static nsHtml5AttributeName* ATTR_SLOPE; + static nsHtml5AttributeName* ATTR_STOP_COLOR; + static nsHtml5AttributeName* ATTR_STOP_OPACITY; + static nsHtml5AttributeName* ATTR_TEMPLATE; + static nsHtml5AttributeName* ATTR_WRAP; + static nsHtml5AttributeName* ATTR_ABBR; + static nsHtml5AttributeName* ATTR_ATTRIBUTENAME; + static nsHtml5AttributeName* ATTR_ATTRIBUTETYPE; + static nsHtml5AttributeName* ATTR_CHAR; + static nsHtml5AttributeName* ATTR_COORDS; + static nsHtml5AttributeName* ATTR_CHAROFF; + static nsHtml5AttributeName* ATTR_CHARSET; + static nsHtml5AttributeName* ATTR_NOWRAP; + static nsHtml5AttributeName* ATTR_NOHREF; + static nsHtml5AttributeName* ATTR_ONDRAG; + static nsHtml5AttributeName* ATTR_ONDRAGENTER; + static nsHtml5AttributeName* ATTR_ONDRAGOVER; + static nsHtml5AttributeName* ATTR_ONDRAGEND; + static nsHtml5AttributeName* ATTR_ONDROP; + static nsHtml5AttributeName* ATTR_ONDRAGDROP; + static nsHtml5AttributeName* ATTR_ONERROR; + static nsHtml5AttributeName* ATTR_OPERATOR; + static nsHtml5AttributeName* ATTR_OVERFLOW; + static nsHtml5AttributeName* ATTR_ONDRAGSTART; + static nsHtml5AttributeName* ATTR_ONDRAGLEAVE; + static nsHtml5AttributeName* ATTR_STARTOFFSET; + static nsHtml5AttributeName* ATTR_START; + static nsHtml5AttributeName* ATTR_AS; + static nsHtml5AttributeName* ATTR_AXIS; + static nsHtml5AttributeName* ATTR_BIAS; + static nsHtml5AttributeName* ATTR_COLSPAN; + static nsHtml5AttributeName* ATTR_CLASSID; + static nsHtml5AttributeName* ATTR_CROSSORIGIN; + static nsHtml5AttributeName* ATTR_COLS; + static nsHtml5AttributeName* ATTR_CURSOR; + static nsHtml5AttributeName* ATTR_CLOSURE; + static nsHtml5AttributeName* ATTR_CLOSE; + static nsHtml5AttributeName* ATTR_CLASS; + static nsHtml5AttributeName* ATTR_IS; + static nsHtml5AttributeName* ATTR_KEYSYSTEM; + static nsHtml5AttributeName* ATTR_KEYSPLINES; + static nsHtml5AttributeName* ATTR_LOWSRC; + static nsHtml5AttributeName* ATTR_MAXSIZE; + static nsHtml5AttributeName* ATTR_MINSIZE; + static nsHtml5AttributeName* ATTR_OFFSET; + static nsHtml5AttributeName* ATTR_PRESERVEALPHA; + static nsHtml5AttributeName* ATTR_PRESERVEASPECTRATIO; + static nsHtml5AttributeName* ATTR_ROWSPAN; + static nsHtml5AttributeName* ATTR_ROWSPACING; + static nsHtml5AttributeName* ATTR_ROWS; + static nsHtml5AttributeName* ATTR_SRCSET; + static nsHtml5AttributeName* ATTR_SUBSCRIPTSHIFT; + static nsHtml5AttributeName* ATTR_VERSION; + static nsHtml5AttributeName* ATTR_ALTTEXT; + static nsHtml5AttributeName* ATTR_CONTENTEDITABLE; + static nsHtml5AttributeName* ATTR_CONTROLS; + static nsHtml5AttributeName* ATTR_CONTENT; + static nsHtml5AttributeName* ATTR_CONTEXTMENU; + static nsHtml5AttributeName* ATTR_DEPTH; + static nsHtml5AttributeName* ATTR_ENCTYPE; + static nsHtml5AttributeName* ATTR_FONT_STRETCH; + static nsHtml5AttributeName* ATTR_FILTER; + static nsHtml5AttributeName* ATTR_FONTWEIGHT; + static nsHtml5AttributeName* ATTR_FONT_WEIGHT; + static nsHtml5AttributeName* ATTR_FONTSTYLE; + static nsHtml5AttributeName* ATTR_FONT_STYLE; + static nsHtml5AttributeName* ATTR_FONTFAMILY; + static nsHtml5AttributeName* ATTR_FONT_FAMILY; + static nsHtml5AttributeName* ATTR_FONT_VARIANT; + static nsHtml5AttributeName* ATTR_FONT_SIZE_ADJUST; + static nsHtml5AttributeName* ATTR_FILTERUNITS; + static nsHtml5AttributeName* ATTR_FONTSIZE; + static nsHtml5AttributeName* ATTR_FONT_SIZE; + static nsHtml5AttributeName* ATTR_KEYTIMES; + static nsHtml5AttributeName* ATTR_LETTER_SPACING; + static nsHtml5AttributeName* ATTR_LIST; + static nsHtml5AttributeName* ATTR_MULTIPLE; + static nsHtml5AttributeName* ATTR_RT; + static nsHtml5AttributeName* ATTR_ONSTOP; + static nsHtml5AttributeName* ATTR_ONSTART; + static nsHtml5AttributeName* ATTR_POSTER; + static nsHtml5AttributeName* ATTR_PATTERNTRANSFORM; + static nsHtml5AttributeName* ATTR_PATTERN; + static nsHtml5AttributeName* ATTR_PATTERNUNITS; + static nsHtml5AttributeName* ATTR_PATTERNCONTENTUNITS; + static nsHtml5AttributeName* ATTR_RESTART; + static nsHtml5AttributeName* ATTR_STITCHTILES; + static nsHtml5AttributeName* ATTR_SYSTEMLANGUAGE; + static nsHtml5AttributeName* ATTR_TEXT_RENDERING; + static nsHtml5AttributeName* ATTR_TEXT_DECORATION; + static nsHtml5AttributeName* ATTR_TEXT_ANCHOR; + static nsHtml5AttributeName* ATTR_TEXTLENGTH; + static nsHtml5AttributeName* ATTR_TEXT; + static nsHtml5AttributeName* ATTR_WRITING_MODE; + static nsHtml5AttributeName* ATTR_WIDTH; + static nsHtml5AttributeName* ATTR_ACCUMULATE; + static nsHtml5AttributeName* ATTR_COLUMNSPAN; + static nsHtml5AttributeName* ATTR_COLUMNLINES; + static nsHtml5AttributeName* ATTR_COLUMNALIGN; + static nsHtml5AttributeName* ATTR_COLUMNSPACING; + static nsHtml5AttributeName* ATTR_COLUMNWIDTH; + static nsHtml5AttributeName* ATTR_GROUPALIGN; + static nsHtml5AttributeName* ATTR_INPUTMODE; + static nsHtml5AttributeName* ATTR_ONSUBMIT; + static nsHtml5AttributeName* ATTR_ONCUT; + static nsHtml5AttributeName* ATTR_REQUIRED; + static nsHtml5AttributeName* ATTR_REQUIREDFEATURES; + static nsHtml5AttributeName* ATTR_RESULT; + static nsHtml5AttributeName* ATTR_REQUIREDEXTENSIONS; + static nsHtml5AttributeName* ATTR_VALUES; + static nsHtml5AttributeName* ATTR_VALUETYPE; + static nsHtml5AttributeName* ATTR_VALUE; + static nsHtml5AttributeName* ATTR_ELEVATION; + static nsHtml5AttributeName* ATTR_VIEWTARGET; + static nsHtml5AttributeName* ATTR_VIEWBOX; + static nsHtml5AttributeName* ATTR_CX; + static nsHtml5AttributeName* ATTR_DX; + static nsHtml5AttributeName* ATTR_FX; + static nsHtml5AttributeName* ATTR_RX; + static nsHtml5AttributeName* ATTR_REFX; + static nsHtml5AttributeName* ATTR_BY; + static nsHtml5AttributeName* ATTR_CY; + static nsHtml5AttributeName* ATTR_DY; + static nsHtml5AttributeName* ATTR_FY; + static nsHtml5AttributeName* ATTR_RY; + static nsHtml5AttributeName* ATTR_REFY; + + private: + static nsHtml5AttributeName** ATTRIBUTE_NAMES; + static staticJArray<int32_t, int32_t> ATTRIBUTE_HASHES; + + public: + static void initializeStatics(); + static void releaseStatics(); +}; + +#endif diff --git a/parser/html/nsHtml5AutoPauseUpdate.h b/parser/html/nsHtml5AutoPauseUpdate.h new file mode 100644 index 0000000000..16c298111d --- /dev/null +++ b/parser/html/nsHtml5AutoPauseUpdate.h @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#ifndef nsHtml5AutoPauseUpdate_h +#define nsHtml5AutoPauseUpdate_h + +#include "nsHtml5DocumentBuilder.h" + +class MOZ_RAII nsHtml5AutoPauseUpdate final { + private: + RefPtr<nsHtml5DocumentBuilder> mBuilder; + + public: + explicit nsHtml5AutoPauseUpdate(nsHtml5DocumentBuilder* aBuilder) + : mBuilder(aBuilder) { + mBuilder->EndDocUpdate(); + } + ~nsHtml5AutoPauseUpdate() { + // Something may have terminated the parser during the update pause. + if (!mBuilder->IsComplete()) { + mBuilder->BeginDocUpdate(); + } + } +}; + +#endif // nsHtml5AutoPauseUpdate_h diff --git a/parser/html/nsHtml5ByteReadable.h b/parser/html/nsHtml5ByteReadable.h new file mode 100644 index 0000000000..e2e318364c --- /dev/null +++ b/parser/html/nsHtml5ByteReadable.h @@ -0,0 +1,28 @@ +/* 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/. */ + +#ifndef nsHtml5ByteReadable_h +#define nsHtml5ByteReadable_h + +/** + * A weak reference wrapper around a byte array. + */ +class nsHtml5ByteReadable { + public: + nsHtml5ByteReadable(const uint8_t* aCurrent, const uint8_t* aEnd) + : current(aCurrent), end(aEnd) {} + + inline int32_t read() { + if (current < end) { + return *(current++); + } else { + return -1; + } + } + + private: + const uint8_t* current; + const uint8_t* end; +}; +#endif diff --git a/parser/html/nsHtml5ContentCreatorFunction.h b/parser/html/nsHtml5ContentCreatorFunction.h new file mode 100644 index 0000000000..32c23afa47 --- /dev/null +++ b/parser/html/nsHtml5ContentCreatorFunction.h @@ -0,0 +1,16 @@ +/* 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/. */ + +#ifndef nsHtml5ContentCreatorFunction_h +#define nsHtml5ContentCreatorFunction_h + +#include "nsGenericHTMLElement.h" +#include "mozilla/dom/SVGElementFactory.h" + +union nsHtml5ContentCreatorFunction { + mozilla::dom::HTMLContentCreatorFunction html; + mozilla::dom::SVGContentCreatorFunction svg; +}; + +#endif // nsHtml5ContentCreatorFunction_h diff --git a/parser/html/nsHtml5DependentUTF16Buffer.cpp b/parser/html/nsHtml5DependentUTF16Buffer.cpp new file mode 100644 index 0000000000..6372b6923b --- /dev/null +++ b/parser/html/nsHtml5DependentUTF16Buffer.cpp @@ -0,0 +1,30 @@ +/* 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/. */ + +#include "nsHtml5DependentUTF16Buffer.h" + +nsHtml5DependentUTF16Buffer::nsHtml5DependentUTF16Buffer( + const nsAString& aToWrap) + : nsHtml5UTF16Buffer(const_cast<char16_t*>(aToWrap.BeginReading()), + aToWrap.Length()) { + MOZ_COUNT_CTOR(nsHtml5DependentUTF16Buffer); +} + +nsHtml5DependentUTF16Buffer::~nsHtml5DependentUTF16Buffer() { + MOZ_COUNT_DTOR(nsHtml5DependentUTF16Buffer); +} + +already_AddRefed<nsHtml5OwningUTF16Buffer> +nsHtml5DependentUTF16Buffer::FalliblyCopyAsOwningBuffer() { + int32_t newLength = getEnd() - getStart(); + RefPtr<nsHtml5OwningUTF16Buffer> newObj = + nsHtml5OwningUTF16Buffer::FalliblyCreate(newLength); + if (!newObj) { + return nullptr; + } + newObj->setEnd(newLength); + memcpy(newObj->getBuffer(), getBuffer() + getStart(), + newLength * sizeof(char16_t)); + return newObj.forget(); +} diff --git a/parser/html/nsHtml5DependentUTF16Buffer.h b/parser/html/nsHtml5DependentUTF16Buffer.h new file mode 100644 index 0000000000..3713de8aca --- /dev/null +++ b/parser/html/nsHtml5DependentUTF16Buffer.h @@ -0,0 +1,30 @@ +/* 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/. */ + +#ifndef nsHtml5DependentUTF16Buffer_h +#define nsHtml5DependentUTF16Buffer_h + +#include "nscore.h" +#include "nsHtml5OwningUTF16Buffer.h" + +class MOZ_STACK_CLASS nsHtml5DependentUTF16Buffer : public nsHtml5UTF16Buffer { + public: + /** + * Wraps a string without taking ownership of the buffer. aToWrap MUST NOT + * go away or be shortened while nsHtml5DependentUTF16Buffer is in use. + */ + explicit nsHtml5DependentUTF16Buffer(const nsAString& aToWrap); + + ~nsHtml5DependentUTF16Buffer(); + + /** + * Copies the currently unconsumed part of this buffer into a new + * heap-allocated nsHtml5OwningUTF16Buffer. The new object is allocated + * with a fallible allocator. If the allocation fails, nullptr is returned. + * @return heap-allocated copy or nullptr if memory allocation failed + */ + already_AddRefed<nsHtml5OwningUTF16Buffer> FalliblyCopyAsOwningBuffer(); +}; + +#endif // nsHtml5DependentUTF16Buffer_h diff --git a/parser/html/nsHtml5DocumentBuilder.cpp b/parser/html/nsHtml5DocumentBuilder.cpp new file mode 100644 index 0000000000..e896edde56 --- /dev/null +++ b/parser/html/nsHtml5DocumentBuilder.cpp @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#include "nsHtml5DocumentBuilder.h" + +#include "mozilla/dom/ScriptLoader.h" +#include "mozilla/dom/LinkStyle.h" +#include "nsNameSpaceManager.h" + +using mozilla::dom::LinkStyle; + +NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHtml5DocumentBuilder, nsContentSink, + mOwnedElements) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHtml5DocumentBuilder) +NS_INTERFACE_MAP_END_INHERITING(nsContentSink) + +NS_IMPL_ADDREF_INHERITED(nsHtml5DocumentBuilder, nsContentSink) +NS_IMPL_RELEASE_INHERITED(nsHtml5DocumentBuilder, nsContentSink) + +nsHtml5DocumentBuilder::nsHtml5DocumentBuilder(bool aRunsToCompletion) + : mBroken(NS_OK), mFlushState(eHtml5FlushState::eNotFlushing) { + mRunsToCompletion = aRunsToCompletion; +} + +nsresult nsHtml5DocumentBuilder::Init(mozilla::dom::Document* aDoc, + nsIURI* aURI, nsISupports* aContainer, + nsIChannel* aChannel) { + return nsContentSink::Init(aDoc, aURI, aContainer, aChannel); +} + +nsHtml5DocumentBuilder::~nsHtml5DocumentBuilder() {} + +nsresult nsHtml5DocumentBuilder::MarkAsBroken(nsresult aReason) { + mBroken = aReason; + return aReason; +} + +void nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement) { + auto* linkStyle = LinkStyle::FromNode(*aElement); + if (!linkStyle) { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to style, but SVG wasn't disabled."); + return; + } + + // Break out of the doc update created by Flush() to zap a runnable + // waiting to call UpdateStyleSheet without the right observer + EndDocUpdate(); + + if (MOZ_UNLIKELY(!mParser)) { + // EndDocUpdate ran stuff that called nsIParser::Terminate() + return; + } + + linkStyle->SetEnableUpdates(true); + + auto updateOrError = + linkStyle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this); + + if (updateOrError.isOk() && updateOrError.unwrap().ShouldBlock() && + !mRunsToCompletion) { + ++mPendingSheetCount; + mScriptLoader->AddParserBlockingScriptExecutionBlocker(); + } + + // Re-open update + BeginDocUpdate(); +} + +void nsHtml5DocumentBuilder::SetDocumentMode(nsHtml5DocumentMode m) { + nsCompatibility mode = eCompatibility_NavQuirks; + const char* errMsgId = nullptr; + + switch (m) { + case STANDARDS_MODE: + mode = eCompatibility_FullStandards; + break; + case ALMOST_STANDARDS_MODE: + mode = eCompatibility_AlmostStandards; + errMsgId = "errAlmostStandardsDoctypeVerbose"; + break; + case QUIRKS_MODE: + mode = eCompatibility_NavQuirks; + errMsgId = "errQuirkyDoctypeVerbose"; + break; + } + mDocument->SetCompatibilityMode(mode); + + if (errMsgId) { + nsCOMPtr<nsIURI> docURI = mDocument->GetDocumentURI(); + bool isData = false; + docURI->SchemeIs("data", &isData); + bool isHttp = false; + docURI->SchemeIs("http", &isHttp); + bool isHttps = false; + docURI->SchemeIs("https", &isHttps); + + nsCOMPtr<nsIPrincipal> principal = mDocument->GetPrincipal(); + if (principal->GetIsNullPrincipal() && !isData && !isHttp && !isHttps) { + // Don't normally warn for null principals. It may well be internal + // documents for which the warning is not applicable. + return; + } + + nsContentUtils::ReportToConsole( + nsIScriptError::warningFlag, "HTML_PARSER__DOCTYPE"_ns, mDocument, + nsContentUtils::eHTMLPARSER_PROPERTIES, errMsgId); + } +} + +// nsContentSink overrides + +void nsHtml5DocumentBuilder::UpdateChildCounts() { + // No-op +} + +nsresult nsHtml5DocumentBuilder::FlushTags() { return NS_OK; } diff --git a/parser/html/nsHtml5DocumentBuilder.h b/parser/html/nsHtml5DocumentBuilder.h new file mode 100644 index 0000000000..16d7d7238b --- /dev/null +++ b/parser/html/nsHtml5DocumentBuilder.h @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#ifndef nsHtml5DocumentBuilder_h +#define nsHtml5DocumentBuilder_h + +#include "mozilla/dom/Document.h" +#include "nsContentSink.h" +#include "nsHtml5DocumentMode.h" +#include "nsIContent.h" + +namespace mozilla::dom { +class Document; +} + +typedef nsIContent* nsIContentPtr; + +enum eHtml5FlushState { + eNotFlushing = 0, // not flushing + eInFlush = 1, // the Flush() method is on the call stack + eInDocUpdate = 2, // inside an update batch on the document +}; + +class nsHtml5DocumentBuilder : public nsContentSink { + using Encoding = mozilla::Encoding; + template <typename T> + using NotNull = mozilla::NotNull<T>; + + public: + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5DocumentBuilder, + nsContentSink) + + NS_DECL_ISUPPORTS_INHERITED + + inline void HoldElement(already_AddRefed<nsIContent> aContent) { + *(mOwnedElements.AppendElement()) = aContent; + } + + nsresult Init(Document* aDoc, nsIURI* aURI, nsISupports* aContainer, + nsIChannel* aChannel); + + // Getters and setters for fields from nsContentSink + Document* GetDocument() { return mDocument; } + + nsNodeInfoManager* GetNodeInfoManager() { return mNodeInfoManager; } + + /** + * Marks this parser as broken and tells the stream parser (if any) to + * terminate. + * + * @return aReason for convenience + */ + virtual nsresult MarkAsBroken(nsresult aReason); + + /** + * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0) + * value if broken. + */ + inline nsresult IsBroken() { return mBroken; } + + inline bool IsComplete() { return !mParser; } + + inline void BeginDocUpdate() { + MOZ_RELEASE_ASSERT(IsInFlush(), "Tried to double-open doc update."); + MOZ_RELEASE_ASSERT(mParser, "Started doc update without parser."); + mFlushState = eInDocUpdate; + mDocument->BeginUpdate(); + } + + inline void EndDocUpdate() { + MOZ_RELEASE_ASSERT(IsInDocUpdate(), + "Tried to end doc update without one open."); + mFlushState = eInFlush; + mDocument->EndUpdate(); + } + + inline void BeginFlush() { + MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing, + "Tried to start a flush when already flushing."); + MOZ_RELEASE_ASSERT(mParser, "Started a flush without parser."); + mFlushState = eInFlush; + } + + inline void EndFlush() { + MOZ_RELEASE_ASSERT(IsInFlush(), "Tried to end flush when not flushing."); + mFlushState = eNotFlushing; + } + + inline bool IsInDocUpdate() { return mFlushState == eInDocUpdate; } + + inline bool IsInFlush() { return mFlushState == eInFlush; } + + /** + * Sets up style sheet load / parse + */ + void UpdateStyleSheet(nsIContent* aElement); + + void SetDocumentMode(nsHtml5DocumentMode m); + + void SetNodeInfoManager(nsNodeInfoManager* aManager) { + mNodeInfoManager = aManager; + } + + // nsContentSink methods + virtual void UpdateChildCounts() override; + virtual nsresult FlushTags() override; + + protected: + explicit nsHtml5DocumentBuilder(bool aRunsToCompletion); + virtual ~nsHtml5DocumentBuilder(); + + protected: + AutoTArray<nsCOMPtr<nsIContent>, 32> mOwnedElements; + /** + * Non-NS_OK if this parser should refuse to process any more input. + * For example, the parser needs to be marked as broken if it drops some + * input due to a memory allocation failure. In such a case, the whole + * parser needs to be marked as broken, because some input has been lost + * and parsing more input could lead to a DOM where pieces of HTML source + * that weren't supposed to become scripts become scripts. + */ + nsresult mBroken; + eHtml5FlushState mFlushState; +}; + +#endif // nsHtml5DocumentBuilder_h diff --git a/parser/html/nsHtml5DocumentMode.h b/parser/html/nsHtml5DocumentMode.h new file mode 100644 index 0000000000..962c7a66b4 --- /dev/null +++ b/parser/html/nsHtml5DocumentMode.h @@ -0,0 +1,10 @@ +/* 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/. */ + +#ifndef nsHtml5DocumentMode_h +#define nsHtml5DocumentMode_h + +enum nsHtml5DocumentMode { STANDARDS_MODE, ALMOST_STANDARDS_MODE, QUIRKS_MODE }; + +#endif // nsHtml5DocumentMode_h diff --git a/parser/html/nsHtml5ElementName.cpp b/parser/html/nsHtml5ElementName.cpp new file mode 100644 index 0000000000..93a6407d38 --- /dev/null +++ b/parser/html/nsHtml5ElementName.cpp @@ -0,0 +1,1495 @@ +/* + * Copyright (c) 2008-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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit ElementName.java instead and regenerate. + */ + +#define nsHtml5ElementName_cpp__ + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +#include "nsHtml5AttributeName.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5Portability.h" + +#include "nsHtml5ElementName.h" + +nsHtml5ElementName::nsHtml5ElementName( + nsAtom* name, nsAtom* camelCaseName, + mozilla::dom::HTMLContentCreatorFunction htmlCreator, + mozilla::dom::SVGContentCreatorFunction svgCreator, int32_t flags) + : name(name), + camelCaseName(camelCaseName), + htmlCreator(htmlCreator), + svgCreator(svgCreator), + flags(flags) { + MOZ_COUNT_CTOR(nsHtml5ElementName); +} + +nsHtml5ElementName::nsHtml5ElementName() + : name(nullptr), + camelCaseName(nullptr), + htmlCreator(NS_NewHTMLUnknownElement), + svgCreator(NS_NewSVGUnknownElement), + flags(nsHtml5TreeBuilder::OTHER | NOT_INTERNED) { + MOZ_COUNT_CTOR(nsHtml5ElementName); +} + +nsHtml5ElementName::~nsHtml5ElementName() { + MOZ_COUNT_DTOR(nsHtml5ElementName); +} + +nsHtml5ElementName* nsHtml5ElementName::ELT_ANNOTATION_XML = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BIG = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BDI = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BDO = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_COL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DEL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DFN = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DIR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DIV = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_IMG = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_INS = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_KBD = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MAP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_NAV = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_PRE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_A = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_B = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_RTC = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SUB = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SVG = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SUP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SET = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_USE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_VAR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_G = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_WBR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_XMP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_I = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_P = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_Q = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_S = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_U = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_H1 = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_H2 = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_H3 = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_H4 = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_H5 = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_H6 = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_AREA = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DATA = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCA = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_METADATA = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_META = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TEXTAREA = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCB = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_RB = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DESC = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DD = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BGSOUND = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_EMBED = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEBLEND = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEFLOOD = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_HEAD = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_LEGEND = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_NOEMBED = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TD = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_THEAD = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ASIDE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ARTICLE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BASE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BLOCKQUOTE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_CODE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_CIRCLE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_CITE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ELLIPSE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FETURBULENCE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEMERGENODE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEIMAGE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEMERGE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FETILE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FRAME = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FIGURE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FECOMPOSITE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_IMAGE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_IFRAME = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_LINE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MARQUEE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_POLYLINE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_PICTURE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SOURCE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_STRIKE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_STYLE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TABLE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TITLE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TIME = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TEMPLATE = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ALTGLYPHDEF = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_GLYPHREF = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DIALOG = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCG = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEDIFFUSELIGHTING = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FESPECULARLIGHTING = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_LISTING = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_STRONG = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ALTGLYPH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_CLIPPATH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MGLYPH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MATH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MPATH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_PATH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SWITCH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TEXTPATH = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_LI = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MI = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_LINK = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MARK = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MALIGNMARK = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MASK = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TRACK = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_HTML = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_OL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_LABEL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_UL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SMALL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SYMBOL = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ALTGLYPHITEM = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATETRANSFORM = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ACRONYM = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_EM = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FORM = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_PARAM = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATEMOTION = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BUTTON = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_CAPTION = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FIGCAPTION = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MN = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_KEYGEN = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MAIN = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_OPTION = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_POLYGON = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_PATTERN = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SPAN = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SECTION = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TSPAN = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_AUDIO = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MO = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_VIDEO = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_COLGROUP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEDISPLACEMENTMAP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_HGROUP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_RP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_OPTGROUP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SAMP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_STOP = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ABBR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATECOLOR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_CENTER = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_HR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FECOMPONENTTRANSFER = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FILTER = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FOOTER = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEGAUSSIANBLUR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_HEADER = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MARKER = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_METER = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_NOBR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TR = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_ADDRESS = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_CANVAS = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DEFS = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DETAILS = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MS = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_NOFRAMES = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_PROGRESS = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_APPLET = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BASEFONT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_DATALIST = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FOREIGNOBJECT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FIELDSET = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FRAMESET = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEOFFSET = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FESPOTLIGHT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEPOINTLIGHT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEDISTANTLIGHT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FONT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_INPUT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_LINEARGRADIENT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MTEXT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_NOSCRIPT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_RT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_OBJECT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_OUTPUT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_PLAINTEXT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_RECT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_RADIALGRADIENT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SELECT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SLOT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SCRIPT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TFOOT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TEXT = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_MENU = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEDROPSHADOW = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_VIEW = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FECOLORMATRIX = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FECONVOLVEMATRIX = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_BODY = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_FEMORPHOLOGY = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_RUBY = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_SUMMARY = nullptr; +nsHtml5ElementName* nsHtml5ElementName::ELT_TBODY = nullptr; +nsHtml5ElementName** nsHtml5ElementName::ELEMENT_NAMES = 0; +static int32_t const ELEMENT_HASHES_DATA[] = { + 1902641154, 1748359220, 2001349720, 876609538, 1798686984, 1971465813, + 2007781534, 59768833, 1730965751, 1756474198, 1868312196, 1939219752, + 1988763672, 2005324101, 2060065124, 52490899, 62390273, 1682547543, + 1740181637, 1749905526, 1766992520, 1818230786, 1881613047, 1907959605, + 1967760215, 1982935782, 1999397992, 2001392798, 2006329158, 2008851557, + 2085266636, 51961587, 57206291, 60352339, 67108865, 943718402, + 1699324759, 1733890180, 1747814436, 1749715159, 1752979652, 1757146773, + 1783388498, 1805502724, 1854228698, 1874053333, 1898223949, 1906087319, + 1932928296, 1965115924, 1968053806, 1973420034, 1983633431, 1998585858, + 2001309869, 2001392795, 2003183333, 2005925890, 2006974466, 2008325940, + 2021937364, 2068523856, 2092255447, 51435587, 52486755, 55110883, + 58773795, 60345171, 61395251, 62973651, 68681729, 910163970, + 1679960596, 1686491348, 1715310660, 1733054663, 1737099991, 1747176599, + 1748100148, 1749656156, 1749801286, 1751288021, 1755076808, 1756625221, + 1757268168, 1783210839, 1790207270, 1803929812, 1806806678, 1853642948, + 1857653029, 1870268949, 1881288348, 1884120164, 1899272519, 1904412884, + 1907435316, 1919418370, 1935549734, 1941221172, 1966223078, 1967795910, + 1971461414, 1971938532, 1982173479, 1983533124, 1986527234, 1990037800, + 1998724870, 2000525512, 2001349704, 2001349736, 2001392796, 2001495140, + 2004635806, 2005719336, 2006028454, 2006896969, 2007601444, 2008125638, + 2008340774, 2008994116, 2051837468, 2068523853, 2083120164, 2091479332, + 2092557349, 51434643, 51438659, 52485715, 52488851, 55104723, + 56151587, 57733651, 59244545, 59821379, 60347747, 60354131, + 61925907, 62450211, 63438849, 67633153, 69730305, 893386754, + 926941186, 960495618, 1681770564, 1686489160, 1689922072, 1703936002, + 1730150402, 1732381397, 1733076167, 1736200310, 1738539010, 1747048757, + 1747306711, 1747838298, 1748225318, 1749395095, 1749673195, 1749723735, + 1749813541, 1749932347, 1751386406, 1753362711, 1755148615, 1756600614, + 1757137429, 1757157700, 1763839627, 1782357526, 1783388497, 1786534215, + 1797585096, 1803876550, 1803929861, 1805647874, 1807599880, 1818755074, + 1854228692, 1854245076, 1864368130, 1870135298, 1873281026, 1874102998, + 1881498736, 1881669634, 1889085973, 1898753862, 1900845386, 1903302038, + 1905563974, 1906135367, 1907661127, 1914900309, 1925844629, 1934172497, + 1938817026, 1941178676, 1963982850, 1965334268, 1967128578, 1967788867, + 1967795958, 1968836118}; +staticJArray<int32_t, int32_t> nsHtml5ElementName::ELEMENT_HASHES = { + ELEMENT_HASHES_DATA, MOZ_ARRAY_LENGTH(ELEMENT_HASHES_DATA)}; +void nsHtml5ElementName::initializeStatics() { + ELT_ANNOTATION_XML = new nsHtml5ElementName( + nsGkAtoms::annotation_xml_, nsGkAtoms::annotation_xml_, + NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::ANNOTATION_XML | SCOPING_AS_MATHML); + ELT_BIG = new nsHtml5ElementName( + nsGkAtoms::big, nsGkAtoms::big, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_BDI = new nsHtml5ElementName(nsGkAtoms::bdi, nsGkAtoms::bdi, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_BDO = new nsHtml5ElementName(nsGkAtoms::bdo, nsGkAtoms::bdo, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_COL = new nsHtml5ElementName( + nsGkAtoms::col, nsGkAtoms::col, NS_NewHTMLTableColElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::COL | SPECIAL); + ELT_DEL = new nsHtml5ElementName( + nsGkAtoms::del, nsGkAtoms::del, NS_NewHTMLModElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_DFN = new nsHtml5ElementName(nsGkAtoms::dfn, nsGkAtoms::dfn, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_DIR = new nsHtml5ElementName( + nsGkAtoms::dir, nsGkAtoms::dir, NS_NewHTMLSharedElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_DIV = new nsHtml5ElementName( + nsGkAtoms::div, nsGkAtoms::div, NS_NewHTMLDivElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); + ELT_IMG = new nsHtml5ElementName( + nsGkAtoms::img, nsGkAtoms::img, NS_NewHTMLImageElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::IMG | SPECIAL); + ELT_INS = new nsHtml5ElementName( + nsGkAtoms::ins, nsGkAtoms::ins, NS_NewHTMLModElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_KBD = new nsHtml5ElementName(nsGkAtoms::kbd, nsGkAtoms::kbd, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_MAP = new nsHtml5ElementName( + nsGkAtoms::map, nsGkAtoms::map, NS_NewHTMLMapElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_NAV = new nsHtml5ElementName( + nsGkAtoms::nav, nsGkAtoms::nav, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_PRE = new nsHtml5ElementName( + nsGkAtoms::pre, nsGkAtoms::pre, NS_NewHTMLPreElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PRE_OR_LISTING | SPECIAL); + ELT_A = new nsHtml5ElementName(nsGkAtoms::a, nsGkAtoms::a, + NS_NewHTMLAnchorElement, NS_NewSVGAElement, + nsHtml5TreeBuilder::A); + ELT_B = new nsHtml5ElementName( + nsGkAtoms::b, nsGkAtoms::b, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_RTC = + new nsHtml5ElementName(nsGkAtoms::rtc, nsGkAtoms::rtc, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RB_OR_RTC | OPTIONAL_END_TAG); + ELT_SUB = new nsHtml5ElementName( + nsGkAtoms::sub, nsGkAtoms::sub, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); + ELT_SVG = new nsHtml5ElementName( + nsGkAtoms::svg, nsGkAtoms::svg, NS_NewHTMLUnknownElement, + NS_NewSVGSVGElement, nsHtml5TreeBuilder::SVG); + ELT_SUP = new nsHtml5ElementName( + nsGkAtoms::sup, nsGkAtoms::sup, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); + ELT_SET = new nsHtml5ElementName( + nsGkAtoms::set, nsGkAtoms::set, NS_NewHTMLUnknownElement, + NS_NewSVGSetElement, nsHtml5TreeBuilder::OTHER); + ELT_USE = new nsHtml5ElementName( + nsGkAtoms::use, nsGkAtoms::use, NS_NewHTMLUnknownElement, + NS_NewSVGUseElement, nsHtml5TreeBuilder::OTHER); + ELT_VAR = new nsHtml5ElementName( + nsGkAtoms::var, nsGkAtoms::var, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); + ELT_G = new nsHtml5ElementName(nsGkAtoms::g, nsGkAtoms::g, + NS_NewHTMLUnknownElement, NS_NewSVGGElement, + nsHtml5TreeBuilder::OTHER); + ELT_WBR = new nsHtml5ElementName(nsGkAtoms::wbr, nsGkAtoms::wbr, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::AREA_OR_WBR | SPECIAL); + ELT_XMP = new nsHtml5ElementName( + nsGkAtoms::xmp, nsGkAtoms::xmp, NS_NewHTMLPreElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::XMP | SPECIAL); + ELT_I = new nsHtml5ElementName( + nsGkAtoms::i, nsGkAtoms::i, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_P = new nsHtml5ElementName( + nsGkAtoms::p, nsGkAtoms::p, NS_NewHTMLParagraphElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::P | SPECIAL | OPTIONAL_END_TAG); + ELT_Q = new nsHtml5ElementName( + nsGkAtoms::q, nsGkAtoms::q, NS_NewHTMLSharedElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_S = new nsHtml5ElementName( + nsGkAtoms::s, nsGkAtoms::s, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_U = new nsHtml5ElementName( + nsGkAtoms::u, nsGkAtoms::u, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_H1 = new nsHtml5ElementName( + nsGkAtoms::h1, nsGkAtoms::h1, NS_NewHTMLHeadingElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); + ELT_H2 = new nsHtml5ElementName( + nsGkAtoms::h2, nsGkAtoms::h2, NS_NewHTMLHeadingElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); + ELT_H3 = new nsHtml5ElementName( + nsGkAtoms::h3, nsGkAtoms::h3, NS_NewHTMLHeadingElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); + ELT_H4 = new nsHtml5ElementName( + nsGkAtoms::h4, nsGkAtoms::h4, NS_NewHTMLHeadingElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); + ELT_H5 = new nsHtml5ElementName( + nsGkAtoms::h5, nsGkAtoms::h5, NS_NewHTMLHeadingElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); + ELT_H6 = new nsHtml5ElementName( + nsGkAtoms::h6, nsGkAtoms::h6, NS_NewHTMLHeadingElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL); + ELT_AREA = new nsHtml5ElementName( + nsGkAtoms::area, nsGkAtoms::area, NS_NewHTMLAreaElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::AREA_OR_WBR | SPECIAL); + ELT_DATA = new nsHtml5ElementName( + nsGkAtoms::data, nsGkAtoms::data, NS_NewHTMLDataElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_FEFUNCA = new nsHtml5ElementName( + nsGkAtoms::fefunca, nsGkAtoms::feFuncA, NS_NewHTMLUnknownElement, + NS_NewSVGFEFuncAElement, nsHtml5TreeBuilder::OTHER); + ELT_METADATA = new nsHtml5ElementName( + nsGkAtoms::metadata, nsGkAtoms::metadata, NS_NewHTMLUnknownElement, + NS_NewSVGMetadataElement, nsHtml5TreeBuilder::OTHER); + ELT_META = new nsHtml5ElementName( + nsGkAtoms::meta, nsGkAtoms::meta, NS_NewHTMLMetaElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::META | SPECIAL); + ELT_TEXTAREA = new nsHtml5ElementName( + nsGkAtoms::textarea, nsGkAtoms::textarea, NS_NewHTMLTextAreaElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::TEXTAREA | SPECIAL); + ELT_FEFUNCB = new nsHtml5ElementName( + nsGkAtoms::fefuncb, nsGkAtoms::feFuncB, NS_NewHTMLUnknownElement, + NS_NewSVGFEFuncBElement, nsHtml5TreeBuilder::OTHER); + ELT_RB = new nsHtml5ElementName( + nsGkAtoms::rb, nsGkAtoms::rb, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RB_OR_RTC | OPTIONAL_END_TAG); + ELT_DESC = new nsHtml5ElementName( + nsGkAtoms::desc, nsGkAtoms::desc, NS_NewHTMLUnknownElement, + NS_NewSVGDescElement, + nsHtml5TreeBuilder::FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG); + ELT_DD = new nsHtml5ElementName( + nsGkAtoms::dd, nsGkAtoms::dd, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::DD_OR_DT | SPECIAL | OPTIONAL_END_TAG); + ELT_BGSOUND = new nsHtml5ElementName( + nsGkAtoms::bgsound, nsGkAtoms::bgsound, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL); + ELT_EMBED = new nsHtml5ElementName( + nsGkAtoms::embed, nsGkAtoms::embed, NS_NewHTMLEmbedElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::EMBED | SPECIAL); + ELT_FEBLEND = new nsHtml5ElementName( + nsGkAtoms::feblend, nsGkAtoms::feBlend, NS_NewHTMLUnknownElement, + NS_NewSVGFEBlendElement, nsHtml5TreeBuilder::OTHER); + ELT_FEFLOOD = new nsHtml5ElementName( + nsGkAtoms::feflood, nsGkAtoms::feFlood, NS_NewHTMLUnknownElement, + NS_NewSVGFEFloodElement, nsHtml5TreeBuilder::OTHER); + ELT_HEAD = new nsHtml5ElementName( + nsGkAtoms::head, nsGkAtoms::head, NS_NewHTMLSharedElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::HEAD | SPECIAL | OPTIONAL_END_TAG); + ELT_LEGEND = new nsHtml5ElementName( + nsGkAtoms::legend, nsGkAtoms::legend, NS_NewHTMLLegendElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_NOEMBED = new nsHtml5ElementName( + nsGkAtoms::noembed, nsGkAtoms::noembed, NS_NewHTMLElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::NOEMBED | SPECIAL); + ELT_TD = new nsHtml5ElementName( + nsGkAtoms::td, nsGkAtoms::td, NS_NewHTMLTableCellElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG); + ELT_THEAD = new nsHtml5ElementName( + nsGkAtoms::thead, nsGkAtoms::thead, NS_NewHTMLTableSectionElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | + OPTIONAL_END_TAG); + ELT_ASIDE = new nsHtml5ElementName( + nsGkAtoms::aside, nsGkAtoms::aside, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_ARTICLE = new nsHtml5ElementName( + nsGkAtoms::article, nsGkAtoms::article, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_ANIMATE = new nsHtml5ElementName( + nsGkAtoms::animate, nsGkAtoms::animate, NS_NewHTMLUnknownElement, + NS_NewSVGAnimateElement, nsHtml5TreeBuilder::OTHER); + ELT_BASE = new nsHtml5ElementName( + nsGkAtoms::base, nsGkAtoms::base, NS_NewHTMLSharedElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::BASE | SPECIAL); + ELT_BLOCKQUOTE = new nsHtml5ElementName( + nsGkAtoms::blockquote, nsGkAtoms::blockquote, NS_NewHTMLSharedElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); + ELT_CODE = new nsHtml5ElementName( + nsGkAtoms::code, nsGkAtoms::code, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_CIRCLE = new nsHtml5ElementName( + nsGkAtoms::circle, nsGkAtoms::circle, NS_NewHTMLUnknownElement, + NS_NewSVGCircleElement, nsHtml5TreeBuilder::OTHER); + ELT_CITE = new nsHtml5ElementName(nsGkAtoms::cite, nsGkAtoms::cite, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_ELLIPSE = new nsHtml5ElementName( + nsGkAtoms::ellipse, nsGkAtoms::ellipse, NS_NewHTMLUnknownElement, + NS_NewSVGEllipseElement, nsHtml5TreeBuilder::OTHER); + ELT_FETURBULENCE = new nsHtml5ElementName( + nsGkAtoms::feturbulence, nsGkAtoms::feTurbulence, + NS_NewHTMLUnknownElement, NS_NewSVGFETurbulenceElement, + nsHtml5TreeBuilder::OTHER); + ELT_FEMERGENODE = new nsHtml5ElementName( + nsGkAtoms::femergenode, nsGkAtoms::feMergeNode, NS_NewHTMLUnknownElement, + NS_NewSVGFEMergeNodeElement, nsHtml5TreeBuilder::OTHER); + ELT_FEIMAGE = new nsHtml5ElementName( + nsGkAtoms::feimage, nsGkAtoms::feImage, NS_NewHTMLUnknownElement, + NS_NewSVGFEImageElement, nsHtml5TreeBuilder::OTHER); + ELT_FEMERGE = new nsHtml5ElementName( + nsGkAtoms::femerge, nsGkAtoms::feMerge, NS_NewHTMLUnknownElement, + NS_NewSVGFEMergeElement, nsHtml5TreeBuilder::OTHER); + ELT_FETILE = new nsHtml5ElementName( + nsGkAtoms::fetile, nsGkAtoms::feTile, NS_NewHTMLUnknownElement, + NS_NewSVGFETileElement, nsHtml5TreeBuilder::OTHER); + ELT_FRAME = new nsHtml5ElementName( + nsGkAtoms::frame, nsGkAtoms::frame, NS_NewHTMLFrameElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FRAME | SPECIAL); + ELT_FIGURE = new nsHtml5ElementName( + nsGkAtoms::figure, nsGkAtoms::figure, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_FECOMPOSITE = new nsHtml5ElementName( + nsGkAtoms::fecomposite, nsGkAtoms::feComposite, NS_NewHTMLUnknownElement, + NS_NewSVGFECompositeElement, nsHtml5TreeBuilder::OTHER); + ELT_IMAGE = new nsHtml5ElementName(nsGkAtoms::image, nsGkAtoms::image, + NS_NewHTMLElement, NS_NewSVGImageElement, + nsHtml5TreeBuilder::IMAGE); + ELT_IFRAME = new nsHtml5ElementName( + nsGkAtoms::iframe, nsGkAtoms::iframe, NS_NewHTMLIFrameElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::IFRAME | SPECIAL); + ELT_LINE = new nsHtml5ElementName( + nsGkAtoms::line, nsGkAtoms::line, NS_NewHTMLUnknownElement, + NS_NewSVGLineElement, nsHtml5TreeBuilder::OTHER); + ELT_MARQUEE = new nsHtml5ElementName( + nsGkAtoms::marquee, nsGkAtoms::marquee, NS_NewHTMLMarqueeElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::MARQUEE_OR_APPLET | SPECIAL | SCOPING); + ELT_POLYLINE = new nsHtml5ElementName( + nsGkAtoms::polyline, nsGkAtoms::polyline, NS_NewHTMLUnknownElement, + NS_NewSVGPolylineElement, nsHtml5TreeBuilder::OTHER); + ELT_PICTURE = new nsHtml5ElementName( + nsGkAtoms::picture, nsGkAtoms::picture, NS_NewHTMLPictureElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_SOURCE = new nsHtml5ElementName( + nsGkAtoms::source, nsGkAtoms::source, NS_NewHTMLSourceElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PARAM_OR_SOURCE_OR_TRACK); + ELT_STRIKE = new nsHtml5ElementName( + nsGkAtoms::strike, nsGkAtoms::strike, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_STYLE = new nsHtml5ElementName( + nsGkAtoms::style, nsGkAtoms::style, NS_NewHTMLStyleElement, + NS_NewSVGStyleElement, nsHtml5TreeBuilder::STYLE | SPECIAL); + ELT_TABLE = new nsHtml5ElementName( + nsGkAtoms::table, nsGkAtoms::table, NS_NewHTMLTableElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TABLE | SPECIAL | FOSTER_PARENTING | SCOPING); + ELT_TITLE = new nsHtml5ElementName( + nsGkAtoms::title, nsGkAtoms::title, NS_NewHTMLTitleElement, + NS_NewSVGTitleElement, + nsHtml5TreeBuilder::TITLE | SPECIAL | SCOPING_AS_SVG); + ELT_TIME = new nsHtml5ElementName( + nsGkAtoms::time, nsGkAtoms::time, NS_NewHTMLTimeElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_TEMPLATE = + new nsHtml5ElementName(nsGkAtoms::_template, nsGkAtoms::_template, + NS_NewHTMLTemplateElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TEMPLATE | SPECIAL | SCOPING); + ELT_ALTGLYPHDEF = new nsHtml5ElementName( + nsGkAtoms::altglyphdef, nsGkAtoms::altGlyphDef, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_GLYPHREF = new nsHtml5ElementName( + nsGkAtoms::glyphref, nsGkAtoms::glyphRef, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_DIALOG = new nsHtml5ElementName( + nsGkAtoms::dialog, nsGkAtoms::dialog, NS_NewHTMLDialogElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_FEFUNCG = new nsHtml5ElementName( + nsGkAtoms::fefuncg, nsGkAtoms::feFuncG, NS_NewHTMLUnknownElement, + NS_NewSVGFEFuncGElement, nsHtml5TreeBuilder::OTHER); + ELT_FEDIFFUSELIGHTING = new nsHtml5ElementName( + nsGkAtoms::fediffuselighting, nsGkAtoms::feDiffuseLighting, + NS_NewHTMLUnknownElement, NS_NewSVGFEDiffuseLightingElement, + nsHtml5TreeBuilder::OTHER); + ELT_FESPECULARLIGHTING = new nsHtml5ElementName( + nsGkAtoms::fespecularlighting, nsGkAtoms::feSpecularLighting, + NS_NewHTMLUnknownElement, NS_NewSVGFESpecularLightingElement, + nsHtml5TreeBuilder::OTHER); + ELT_LISTING = new nsHtml5ElementName( + nsGkAtoms::listing, nsGkAtoms::listing, NS_NewHTMLPreElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PRE_OR_LISTING | SPECIAL); + ELT_STRONG = new nsHtml5ElementName( + nsGkAtoms::strong, nsGkAtoms::strong, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_ALTGLYPH = new nsHtml5ElementName( + nsGkAtoms::altglyph, nsGkAtoms::altGlyph, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_CLIPPATH = new nsHtml5ElementName( + nsGkAtoms::clippath, nsGkAtoms::clipPath, NS_NewHTMLUnknownElement, + NS_NewSVGClipPathElement, nsHtml5TreeBuilder::OTHER); + ELT_MGLYPH = new nsHtml5ElementName( + nsGkAtoms::mglyph_, nsGkAtoms::mglyph_, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::MGLYPH_OR_MALIGNMARK); + ELT_MATH = new nsHtml5ElementName( + nsGkAtoms::math, nsGkAtoms::math, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::MATH); + ELT_MPATH = new nsHtml5ElementName( + nsGkAtoms::mpath, nsGkAtoms::mpath, NS_NewHTMLUnknownElement, + NS_NewSVGMPathElement, nsHtml5TreeBuilder::OTHER); + ELT_PATH = new nsHtml5ElementName( + nsGkAtoms::path, nsGkAtoms::path, NS_NewHTMLUnknownElement, + NS_NewSVGPathElement, nsHtml5TreeBuilder::OTHER); + ELT_TH = new nsHtml5ElementName( + nsGkAtoms::th, nsGkAtoms::th, NS_NewHTMLTableCellElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG); + ELT_SWITCH = new nsHtml5ElementName( + nsGkAtoms::svgSwitch, nsGkAtoms::svgSwitch, NS_NewHTMLUnknownElement, + NS_NewSVGSwitchElement, nsHtml5TreeBuilder::OTHER); + ELT_TEXTPATH = new nsHtml5ElementName( + nsGkAtoms::textpath, nsGkAtoms::textPath, NS_NewHTMLUnknownElement, + NS_NewSVGTextPathElement, nsHtml5TreeBuilder::OTHER); + ELT_LI = new nsHtml5ElementName( + nsGkAtoms::li, nsGkAtoms::li, NS_NewHTMLLIElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::LI | SPECIAL | OPTIONAL_END_TAG); + ELT_MI = new nsHtml5ElementName( + nsGkAtoms::mi_, nsGkAtoms::mi_, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); + ELT_LINK = new nsHtml5ElementName( + nsGkAtoms::link, nsGkAtoms::link, NS_NewHTMLLinkElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL); + ELT_MARK = new nsHtml5ElementName(nsGkAtoms::mark, nsGkAtoms::mark, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_MALIGNMARK = new nsHtml5ElementName( + nsGkAtoms::malignmark_, nsGkAtoms::malignmark_, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::MGLYPH_OR_MALIGNMARK); + ELT_MASK = new nsHtml5ElementName( + nsGkAtoms::mask, nsGkAtoms::mask, NS_NewHTMLUnknownElement, + NS_NewSVGMaskElement, nsHtml5TreeBuilder::OTHER); + ELT_TRACK = new nsHtml5ElementName( + nsGkAtoms::track, nsGkAtoms::track, NS_NewHTMLTrackElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::PARAM_OR_SOURCE_OR_TRACK | SPECIAL); + ELT_DL = new nsHtml5ElementName( + nsGkAtoms::dl, nsGkAtoms::dl, NS_NewHTMLSharedListElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::UL_OR_OL_OR_DL | SPECIAL); + ELT_HTML = new nsHtml5ElementName( + nsGkAtoms::html, nsGkAtoms::html, NS_NewHTMLSharedElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::HTML | SPECIAL | SCOPING | OPTIONAL_END_TAG); + ELT_OL = new nsHtml5ElementName( + nsGkAtoms::ol, nsGkAtoms::ol, NS_NewHTMLSharedListElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::UL_OR_OL_OR_DL | SPECIAL); + ELT_LABEL = new nsHtml5ElementName( + nsGkAtoms::label, nsGkAtoms::label, NS_NewHTMLLabelElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_UL = new nsHtml5ElementName( + nsGkAtoms::ul, nsGkAtoms::ul, NS_NewHTMLSharedListElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::UL_OR_OL_OR_DL | SPECIAL); + ELT_SMALL = new nsHtml5ElementName( + nsGkAtoms::small, nsGkAtoms::small, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_SYMBOL = new nsHtml5ElementName( + nsGkAtoms::symbol, nsGkAtoms::symbol, NS_NewHTMLUnknownElement, + NS_NewSVGSymbolElement, nsHtml5TreeBuilder::OTHER); + ELT_ALTGLYPHITEM = + new nsHtml5ElementName(nsGkAtoms::altglyphitem, nsGkAtoms::altGlyphItem, + NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_ANIMATETRANSFORM = new nsHtml5ElementName( + nsGkAtoms::animatetransform, nsGkAtoms::animateTransform, + NS_NewHTMLUnknownElement, NS_NewSVGAnimateTransformElement, + nsHtml5TreeBuilder::OTHER); + ELT_ACRONYM = new nsHtml5ElementName( + nsGkAtoms::acronym, nsGkAtoms::acronym, NS_NewHTMLElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_EM = new nsHtml5ElementName( + nsGkAtoms::em, nsGkAtoms::em, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_FORM = new nsHtml5ElementName( + nsGkAtoms::form, nsGkAtoms::form, NS_NewHTMLFormElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FORM | SPECIAL); + ELT_PARAM = new nsHtml5ElementName( + nsGkAtoms::param, nsGkAtoms::param, NS_NewHTMLSharedElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::PARAM_OR_SOURCE_OR_TRACK | SPECIAL); + ELT_ANIMATEMOTION = new nsHtml5ElementName( + nsGkAtoms::animatemotion, nsGkAtoms::animateMotion, + NS_NewHTMLUnknownElement, NS_NewSVGAnimateMotionElement, + nsHtml5TreeBuilder::OTHER); + ELT_BUTTON = new nsHtml5ElementName( + nsGkAtoms::button, nsGkAtoms::button, NS_NewHTMLButtonElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::BUTTON | SPECIAL); + ELT_CAPTION = new nsHtml5ElementName( + nsGkAtoms::caption, nsGkAtoms::caption, NS_NewHTMLTableCaptionElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::CAPTION | SPECIAL | SCOPING); + ELT_FIGCAPTION = new nsHtml5ElementName( + nsGkAtoms::figcaption, nsGkAtoms::figcaption, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_MN = new nsHtml5ElementName( + nsGkAtoms::mn_, nsGkAtoms::mn_, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); + ELT_KEYGEN = new nsHtml5ElementName( + nsGkAtoms::keygen, nsGkAtoms::keygen, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::KEYGEN | SPECIAL); + ELT_MAIN = new nsHtml5ElementName( + nsGkAtoms::main, nsGkAtoms::main, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_OPTION = new nsHtml5ElementName( + nsGkAtoms::option, nsGkAtoms::option, NS_NewHTMLOptionElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OPTION | OPTIONAL_END_TAG); + ELT_POLYGON = new nsHtml5ElementName( + nsGkAtoms::polygon, nsGkAtoms::polygon, NS_NewHTMLUnknownElement, + NS_NewSVGPolygonElement, nsHtml5TreeBuilder::OTHER); + ELT_PATTERN = new nsHtml5ElementName( + nsGkAtoms::pattern, nsGkAtoms::pattern, NS_NewHTMLUnknownElement, + NS_NewSVGPatternElement, nsHtml5TreeBuilder::OTHER); + ELT_SPAN = new nsHtml5ElementName( + nsGkAtoms::span, nsGkAtoms::span, NS_NewHTMLSpanElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); + ELT_SECTION = new nsHtml5ElementName( + nsGkAtoms::section, nsGkAtoms::section, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_TSPAN = new nsHtml5ElementName( + nsGkAtoms::tspan, nsGkAtoms::tspan, NS_NewHTMLUnknownElement, + NS_NewSVGTSpanElement, nsHtml5TreeBuilder::OTHER); + ELT_AUDIO = new nsHtml5ElementName( + nsGkAtoms::audio, nsGkAtoms::audio, NS_NewHTMLAudioElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_MO = new nsHtml5ElementName( + nsGkAtoms::mo_, nsGkAtoms::mo_, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); + ELT_VIDEO = new nsHtml5ElementName( + nsGkAtoms::video, nsGkAtoms::video, NS_NewHTMLVideoElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_COLGROUP = new nsHtml5ElementName( + nsGkAtoms::colgroup, nsGkAtoms::colgroup, NS_NewHTMLTableColElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::COLGROUP | SPECIAL | OPTIONAL_END_TAG); + ELT_FEDISPLACEMENTMAP = new nsHtml5ElementName( + nsGkAtoms::fedisplacementmap, nsGkAtoms::feDisplacementMap, + NS_NewHTMLUnknownElement, NS_NewSVGFEDisplacementMapElement, + nsHtml5TreeBuilder::OTHER); + ELT_HGROUP = new nsHtml5ElementName( + nsGkAtoms::hgroup, nsGkAtoms::hgroup, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_RP = new nsHtml5ElementName( + nsGkAtoms::rp, nsGkAtoms::rp, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RT_OR_RP | OPTIONAL_END_TAG); + ELT_OPTGROUP = new nsHtml5ElementName( + nsGkAtoms::optgroup, nsGkAtoms::optgroup, NS_NewHTMLOptGroupElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OPTGROUP | OPTIONAL_END_TAG); + ELT_SAMP = new nsHtml5ElementName(nsGkAtoms::samp, nsGkAtoms::samp, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_STOP = new nsHtml5ElementName( + nsGkAtoms::stop, nsGkAtoms::stop, NS_NewHTMLUnknownElement, + NS_NewSVGStopElement, nsHtml5TreeBuilder::OTHER); + ELT_BR = new nsHtml5ElementName(nsGkAtoms::br, nsGkAtoms::br, + NS_NewHTMLBRElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::BR | SPECIAL); + ELT_ABBR = new nsHtml5ElementName(nsGkAtoms::abbr, nsGkAtoms::abbr, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_ANIMATECOLOR = + new nsHtml5ElementName(nsGkAtoms::animatecolor, nsGkAtoms::animateColor, + NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::OTHER); + ELT_CENTER = new nsHtml5ElementName( + nsGkAtoms::center, nsGkAtoms::center, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); + ELT_HR = new nsHtml5ElementName(nsGkAtoms::hr, nsGkAtoms::hr, + NS_NewHTMLHRElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::HR | SPECIAL); + ELT_FEFUNCR = new nsHtml5ElementName( + nsGkAtoms::fefuncr, nsGkAtoms::feFuncR, NS_NewHTMLUnknownElement, + NS_NewSVGFEFuncRElement, nsHtml5TreeBuilder::OTHER); + ELT_FECOMPONENTTRANSFER = new nsHtml5ElementName( + nsGkAtoms::fecomponenttransfer, nsGkAtoms::feComponentTransfer, + NS_NewHTMLUnknownElement, NS_NewSVGFEComponentTransferElement, + nsHtml5TreeBuilder::OTHER); + ELT_FILTER = new nsHtml5ElementName( + nsGkAtoms::filter, nsGkAtoms::filter, NS_NewHTMLUnknownElement, + NS_NewSVGFilterElement, nsHtml5TreeBuilder::OTHER); + ELT_FOOTER = new nsHtml5ElementName( + nsGkAtoms::footer, nsGkAtoms::footer, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_FEGAUSSIANBLUR = new nsHtml5ElementName( + nsGkAtoms::fegaussianblur, nsGkAtoms::feGaussianBlur, + NS_NewHTMLUnknownElement, NS_NewSVGFEGaussianBlurElement, + nsHtml5TreeBuilder::OTHER); + ELT_HEADER = new nsHtml5ElementName( + nsGkAtoms::header, nsGkAtoms::header, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_MARKER = new nsHtml5ElementName( + nsGkAtoms::marker, nsGkAtoms::marker, NS_NewHTMLUnknownElement, + NS_NewSVGMarkerElement, nsHtml5TreeBuilder::OTHER); + ELT_METER = new nsHtml5ElementName( + nsGkAtoms::meter, nsGkAtoms::meter, NS_NewHTMLMeterElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_NOBR = new nsHtml5ElementName(nsGkAtoms::nobr, nsGkAtoms::nobr, + NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::NOBR); + ELT_TR = new nsHtml5ElementName( + nsGkAtoms::tr, nsGkAtoms::tr, NS_NewHTMLTableRowElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TR | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG); + ELT_ADDRESS = new nsHtml5ElementName( + nsGkAtoms::address, nsGkAtoms::address, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_CANVAS = new nsHtml5ElementName( + nsGkAtoms::canvas, nsGkAtoms::canvas, NS_NewHTMLCanvasElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_DEFS = new nsHtml5ElementName( + nsGkAtoms::defs, nsGkAtoms::defs, NS_NewHTMLUnknownElement, + NS_NewSVGDefsElement, nsHtml5TreeBuilder::OTHER); + ELT_DETAILS = new nsHtml5ElementName( + nsGkAtoms::details, nsGkAtoms::details, NS_NewHTMLDetailsElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_MS = new nsHtml5ElementName( + nsGkAtoms::ms_, nsGkAtoms::ms_, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); + ELT_NOFRAMES = new nsHtml5ElementName( + nsGkAtoms::noframes, nsGkAtoms::noframes, NS_NewHTMLElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::NOFRAMES | SPECIAL); + ELT_PROGRESS = new nsHtml5ElementName( + nsGkAtoms::progress, nsGkAtoms::progress, NS_NewHTMLProgressElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_DT = new nsHtml5ElementName( + nsGkAtoms::dt, nsGkAtoms::dt, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::DD_OR_DT | SPECIAL | OPTIONAL_END_TAG); + ELT_APPLET = new nsHtml5ElementName( + nsGkAtoms::applet, nsGkAtoms::applet, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::MARQUEE_OR_APPLET | SPECIAL | SCOPING); + ELT_BASEFONT = new nsHtml5ElementName( + nsGkAtoms::basefont, nsGkAtoms::basefont, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL); + ELT_DATALIST = new nsHtml5ElementName( + nsGkAtoms::datalist, nsGkAtoms::datalist, NS_NewHTMLDataListElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_FOREIGNOBJECT = new nsHtml5ElementName( + nsGkAtoms::foreignobject, nsGkAtoms::foreignObject, + NS_NewHTMLUnknownElement, NS_NewSVGForeignObjectElement, + nsHtml5TreeBuilder::FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG); + ELT_FIELDSET = new nsHtml5ElementName( + nsGkAtoms::fieldset, nsGkAtoms::fieldset, NS_NewHTMLFieldSetElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FIELDSET | SPECIAL); + ELT_FRAMESET = new nsHtml5ElementName( + nsGkAtoms::frameset, nsGkAtoms::frameset, NS_NewHTMLFrameSetElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FRAMESET | SPECIAL); + ELT_FEOFFSET = new nsHtml5ElementName( + nsGkAtoms::feoffset, nsGkAtoms::feOffset, NS_NewHTMLUnknownElement, + NS_NewSVGFEOffsetElement, nsHtml5TreeBuilder::OTHER); + ELT_FESPOTLIGHT = new nsHtml5ElementName( + nsGkAtoms::fespotlight, nsGkAtoms::feSpotLight, NS_NewHTMLUnknownElement, + NS_NewSVGFESpotLightElement, nsHtml5TreeBuilder::OTHER); + ELT_FEPOINTLIGHT = new nsHtml5ElementName( + nsGkAtoms::fepointlight, nsGkAtoms::fePointLight, + NS_NewHTMLUnknownElement, NS_NewSVGFEPointLightElement, + nsHtml5TreeBuilder::OTHER); + ELT_FEDISTANTLIGHT = new nsHtml5ElementName( + nsGkAtoms::fedistantlight, nsGkAtoms::feDistantLight, + NS_NewHTMLUnknownElement, NS_NewSVGFEDistantLightElement, + nsHtml5TreeBuilder::OTHER); + ELT_FONT = new nsHtml5ElementName( + nsGkAtoms::font, nsGkAtoms::font, NS_NewHTMLFontElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FONT); + ELT_INPUT = new nsHtml5ElementName( + nsGkAtoms::input, nsGkAtoms::input, NS_NewHTMLInputElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::INPUT | SPECIAL); + ELT_LINEARGRADIENT = new nsHtml5ElementName( + nsGkAtoms::lineargradient, nsGkAtoms::linearGradient, + NS_NewHTMLUnknownElement, NS_NewSVGLinearGradientElement, + nsHtml5TreeBuilder::OTHER); + ELT_MTEXT = new nsHtml5ElementName( + nsGkAtoms::mtext_, nsGkAtoms::mtext_, NS_NewHTMLUnknownElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML); + ELT_NOSCRIPT = new nsHtml5ElementName( + nsGkAtoms::noscript, nsGkAtoms::noscript, NS_NewHTMLElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::NOSCRIPT | SPECIAL); + ELT_RT = new nsHtml5ElementName( + nsGkAtoms::rt, nsGkAtoms::rt, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RT_OR_RP | OPTIONAL_END_TAG); + ELT_OBJECT = new nsHtml5ElementName( + nsGkAtoms::object, nsGkAtoms::object, NS_NewHTMLObjectElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OBJECT | SPECIAL | SCOPING); + ELT_OUTPUT = new nsHtml5ElementName( + nsGkAtoms::output, nsGkAtoms::output, NS_NewHTMLOutputElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OUTPUT); + ELT_PLAINTEXT = new nsHtml5ElementName( + nsGkAtoms::plaintext, nsGkAtoms::plaintext, NS_NewHTMLElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PLAINTEXT | SPECIAL); + ELT_TT = new nsHtml5ElementName( + nsGkAtoms::tt, nsGkAtoms::tt, NS_NewHTMLElement, NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U); + ELT_RECT = new nsHtml5ElementName( + nsGkAtoms::rect, nsGkAtoms::rect, NS_NewHTMLUnknownElement, + NS_NewSVGRectElement, nsHtml5TreeBuilder::OTHER); + ELT_RADIALGRADIENT = new nsHtml5ElementName( + nsGkAtoms::radialgradient, nsGkAtoms::radialGradient, + NS_NewHTMLUnknownElement, NS_NewSVGRadialGradientElement, + nsHtml5TreeBuilder::OTHER); + ELT_SELECT = new nsHtml5ElementName( + nsGkAtoms::select, nsGkAtoms::select, NS_NewHTMLSelectElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::SELECT | SPECIAL); + ELT_SLOT = new nsHtml5ElementName( + nsGkAtoms::slot, nsGkAtoms::slot, NS_NewHTMLSlotElement, + NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER); + ELT_SCRIPT = new nsHtml5ElementName( + nsGkAtoms::script, nsGkAtoms::script, NS_NewHTMLScriptElement, + NS_NewSVGScriptElement, nsHtml5TreeBuilder::SCRIPT | SPECIAL); + ELT_TFOOT = new nsHtml5ElementName( + nsGkAtoms::tfoot, nsGkAtoms::tfoot, NS_NewHTMLTableSectionElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | + OPTIONAL_END_TAG); + ELT_TEXT = new nsHtml5ElementName( + nsGkAtoms::text, nsGkAtoms::text, NS_NewHTMLUnknownElement, + NS_NewSVGTextElement, nsHtml5TreeBuilder::OTHER); + ELT_MENU = new nsHtml5ElementName( + nsGkAtoms::menu, nsGkAtoms::menu, NS_NewHTMLMenuElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL); + ELT_FEDROPSHADOW = new nsHtml5ElementName( + nsGkAtoms::fedropshadow, nsGkAtoms::feDropShadow, + NS_NewHTMLUnknownElement, NS_NewSVGFEDropShadowElement, + nsHtml5TreeBuilder::OTHER); + ELT_VIEW = new nsHtml5ElementName( + nsGkAtoms::view, nsGkAtoms::view, NS_NewHTMLUnknownElement, + NS_NewSVGViewElement, nsHtml5TreeBuilder::OTHER); + ELT_FECOLORMATRIX = new nsHtml5ElementName( + nsGkAtoms::fecolormatrix, nsGkAtoms::feColorMatrix, + NS_NewHTMLUnknownElement, NS_NewSVGFEColorMatrixElement, + nsHtml5TreeBuilder::OTHER); + ELT_FECONVOLVEMATRIX = new nsHtml5ElementName( + nsGkAtoms::feconvolvematrix, nsGkAtoms::feConvolveMatrix, + NS_NewHTMLUnknownElement, NS_NewSVGFEConvolveMatrixElement, + nsHtml5TreeBuilder::OTHER); + ELT_BODY = new nsHtml5ElementName( + nsGkAtoms::body, nsGkAtoms::body, NS_NewHTMLBodyElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::BODY | SPECIAL | OPTIONAL_END_TAG); + ELT_FEMORPHOLOGY = new nsHtml5ElementName( + nsGkAtoms::femorphology, nsGkAtoms::feMorphology, + NS_NewHTMLUnknownElement, NS_NewSVGFEMorphologyElement, + nsHtml5TreeBuilder::OTHER); + ELT_RUBY = new nsHtml5ElementName( + nsGkAtoms::ruby, nsGkAtoms::ruby, NS_NewHTMLElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR); + ELT_SUMMARY = new nsHtml5ElementName( + nsGkAtoms::summary, nsGkAtoms::summary, NS_NewHTMLSummaryElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder:: + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | + SPECIAL); + ELT_TBODY = new nsHtml5ElementName( + nsGkAtoms::tbody, nsGkAtoms::tbody, NS_NewHTMLTableSectionElement, + NS_NewSVGUnknownElement, + nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | + OPTIONAL_END_TAG); + ELEMENT_NAMES = new nsHtml5ElementName*[206]; + ELEMENT_NAMES[0] = ELT_MN; + ELEMENT_NAMES[1] = ELT_CITE; + ELEMENT_NAMES[2] = ELT_FRAMESET; + ELEMENT_NAMES[3] = ELT_H1; + ELEMENT_NAMES[4] = ELT_CLIPPATH; + ELEMENT_NAMES[5] = ELT_METER; + ELEMENT_NAMES[6] = ELT_RADIALGRADIENT; + ELEMENT_NAMES[7] = ELT_B; + ELEMENT_NAMES[8] = ELT_BGSOUND; + ELEMENT_NAMES[9] = ELT_SOURCE; + ELEMENT_NAMES[10] = ELT_HTML; + ELEMENT_NAMES[11] = ELT_OPTGROUP; + ELEMENT_NAMES[12] = ELT_NOFRAMES; + ELEMENT_NAMES[13] = ELT_MTEXT; + ELEMENT_NAMES[14] = ELT_VIEW; + ELEMENT_NAMES[15] = ELT_DIV; + ELEMENT_NAMES[16] = ELT_G; + ELEMENT_NAMES[17] = ELT_FEFUNCA; + ELEMENT_NAMES[18] = ELT_THEAD; + ELEMENT_NAMES[19] = ELT_FIGURE; + ELEMENT_NAMES[20] = ELT_GLYPHREF; + ELEMENT_NAMES[21] = ELT_LI; + ELEMENT_NAMES[22] = ELT_ACRONYM; + ELEMENT_NAMES[23] = ELT_TSPAN; + ELEMENT_NAMES[24] = ELT_FEFUNCR; + ELEMENT_NAMES[25] = ELT_CANVAS; + ELEMENT_NAMES[26] = ELT_BASEFONT; + ELEMENT_NAMES[27] = ELT_FEDISTANTLIGHT; + ELEMENT_NAMES[28] = ELT_OUTPUT; + ELEMENT_NAMES[29] = ELT_TFOOT; + ELEMENT_NAMES[30] = ELT_FEMORPHOLOGY; + ELEMENT_NAMES[31] = ELT_COL; + ELEMENT_NAMES[32] = ELT_MAP; + ELEMENT_NAMES[33] = ELT_SUP; + ELEMENT_NAMES[34] = ELT_P; + ELEMENT_NAMES[35] = ELT_H5; + ELEMENT_NAMES[36] = ELT_FEFUNCB; + ELEMENT_NAMES[37] = ELT_HEAD; + ELEMENT_NAMES[38] = ELT_BASE; + ELEMENT_NAMES[39] = ELT_FEIMAGE; + ELEMENT_NAMES[40] = ELT_LINE; + ELEMENT_NAMES[41] = ELT_TITLE; + ELEMENT_NAMES[42] = ELT_FESPECULARLIGHTING; + ELEMENT_NAMES[43] = ELT_PATH; + ELEMENT_NAMES[44] = ELT_MALIGNMARK; + ELEMENT_NAMES[45] = ELT_SMALL; + ELEMENT_NAMES[46] = ELT_ANIMATEMOTION; + ELEMENT_NAMES[47] = ELT_POLYGON; + ELEMENT_NAMES[48] = ELT_COLGROUP; + ELEMENT_NAMES[49] = ELT_ABBR; + ELEMENT_NAMES[50] = ELT_FEGAUSSIANBLUR; + ELEMENT_NAMES[51] = ELT_TR; + ELEMENT_NAMES[52] = ELT_DETAILS; + ELEMENT_NAMES[53] = ELT_DT; + ELEMENT_NAMES[54] = ELT_FOREIGNOBJECT; + ELEMENT_NAMES[55] = ELT_FESPOTLIGHT; + ELEMENT_NAMES[56] = ELT_INPUT; + ELEMENT_NAMES[57] = ELT_RT; + ELEMENT_NAMES[58] = ELT_TT; + ELEMENT_NAMES[59] = ELT_SLOT; + ELEMENT_NAMES[60] = ELT_MENU; + ELEMENT_NAMES[61] = ELT_FECONVOLVEMATRIX; + ELEMENT_NAMES[62] = ELT_SUMMARY; + ELEMENT_NAMES[63] = ELT_BDI; + ELEMENT_NAMES[64] = ELT_DFN; + ELEMENT_NAMES[65] = ELT_INS; + ELEMENT_NAMES[66] = ELT_PRE; + ELEMENT_NAMES[67] = ELT_SUB; + ELEMENT_NAMES[68] = ELT_USE; + ELEMENT_NAMES[69] = ELT_XMP; + ELEMENT_NAMES[70] = ELT_S; + ELEMENT_NAMES[71] = ELT_H3; + ELEMENT_NAMES[72] = ELT_AREA; + ELEMENT_NAMES[73] = ELT_META; + ELEMENT_NAMES[74] = ELT_DESC; + ELEMENT_NAMES[75] = ELT_FEBLEND; + ELEMENT_NAMES[76] = ELT_NOEMBED; + ELEMENT_NAMES[77] = ELT_ARTICLE; + ELEMENT_NAMES[78] = ELT_CODE; + ELEMENT_NAMES[79] = ELT_FETURBULENCE; + ELEMENT_NAMES[80] = ELT_FETILE; + ELEMENT_NAMES[81] = ELT_IMAGE; + ELEMENT_NAMES[82] = ELT_POLYLINE; + ELEMENT_NAMES[83] = ELT_STYLE; + ELEMENT_NAMES[84] = ELT_TEMPLATE; + ELEMENT_NAMES[85] = ELT_FEFUNCG; + ELEMENT_NAMES[86] = ELT_STRONG; + ELEMENT_NAMES[87] = ELT_MATH; + ELEMENT_NAMES[88] = ELT_SWITCH; + ELEMENT_NAMES[89] = ELT_LINK; + ELEMENT_NAMES[90] = ELT_TRACK; + ELEMENT_NAMES[91] = ELT_LABEL; + ELEMENT_NAMES[92] = ELT_ALTGLYPHITEM; + ELEMENT_NAMES[93] = ELT_FORM; + ELEMENT_NAMES[94] = ELT_CAPTION; + ELEMENT_NAMES[95] = ELT_MAIN; + ELEMENT_NAMES[96] = ELT_SPAN; + ELEMENT_NAMES[97] = ELT_MO; + ELEMENT_NAMES[98] = ELT_HGROUP; + ELEMENT_NAMES[99] = ELT_STOP; + ELEMENT_NAMES[100] = ELT_CENTER; + ELEMENT_NAMES[101] = ELT_FILTER; + ELEMENT_NAMES[102] = ELT_MARKER; + ELEMENT_NAMES[103] = ELT_NOBR; + ELEMENT_NAMES[104] = ELT_ADDRESS; + ELEMENT_NAMES[105] = ELT_DEFS; + ELEMENT_NAMES[106] = ELT_MS; + ELEMENT_NAMES[107] = ELT_PROGRESS; + ELEMENT_NAMES[108] = ELT_APPLET; + ELEMENT_NAMES[109] = ELT_DATALIST; + ELEMENT_NAMES[110] = ELT_FIELDSET; + ELEMENT_NAMES[111] = ELT_FEOFFSET; + ELEMENT_NAMES[112] = ELT_FEPOINTLIGHT; + ELEMENT_NAMES[113] = ELT_FONT; + ELEMENT_NAMES[114] = ELT_LINEARGRADIENT; + ELEMENT_NAMES[115] = ELT_NOSCRIPT; + ELEMENT_NAMES[116] = ELT_OBJECT; + ELEMENT_NAMES[117] = ELT_PLAINTEXT; + ELEMENT_NAMES[118] = ELT_RECT; + ELEMENT_NAMES[119] = ELT_SELECT; + ELEMENT_NAMES[120] = ELT_SCRIPT; + ELEMENT_NAMES[121] = ELT_TEXT; + ELEMENT_NAMES[122] = ELT_FEDROPSHADOW; + ELEMENT_NAMES[123] = ELT_FECOLORMATRIX; + ELEMENT_NAMES[124] = ELT_BODY; + ELEMENT_NAMES[125] = ELT_RUBY; + ELEMENT_NAMES[126] = ELT_TBODY; + ELEMENT_NAMES[127] = ELT_BIG; + ELEMENT_NAMES[128] = ELT_BDO; + ELEMENT_NAMES[129] = ELT_DEL; + ELEMENT_NAMES[130] = ELT_DIR; + ELEMENT_NAMES[131] = ELT_IMG; + ELEMENT_NAMES[132] = ELT_KBD; + ELEMENT_NAMES[133] = ELT_NAV; + ELEMENT_NAMES[134] = ELT_A; + ELEMENT_NAMES[135] = ELT_RTC; + ELEMENT_NAMES[136] = ELT_SVG; + ELEMENT_NAMES[137] = ELT_SET; + ELEMENT_NAMES[138] = ELT_VAR; + ELEMENT_NAMES[139] = ELT_WBR; + ELEMENT_NAMES[140] = ELT_I; + ELEMENT_NAMES[141] = ELT_Q; + ELEMENT_NAMES[142] = ELT_U; + ELEMENT_NAMES[143] = ELT_H2; + ELEMENT_NAMES[144] = ELT_H4; + ELEMENT_NAMES[145] = ELT_H6; + ELEMENT_NAMES[146] = ELT_DATA; + ELEMENT_NAMES[147] = ELT_METADATA; + ELEMENT_NAMES[148] = ELT_TEXTAREA; + ELEMENT_NAMES[149] = ELT_RB; + ELEMENT_NAMES[150] = ELT_DD; + ELEMENT_NAMES[151] = ELT_EMBED; + ELEMENT_NAMES[152] = ELT_FEFLOOD; + ELEMENT_NAMES[153] = ELT_LEGEND; + ELEMENT_NAMES[154] = ELT_TD; + ELEMENT_NAMES[155] = ELT_ASIDE; + ELEMENT_NAMES[156] = ELT_ANIMATE; + ELEMENT_NAMES[157] = ELT_BLOCKQUOTE; + ELEMENT_NAMES[158] = ELT_CIRCLE; + ELEMENT_NAMES[159] = ELT_ELLIPSE; + ELEMENT_NAMES[160] = ELT_FEMERGENODE; + ELEMENT_NAMES[161] = ELT_FEMERGE; + ELEMENT_NAMES[162] = ELT_FRAME; + ELEMENT_NAMES[163] = ELT_FECOMPOSITE; + ELEMENT_NAMES[164] = ELT_IFRAME; + ELEMENT_NAMES[165] = ELT_MARQUEE; + ELEMENT_NAMES[166] = ELT_PICTURE; + ELEMENT_NAMES[167] = ELT_STRIKE; + ELEMENT_NAMES[168] = ELT_TABLE; + ELEMENT_NAMES[169] = ELT_TIME; + ELEMENT_NAMES[170] = ELT_ALTGLYPHDEF; + ELEMENT_NAMES[171] = ELT_DIALOG; + ELEMENT_NAMES[172] = ELT_FEDIFFUSELIGHTING; + ELEMENT_NAMES[173] = ELT_LISTING; + ELEMENT_NAMES[174] = ELT_ALTGLYPH; + ELEMENT_NAMES[175] = ELT_MGLYPH; + ELEMENT_NAMES[176] = ELT_MPATH; + ELEMENT_NAMES[177] = ELT_TH; + ELEMENT_NAMES[178] = ELT_TEXTPATH; + ELEMENT_NAMES[179] = ELT_MI; + ELEMENT_NAMES[180] = ELT_MARK; + ELEMENT_NAMES[181] = ELT_MASK; + ELEMENT_NAMES[182] = ELT_DL; + ELEMENT_NAMES[183] = ELT_OL; + ELEMENT_NAMES[184] = ELT_UL; + ELEMENT_NAMES[185] = ELT_SYMBOL; + ELEMENT_NAMES[186] = ELT_ANIMATETRANSFORM; + ELEMENT_NAMES[187] = ELT_EM; + ELEMENT_NAMES[188] = ELT_PARAM; + ELEMENT_NAMES[189] = ELT_BUTTON; + ELEMENT_NAMES[190] = ELT_FIGCAPTION; + ELEMENT_NAMES[191] = ELT_KEYGEN; + ELEMENT_NAMES[192] = ELT_OPTION; + ELEMENT_NAMES[193] = ELT_PATTERN; + ELEMENT_NAMES[194] = ELT_SECTION; + ELEMENT_NAMES[195] = ELT_AUDIO; + ELEMENT_NAMES[196] = ELT_VIDEO; + ELEMENT_NAMES[197] = ELT_FEDISPLACEMENTMAP; + ELEMENT_NAMES[198] = ELT_RP; + ELEMENT_NAMES[199] = ELT_SAMP; + ELEMENT_NAMES[200] = ELT_BR; + ELEMENT_NAMES[201] = ELT_ANIMATECOLOR; + ELEMENT_NAMES[202] = ELT_HR; + ELEMENT_NAMES[203] = ELT_FECOMPONENTTRANSFER; + ELEMENT_NAMES[204] = ELT_FOOTER; + ELEMENT_NAMES[205] = ELT_HEADER; +} + +void nsHtml5ElementName::releaseStatics() { + delete ELT_ANNOTATION_XML; + delete ELT_BIG; + delete ELT_BDI; + delete ELT_BDO; + delete ELT_COL; + delete ELT_DEL; + delete ELT_DFN; + delete ELT_DIR; + delete ELT_DIV; + delete ELT_IMG; + delete ELT_INS; + delete ELT_KBD; + delete ELT_MAP; + delete ELT_NAV; + delete ELT_PRE; + delete ELT_A; + delete ELT_B; + delete ELT_RTC; + delete ELT_SUB; + delete ELT_SVG; + delete ELT_SUP; + delete ELT_SET; + delete ELT_USE; + delete ELT_VAR; + delete ELT_G; + delete ELT_WBR; + delete ELT_XMP; + delete ELT_I; + delete ELT_P; + delete ELT_Q; + delete ELT_S; + delete ELT_U; + delete ELT_H1; + delete ELT_H2; + delete ELT_H3; + delete ELT_H4; + delete ELT_H5; + delete ELT_H6; + delete ELT_AREA; + delete ELT_DATA; + delete ELT_FEFUNCA; + delete ELT_METADATA; + delete ELT_META; + delete ELT_TEXTAREA; + delete ELT_FEFUNCB; + delete ELT_RB; + delete ELT_DESC; + delete ELT_DD; + delete ELT_BGSOUND; + delete ELT_EMBED; + delete ELT_FEBLEND; + delete ELT_FEFLOOD; + delete ELT_HEAD; + delete ELT_LEGEND; + delete ELT_NOEMBED; + delete ELT_TD; + delete ELT_THEAD; + delete ELT_ASIDE; + delete ELT_ARTICLE; + delete ELT_ANIMATE; + delete ELT_BASE; + delete ELT_BLOCKQUOTE; + delete ELT_CODE; + delete ELT_CIRCLE; + delete ELT_CITE; + delete ELT_ELLIPSE; + delete ELT_FETURBULENCE; + delete ELT_FEMERGENODE; + delete ELT_FEIMAGE; + delete ELT_FEMERGE; + delete ELT_FETILE; + delete ELT_FRAME; + delete ELT_FIGURE; + delete ELT_FECOMPOSITE; + delete ELT_IMAGE; + delete ELT_IFRAME; + delete ELT_LINE; + delete ELT_MARQUEE; + delete ELT_POLYLINE; + delete ELT_PICTURE; + delete ELT_SOURCE; + delete ELT_STRIKE; + delete ELT_STYLE; + delete ELT_TABLE; + delete ELT_TITLE; + delete ELT_TIME; + delete ELT_TEMPLATE; + delete ELT_ALTGLYPHDEF; + delete ELT_GLYPHREF; + delete ELT_DIALOG; + delete ELT_FEFUNCG; + delete ELT_FEDIFFUSELIGHTING; + delete ELT_FESPECULARLIGHTING; + delete ELT_LISTING; + delete ELT_STRONG; + delete ELT_ALTGLYPH; + delete ELT_CLIPPATH; + delete ELT_MGLYPH; + delete ELT_MATH; + delete ELT_MPATH; + delete ELT_PATH; + delete ELT_TH; + delete ELT_SWITCH; + delete ELT_TEXTPATH; + delete ELT_LI; + delete ELT_MI; + delete ELT_LINK; + delete ELT_MARK; + delete ELT_MALIGNMARK; + delete ELT_MASK; + delete ELT_TRACK; + delete ELT_DL; + delete ELT_HTML; + delete ELT_OL; + delete ELT_LABEL; + delete ELT_UL; + delete ELT_SMALL; + delete ELT_SYMBOL; + delete ELT_ALTGLYPHITEM; + delete ELT_ANIMATETRANSFORM; + delete ELT_ACRONYM; + delete ELT_EM; + delete ELT_FORM; + delete ELT_PARAM; + delete ELT_ANIMATEMOTION; + delete ELT_BUTTON; + delete ELT_CAPTION; + delete ELT_FIGCAPTION; + delete ELT_MN; + delete ELT_KEYGEN; + delete ELT_MAIN; + delete ELT_OPTION; + delete ELT_POLYGON; + delete ELT_PATTERN; + delete ELT_SPAN; + delete ELT_SECTION; + delete ELT_TSPAN; + delete ELT_AUDIO; + delete ELT_MO; + delete ELT_VIDEO; + delete ELT_COLGROUP; + delete ELT_FEDISPLACEMENTMAP; + delete ELT_HGROUP; + delete ELT_RP; + delete ELT_OPTGROUP; + delete ELT_SAMP; + delete ELT_STOP; + delete ELT_BR; + delete ELT_ABBR; + delete ELT_ANIMATECOLOR; + delete ELT_CENTER; + delete ELT_HR; + delete ELT_FEFUNCR; + delete ELT_FECOMPONENTTRANSFER; + delete ELT_FILTER; + delete ELT_FOOTER; + delete ELT_FEGAUSSIANBLUR; + delete ELT_HEADER; + delete ELT_MARKER; + delete ELT_METER; + delete ELT_NOBR; + delete ELT_TR; + delete ELT_ADDRESS; + delete ELT_CANVAS; + delete ELT_DEFS; + delete ELT_DETAILS; + delete ELT_MS; + delete ELT_NOFRAMES; + delete ELT_PROGRESS; + delete ELT_DT; + delete ELT_APPLET; + delete ELT_BASEFONT; + delete ELT_DATALIST; + delete ELT_FOREIGNOBJECT; + delete ELT_FIELDSET; + delete ELT_FRAMESET; + delete ELT_FEOFFSET; + delete ELT_FESPOTLIGHT; + delete ELT_FEPOINTLIGHT; + delete ELT_FEDISTANTLIGHT; + delete ELT_FONT; + delete ELT_INPUT; + delete ELT_LINEARGRADIENT; + delete ELT_MTEXT; + delete ELT_NOSCRIPT; + delete ELT_RT; + delete ELT_OBJECT; + delete ELT_OUTPUT; + delete ELT_PLAINTEXT; + delete ELT_TT; + delete ELT_RECT; + delete ELT_RADIALGRADIENT; + delete ELT_SELECT; + delete ELT_SLOT; + delete ELT_SCRIPT; + delete ELT_TFOOT; + delete ELT_TEXT; + delete ELT_MENU; + delete ELT_FEDROPSHADOW; + delete ELT_VIEW; + delete ELT_FECOLORMATRIX; + delete ELT_FECONVOLVEMATRIX; + delete ELT_BODY; + delete ELT_FEMORPHOLOGY; + delete ELT_RUBY; + delete ELT_SUMMARY; + delete ELT_TBODY; + delete[] ELEMENT_NAMES; +} diff --git a/parser/html/nsHtml5ElementName.h b/parser/html/nsHtml5ElementName.h new file mode 100644 index 0000000000..fc064a2655 --- /dev/null +++ b/parser/html/nsHtml5ElementName.h @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2008-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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit ElementName.java instead and regenerate. + */ + +#ifndef nsHtml5ElementName_h +#define nsHtml5ElementName_h + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +class nsHtml5StreamParser; + +class nsHtml5AttributeName; +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5UTF16Buffer; +class nsHtml5StateSnapshot; +class nsHtml5Portability; + +class nsHtml5ElementName { + public: + static const int32_t GROUP_MASK = 127; + + static const int32_t NOT_INTERNED = (1 << 30); + + static const int32_t SPECIAL = (1 << 29); + + static const int32_t FOSTER_PARENTING = (1 << 28); + + static const int32_t SCOPING = (1 << 27); + + static const int32_t SCOPING_AS_SVG = (1 << 26); + + static const int32_t SCOPING_AS_MATHML = (1 << 25); + + static const int32_t HTML_INTEGRATION_POINT = (1 << 24); + + static const int32_t OPTIONAL_END_TAG = (1 << 23); + + private: + RefPtr<nsAtom> name; + RefPtr<nsAtom> camelCaseName; + mozilla::dom::HTMLContentCreatorFunction htmlCreator; + mozilla::dom::SVGContentCreatorFunction svgCreator; + + public: + int32_t flags; + inline nsAtom* getName() { return name; } + + inline nsAtom* getCamelCaseName() { return camelCaseName; } + + inline mozilla::dom::HTMLContentCreatorFunction getHtmlCreator() { + return htmlCreator; + } + + inline mozilla::dom::SVGContentCreatorFunction getSvgCreator() { + return svgCreator; + } + + inline int32_t getFlags() { return flags; } + + inline int32_t getGroup() { return flags & nsHtml5ElementName::GROUP_MASK; } + + inline bool isInterned() { + return !(flags & nsHtml5ElementName::NOT_INTERNED); + } + + inline static int32_t levelOrderBinarySearch(jArray<int32_t, int32_t> data, + int32_t key) { + int32_t n = data.length; + int32_t i = 0; + while (i < n) { + int32_t val = data[i]; + if (val < key) { + i = 2 * i + 2; + } else if (val > key) { + i = 2 * i + 1; + } else { + return i; + } + } + return -1; + } + + inline static nsHtml5ElementName* elementNameByBuffer( + char16_t* buf, int32_t length, nsHtml5AtomTable* interner) { + uint32_t hash = nsHtml5ElementName::bufToHash(buf, length); + jArray<int32_t, int32_t> hashes; + hashes = nsHtml5ElementName::ELEMENT_HASHES; + int32_t index = levelOrderBinarySearch(hashes, hash); + if (index < 0) { + return nullptr; + } else { + nsHtml5ElementName* elementName = + nsHtml5ElementName::ELEMENT_NAMES[index]; + nsAtom* name = elementName->name; + if (!nsHtml5Portability::localEqualsBuffer(name, buf, length)) { + return nullptr; + } + return elementName; + } + } + + private: + inline static uint32_t bufToHash(char16_t* buf, int32_t length) { + uint32_t len = length; + uint32_t first = buf[0]; + first <<= 19; + uint32_t second = 1 << 23; + uint32_t third = 0; + uint32_t fourth = 0; + uint32_t fifth = 0; + if (length >= 4) { + second = buf[length - 4]; + second <<= 4; + third = buf[length - 3]; + third <<= 9; + fourth = buf[length - 2]; + fourth <<= 14; + fifth = buf[length - 1]; + fifth <<= 24; + } else if (length == 3) { + second = buf[1]; + second <<= 4; + third = buf[2]; + third <<= 9; + } else if (length == 2) { + second = buf[1]; + second <<= 24; + } + return len + first + second + third + fourth + fifth; + } + + nsHtml5ElementName(nsAtom* name, nsAtom* camelCaseName, + mozilla::dom::HTMLContentCreatorFunction htmlCreator, + mozilla::dom::SVGContentCreatorFunction svgCreator, + int32_t flags); + + public: + nsHtml5ElementName(); + ~nsHtml5ElementName(); + inline void setNameForNonInterned(nsAtom* name, bool custom) { + this->name = name; + this->camelCaseName = name; + if (custom) { + this->htmlCreator = NS_NewCustomElement; + } else { + this->htmlCreator = NS_NewHTMLUnknownElement; + } + MOZ_ASSERT(this->flags == nsHtml5ElementName::NOT_INTERNED); + } + + inline bool isCustom() { return this->htmlCreator == NS_NewCustomElement; } + + static nsHtml5ElementName* ELT_ANNOTATION_XML; + static nsHtml5ElementName* ELT_BIG; + static nsHtml5ElementName* ELT_BDI; + static nsHtml5ElementName* ELT_BDO; + static nsHtml5ElementName* ELT_COL; + static nsHtml5ElementName* ELT_DEL; + static nsHtml5ElementName* ELT_DFN; + static nsHtml5ElementName* ELT_DIR; + static nsHtml5ElementName* ELT_DIV; + static nsHtml5ElementName* ELT_IMG; + static nsHtml5ElementName* ELT_INS; + static nsHtml5ElementName* ELT_KBD; + static nsHtml5ElementName* ELT_MAP; + static nsHtml5ElementName* ELT_NAV; + static nsHtml5ElementName* ELT_PRE; + static nsHtml5ElementName* ELT_A; + static nsHtml5ElementName* ELT_B; + static nsHtml5ElementName* ELT_RTC; + static nsHtml5ElementName* ELT_SUB; + static nsHtml5ElementName* ELT_SVG; + static nsHtml5ElementName* ELT_SUP; + static nsHtml5ElementName* ELT_SET; + static nsHtml5ElementName* ELT_USE; + static nsHtml5ElementName* ELT_VAR; + static nsHtml5ElementName* ELT_G; + static nsHtml5ElementName* ELT_WBR; + static nsHtml5ElementName* ELT_XMP; + static nsHtml5ElementName* ELT_I; + static nsHtml5ElementName* ELT_P; + static nsHtml5ElementName* ELT_Q; + static nsHtml5ElementName* ELT_S; + static nsHtml5ElementName* ELT_U; + static nsHtml5ElementName* ELT_H1; + static nsHtml5ElementName* ELT_H2; + static nsHtml5ElementName* ELT_H3; + static nsHtml5ElementName* ELT_H4; + static nsHtml5ElementName* ELT_H5; + static nsHtml5ElementName* ELT_H6; + static nsHtml5ElementName* ELT_AREA; + static nsHtml5ElementName* ELT_DATA; + static nsHtml5ElementName* ELT_FEFUNCA; + static nsHtml5ElementName* ELT_METADATA; + static nsHtml5ElementName* ELT_META; + static nsHtml5ElementName* ELT_TEXTAREA; + static nsHtml5ElementName* ELT_FEFUNCB; + static nsHtml5ElementName* ELT_RB; + static nsHtml5ElementName* ELT_DESC; + static nsHtml5ElementName* ELT_DD; + static nsHtml5ElementName* ELT_BGSOUND; + static nsHtml5ElementName* ELT_EMBED; + static nsHtml5ElementName* ELT_FEBLEND; + static nsHtml5ElementName* ELT_FEFLOOD; + static nsHtml5ElementName* ELT_HEAD; + static nsHtml5ElementName* ELT_LEGEND; + static nsHtml5ElementName* ELT_NOEMBED; + static nsHtml5ElementName* ELT_TD; + static nsHtml5ElementName* ELT_THEAD; + static nsHtml5ElementName* ELT_ASIDE; + static nsHtml5ElementName* ELT_ARTICLE; + static nsHtml5ElementName* ELT_ANIMATE; + static nsHtml5ElementName* ELT_BASE; + static nsHtml5ElementName* ELT_BLOCKQUOTE; + static nsHtml5ElementName* ELT_CODE; + static nsHtml5ElementName* ELT_CIRCLE; + static nsHtml5ElementName* ELT_CITE; + static nsHtml5ElementName* ELT_ELLIPSE; + static nsHtml5ElementName* ELT_FETURBULENCE; + static nsHtml5ElementName* ELT_FEMERGENODE; + static nsHtml5ElementName* ELT_FEIMAGE; + static nsHtml5ElementName* ELT_FEMERGE; + static nsHtml5ElementName* ELT_FETILE; + static nsHtml5ElementName* ELT_FRAME; + static nsHtml5ElementName* ELT_FIGURE; + static nsHtml5ElementName* ELT_FECOMPOSITE; + static nsHtml5ElementName* ELT_IMAGE; + static nsHtml5ElementName* ELT_IFRAME; + static nsHtml5ElementName* ELT_LINE; + static nsHtml5ElementName* ELT_MARQUEE; + static nsHtml5ElementName* ELT_POLYLINE; + static nsHtml5ElementName* ELT_PICTURE; + static nsHtml5ElementName* ELT_SOURCE; + static nsHtml5ElementName* ELT_STRIKE; + static nsHtml5ElementName* ELT_STYLE; + static nsHtml5ElementName* ELT_TABLE; + static nsHtml5ElementName* ELT_TITLE; + static nsHtml5ElementName* ELT_TIME; + static nsHtml5ElementName* ELT_TEMPLATE; + static nsHtml5ElementName* ELT_ALTGLYPHDEF; + static nsHtml5ElementName* ELT_GLYPHREF; + static nsHtml5ElementName* ELT_DIALOG; + static nsHtml5ElementName* ELT_FEFUNCG; + static nsHtml5ElementName* ELT_FEDIFFUSELIGHTING; + static nsHtml5ElementName* ELT_FESPECULARLIGHTING; + static nsHtml5ElementName* ELT_LISTING; + static nsHtml5ElementName* ELT_STRONG; + static nsHtml5ElementName* ELT_ALTGLYPH; + static nsHtml5ElementName* ELT_CLIPPATH; + static nsHtml5ElementName* ELT_MGLYPH; + static nsHtml5ElementName* ELT_MATH; + static nsHtml5ElementName* ELT_MPATH; + static nsHtml5ElementName* ELT_PATH; + static nsHtml5ElementName* ELT_TH; + static nsHtml5ElementName* ELT_SWITCH; + static nsHtml5ElementName* ELT_TEXTPATH; + static nsHtml5ElementName* ELT_LI; + static nsHtml5ElementName* ELT_MI; + static nsHtml5ElementName* ELT_LINK; + static nsHtml5ElementName* ELT_MARK; + static nsHtml5ElementName* ELT_MALIGNMARK; + static nsHtml5ElementName* ELT_MASK; + static nsHtml5ElementName* ELT_TRACK; + static nsHtml5ElementName* ELT_DL; + static nsHtml5ElementName* ELT_HTML; + static nsHtml5ElementName* ELT_OL; + static nsHtml5ElementName* ELT_LABEL; + static nsHtml5ElementName* ELT_UL; + static nsHtml5ElementName* ELT_SMALL; + static nsHtml5ElementName* ELT_SYMBOL; + static nsHtml5ElementName* ELT_ALTGLYPHITEM; + static nsHtml5ElementName* ELT_ANIMATETRANSFORM; + static nsHtml5ElementName* ELT_ACRONYM; + static nsHtml5ElementName* ELT_EM; + static nsHtml5ElementName* ELT_FORM; + static nsHtml5ElementName* ELT_PARAM; + static nsHtml5ElementName* ELT_ANIMATEMOTION; + static nsHtml5ElementName* ELT_BUTTON; + static nsHtml5ElementName* ELT_CAPTION; + static nsHtml5ElementName* ELT_FIGCAPTION; + static nsHtml5ElementName* ELT_MN; + static nsHtml5ElementName* ELT_KEYGEN; + static nsHtml5ElementName* ELT_MAIN; + static nsHtml5ElementName* ELT_OPTION; + static nsHtml5ElementName* ELT_POLYGON; + static nsHtml5ElementName* ELT_PATTERN; + static nsHtml5ElementName* ELT_SPAN; + static nsHtml5ElementName* ELT_SECTION; + static nsHtml5ElementName* ELT_TSPAN; + static nsHtml5ElementName* ELT_AUDIO; + static nsHtml5ElementName* ELT_MO; + static nsHtml5ElementName* ELT_VIDEO; + static nsHtml5ElementName* ELT_COLGROUP; + static nsHtml5ElementName* ELT_FEDISPLACEMENTMAP; + static nsHtml5ElementName* ELT_HGROUP; + static nsHtml5ElementName* ELT_RP; + static nsHtml5ElementName* ELT_OPTGROUP; + static nsHtml5ElementName* ELT_SAMP; + static nsHtml5ElementName* ELT_STOP; + static nsHtml5ElementName* ELT_BR; + static nsHtml5ElementName* ELT_ABBR; + static nsHtml5ElementName* ELT_ANIMATECOLOR; + static nsHtml5ElementName* ELT_CENTER; + static nsHtml5ElementName* ELT_HR; + static nsHtml5ElementName* ELT_FEFUNCR; + static nsHtml5ElementName* ELT_FECOMPONENTTRANSFER; + static nsHtml5ElementName* ELT_FILTER; + static nsHtml5ElementName* ELT_FOOTER; + static nsHtml5ElementName* ELT_FEGAUSSIANBLUR; + static nsHtml5ElementName* ELT_HEADER; + static nsHtml5ElementName* ELT_MARKER; + static nsHtml5ElementName* ELT_METER; + static nsHtml5ElementName* ELT_NOBR; + static nsHtml5ElementName* ELT_TR; + static nsHtml5ElementName* ELT_ADDRESS; + static nsHtml5ElementName* ELT_CANVAS; + static nsHtml5ElementName* ELT_DEFS; + static nsHtml5ElementName* ELT_DETAILS; + static nsHtml5ElementName* ELT_MS; + static nsHtml5ElementName* ELT_NOFRAMES; + static nsHtml5ElementName* ELT_PROGRESS; + static nsHtml5ElementName* ELT_DT; + static nsHtml5ElementName* ELT_APPLET; + static nsHtml5ElementName* ELT_BASEFONT; + static nsHtml5ElementName* ELT_DATALIST; + static nsHtml5ElementName* ELT_FOREIGNOBJECT; + static nsHtml5ElementName* ELT_FIELDSET; + static nsHtml5ElementName* ELT_FRAMESET; + static nsHtml5ElementName* ELT_FEOFFSET; + static nsHtml5ElementName* ELT_FESPOTLIGHT; + static nsHtml5ElementName* ELT_FEPOINTLIGHT; + static nsHtml5ElementName* ELT_FEDISTANTLIGHT; + static nsHtml5ElementName* ELT_FONT; + static nsHtml5ElementName* ELT_INPUT; + static nsHtml5ElementName* ELT_LINEARGRADIENT; + static nsHtml5ElementName* ELT_MTEXT; + static nsHtml5ElementName* ELT_NOSCRIPT; + static nsHtml5ElementName* ELT_RT; + static nsHtml5ElementName* ELT_OBJECT; + static nsHtml5ElementName* ELT_OUTPUT; + static nsHtml5ElementName* ELT_PLAINTEXT; + static nsHtml5ElementName* ELT_TT; + static nsHtml5ElementName* ELT_RECT; + static nsHtml5ElementName* ELT_RADIALGRADIENT; + static nsHtml5ElementName* ELT_SELECT; + static nsHtml5ElementName* ELT_SLOT; + static nsHtml5ElementName* ELT_SCRIPT; + static nsHtml5ElementName* ELT_TFOOT; + static nsHtml5ElementName* ELT_TEXT; + static nsHtml5ElementName* ELT_MENU; + static nsHtml5ElementName* ELT_FEDROPSHADOW; + static nsHtml5ElementName* ELT_VIEW; + static nsHtml5ElementName* ELT_FECOLORMATRIX; + static nsHtml5ElementName* ELT_FECONVOLVEMATRIX; + static nsHtml5ElementName* ELT_BODY; + static nsHtml5ElementName* ELT_FEMORPHOLOGY; + static nsHtml5ElementName* ELT_RUBY; + static nsHtml5ElementName* ELT_SUMMARY; + static nsHtml5ElementName* ELT_TBODY; + + private: + static nsHtml5ElementName** ELEMENT_NAMES; + static staticJArray<int32_t, int32_t> ELEMENT_HASHES; + + public: + static void initializeStatics(); + static void releaseStatics(); +}; + +#endif diff --git a/parser/html/nsHtml5Highlighter.cpp b/parser/html/nsHtml5Highlighter.cpp new file mode 100644 index 0000000000..45c84b743a --- /dev/null +++ b/parser/html/nsHtml5Highlighter.cpp @@ -0,0 +1,790 @@ +/* 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/. */ + +#include "nsHtml5Highlighter.h" +#include "ErrorList.h" +#include "nsDebug.h" +#include "nsHtml5AttributeName.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5ViewSourceUtils.h" +#include "nsString.h" +#include "nsThreadUtils.h" + +#include "mozilla/Attributes.h" +#include "mozilla/Preferences.h" + +using namespace mozilla; + +// The old code had a limit of 16 tokens. 1300 is a number picked my measuring +// the size of 16 tokens on cnn.com. +#define NS_HTML5_HIGHLIGHTER_PRE_BREAK_THRESHOLD 1300 + +char16_t nsHtml5Highlighter::sComment[] = {'c', 'o', 'm', 'm', + 'e', 'n', 't', 0}; + +char16_t nsHtml5Highlighter::sCdata[] = {'c', 'd', 'a', 't', 'a', 0}; + +char16_t nsHtml5Highlighter::sEntity[] = {'e', 'n', 't', 'i', 't', 'y', 0}; + +char16_t nsHtml5Highlighter::sEndTag[] = {'e', 'n', 'd', '-', 't', 'a', 'g', 0}; + +char16_t nsHtml5Highlighter::sStartTag[] = {'s', 't', 'a', 'r', 't', + '-', 't', 'a', 'g', 0}; + +char16_t nsHtml5Highlighter::sAttributeName[] = { + 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', '-', 'n', 'a', 'm', 'e', 0}; + +char16_t nsHtml5Highlighter::sAttributeValue[] = {'a', 't', 't', 'r', 'i', 'b', + 'u', 't', 'e', '-', 'v', 'a', + 'l', 'u', 'e', 0}; + +char16_t nsHtml5Highlighter::sDoctype[] = {'d', 'o', 'c', 't', + 'y', 'p', 'e', 0}; + +char16_t nsHtml5Highlighter::sPi[] = {'p', 'i', 0}; + +nsHtml5Highlighter::nsHtml5Highlighter(nsAHtml5TreeOpSink* aOpSink) + : mState(nsHtml5Tokenizer::DATA), + mCStart(INT32_MAX), + mPos(0), + mLineNumber(1), + mInlinesOpen(0), + mInCharacters(false), + mBuffer(nullptr), + mOpSink(aOpSink), + mCurrentRun(nullptr), + mAmpersand(nullptr), + mSlash(nullptr), + mHandles( + MakeUnique<nsIContent*[]>(NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH)), + mHandlesUsed(0), + mSeenBase(false) { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); +} + +nsHtml5Highlighter::~nsHtml5Highlighter() { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); +} + +void nsHtml5Highlighter::SetOpSink(nsAHtml5TreeOpSink* aOpSink) { + mOpSink = aOpSink; +} + +void nsHtml5Highlighter::Rewind() { + mState = 0; + mCStart = INT32_MAX; + mPos = 0; + mLineNumber = 1; + mInlinesOpen = 0; + mInCharacters = false; + mBuffer = nullptr; + mOpQueue.Clear(); + mCurrentRun = nullptr; + mAmpersand = nullptr; + mSlash = nullptr; + // Pop until we have three elements on the stack: + // html, body, and pre. + while (mStack.Length() > 3) { + Pop(); + } + mSeenBase = false; +} + +void nsHtml5Highlighter::Start(const nsAutoString& aTitle) { + // Doctype + opAppendDoctypeToDocument operation(nsGkAtoms::html, u""_ns, u""_ns); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); + + mOpQueue.AppendElement()->Init(mozilla::AsVariant(STANDARDS_MODE)); + + // <html> uses NS_NewHTMLSharedElement creator + nsIContent** root = + CreateElement(nsGkAtoms::html, nullptr, nullptr, NS_NewHTMLSharedElement); + opAppendToDocument appendOp(root); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(appendOp)); + mStack.AppendElement(root); + + // <head> uses NS_NewHTMLSharedElement creator + Push(nsGkAtoms::head, nullptr, NS_NewHTMLSharedElement); + + Push(nsGkAtoms::meta, nsHtml5ViewSourceUtils::NewMetaViewportAttributes(), + NS_NewHTMLMetaElement); + Pop(); // meta + + Push(nsGkAtoms::title, nullptr, NS_NewHTMLTitleElement); + // XUL will add the "Source of: " prefix. + uint32_t length = aTitle.Length(); + if (length > INT32_MAX) { + length = INT32_MAX; + } + AppendCharacters(aTitle.BeginReading(), 0, (int32_t)length); + Pop(); // title + + Push(nsGkAtoms::link, nsHtml5ViewSourceUtils::NewLinkAttributes(), + NS_NewHTMLLinkElement); + + opUpdateStyleSheet updateOp(CurrentNode()); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(updateOp)); + + Pop(); // link + + Pop(); // head + + Push(nsGkAtoms::body, nsHtml5ViewSourceUtils::NewBodyAttributes(), + NS_NewHTMLBodyElement); + + nsHtml5HtmlAttributes* preAttrs = new nsHtml5HtmlAttributes(0); + nsHtml5String preId = nsHtml5Portability::newStringFromLiteral("line1"); + preAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, preId, -1); + Push(nsGkAtoms::pre, preAttrs, NS_NewHTMLPreElement); + + // Don't call StartCharacters here in order to be able to put it in + // a speculation. + + mOpQueue.AppendElement()->Init(mozilla::AsVariant(opStartLayout())); +} + +void nsHtml5Highlighter::UpdateCharsetSource(nsCharsetSource aCharsetSource) { + opUpdateCharsetSource operation(aCharsetSource); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); +} + +int32_t nsHtml5Highlighter::Transition(int32_t aState, bool aReconsume, + int32_t aPos) { + mPos = aPos; + switch (mState) { + case nsHtml5Tokenizer::SCRIPT_DATA: + case nsHtml5Tokenizer::RAWTEXT: + case nsHtml5Tokenizer::RCDATA: + case nsHtml5Tokenizer::DATA: + // We can transition on < and on &. Either way, we don't yet know the + // role of the token, so open a span without class. + if (aState == nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE) { + StartSpan(); + // Start another span for highlighting the ampersand + StartSpan(); + mAmpersand = CurrentNode(); + } else { + EndCharactersAndStartMarkupRun(); + } + break; + case nsHtml5Tokenizer::TAG_OPEN: + switch (aState) { + case nsHtml5Tokenizer::TAG_NAME: + StartSpan(sStartTag); + break; + case nsHtml5Tokenizer::DATA: + FinishTag(); // DATA + break; + case nsHtml5Tokenizer::PROCESSING_INSTRUCTION: + AddClass(sPi); + break; + } + break; + case nsHtml5Tokenizer::TAG_NAME: + switch (aState) { + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME: + EndSpanOrA(); // nsHtml5Tokenizer::TAG_NAME + break; + case nsHtml5Tokenizer::SELF_CLOSING_START_TAG: + EndSpanOrA(); // nsHtml5Tokenizer::TAG_NAME + StartSpan(); // for highlighting the slash + mSlash = CurrentNode(); + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME: + switch (aState) { + case nsHtml5Tokenizer::ATTRIBUTE_NAME: + StartSpan(sAttributeName); + break; + case nsHtml5Tokenizer::SELF_CLOSING_START_TAG: + StartSpan(); // for highlighting the slash + mSlash = CurrentNode(); + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::ATTRIBUTE_NAME: + switch (aState) { + case nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME: + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE: + EndSpanOrA(); // nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME + break; + case nsHtml5Tokenizer::SELF_CLOSING_START_TAG: + EndSpanOrA(); // nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME + StartSpan(); // for highlighting the slash + mSlash = CurrentNode(); + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE: + switch (aState) { + case nsHtml5Tokenizer::ATTRIBUTE_VALUE_DOUBLE_QUOTED: + case nsHtml5Tokenizer::ATTRIBUTE_VALUE_SINGLE_QUOTED: + FlushCurrent(); + StartA(); + break; + case nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED: + StartA(); + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::ATTRIBUTE_VALUE_DOUBLE_QUOTED: + case nsHtml5Tokenizer::ATTRIBUTE_VALUE_SINGLE_QUOTED: + switch (aState) { + case nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED: + EndSpanOrA(); + break; + case nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE: + StartSpan(); + StartSpan(); // for ampersand itself + mAmpersand = CurrentNode(); + break; + default: + MOZ_ASSERT_UNREACHABLE("Impossible transition."); + break; + } + break; + case nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED: + switch (aState) { + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME: + break; + case nsHtml5Tokenizer::SELF_CLOSING_START_TAG: + StartSpan(); // for highlighting the slash + mSlash = CurrentNode(); + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::SELF_CLOSING_START_TAG: + EndSpanOrA(); // end the slash highlight + switch (aState) { + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME: + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED: + switch (aState) { + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME: + EndSpanOrA(); + break; + case nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE: + StartSpan(); + StartSpan(); // for ampersand itself + mAmpersand = CurrentNode(); + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME: + switch (aState) { + case nsHtml5Tokenizer::SELF_CLOSING_START_TAG: + StartSpan(); // for highlighting the slash + mSlash = CurrentNode(); + break; + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE: + break; + case nsHtml5Tokenizer::ATTRIBUTE_NAME: + StartSpan(sAttributeName); + break; + default: + FinishTag(); + break; + } + break; + // most comment states are omitted, because they don't matter to + // highlighting + case nsHtml5Tokenizer::COMMENT_START: + case nsHtml5Tokenizer::COMMENT_END: + case nsHtml5Tokenizer::COMMENT_END_BANG: + case nsHtml5Tokenizer::COMMENT_START_DASH: + case nsHtml5Tokenizer::BOGUS_COMMENT: + case nsHtml5Tokenizer::BOGUS_COMMENT_HYPHEN: + case nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG_DASH_DASH: + if (aState == nsHtml5Tokenizer::DATA) { + AddClass(sComment); + FinishTag(); + } + break; + // most cdata states are omitted, because they don't matter to + // highlighting + case nsHtml5Tokenizer::CDATA_RSQB_RSQB: + if (aState == nsHtml5Tokenizer::DATA) { + AddClass(sCdata); + FinishTag(); + } + break; + case nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE: + EndSpanOrA(); // the span for the ampersand + switch (aState) { + case nsHtml5Tokenizer::CONSUME_NCR: + case nsHtml5Tokenizer::CHARACTER_REFERENCE_HILO_LOOKUP: + break; + default: + // not actually a character reference + EndSpanOrA(); + break; + } + break; + case nsHtml5Tokenizer::CHARACTER_REFERENCE_HILO_LOOKUP: + if (aState == nsHtml5Tokenizer::CHARACTER_REFERENCE_TAIL) { + break; + } + // not actually a character reference + EndSpanOrA(); + break; + case nsHtml5Tokenizer::CHARACTER_REFERENCE_TAIL: + if (!aReconsume) { + FlushCurrent(); + } + EndSpanOrA(); + break; + case nsHtml5Tokenizer::DECIMAL_NRC_LOOP: + case nsHtml5Tokenizer::HEX_NCR_LOOP: + switch (aState) { + case nsHtml5Tokenizer::HANDLE_NCR_VALUE: + AddClass(sEntity); + FlushCurrent(); + break; + case nsHtml5Tokenizer::HANDLE_NCR_VALUE_RECONSUME: + AddClass(sEntity); + break; + } + EndSpanOrA(); + break; + case nsHtml5Tokenizer::CLOSE_TAG_OPEN: + switch (aState) { + case nsHtml5Tokenizer::DATA: + FinishTag(); + break; + case nsHtml5Tokenizer::TAG_NAME: + StartSpan(sEndTag); + break; + } + break; + case nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN: + if (aState == nsHtml5Tokenizer::NON_DATA_END_TAG_NAME) { + FlushCurrent(); + StartSpan(); // don't know if it is "end-tag" yet :-( + break; + } + EndSpanOrA(); + StartCharacters(); + break; + case nsHtml5Tokenizer::NON_DATA_END_TAG_NAME: + switch (aState) { + case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME: + AddClass(sEndTag); + EndSpanOrA(); + break; + case nsHtml5Tokenizer::SELF_CLOSING_START_TAG: + AddClass(sEndTag); + EndSpanOrA(); + StartSpan(); // for highlighting the slash + mSlash = CurrentNode(); + break; + case nsHtml5Tokenizer::DATA: // yes, as a result of emitting the token + AddClass(sEndTag); + FinishTag(); + break; + default: + FinishTag(); + break; + } + break; + case nsHtml5Tokenizer::SCRIPT_DATA_LESS_THAN_SIGN: + case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: + if (aState == nsHtml5Tokenizer::NON_DATA_END_TAG_NAME) { + FlushCurrent(); + StartSpan(); // don't know if it is "end-tag" yet :-( + break; + } + FinishTag(); + break; + case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH: + case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED: + case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH: + if (aState == nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN) { + EndCharactersAndStartMarkupRun(); + } + break; + // Lots of double escape states omitted, because they don't highlight. + // Likewise, only doctype states that can emit the doctype are of + // interest. Otherwise, the transition out of bogus comment deals. + case nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME: + case nsHtml5Tokenizer::DOCTYPE_NAME: + case nsHtml5Tokenizer::AFTER_DOCTYPE_NAME: + case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_KEYWORD: + case nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: + case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: + case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER: + case nsHtml5Tokenizer::BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: + case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: + case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER: + case nsHtml5Tokenizer::BOGUS_DOCTYPE: + case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_KEYWORD: + case nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: + case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: + if (aState == nsHtml5Tokenizer::DATA) { + AddClass(sDoctype); + FinishTag(); + } + break; + case nsHtml5Tokenizer::PROCESSING_INSTRUCTION_QUESTION_MARK: + if (aState == nsHtml5Tokenizer::DATA) { + FinishTag(); + } + break; + default: + break; + } + mState = aState; + return aState; +} + +[[nodiscard]] bool nsHtml5Highlighter::End() { + switch (mState) { + case nsHtml5Tokenizer::COMMENT_END: + case nsHtml5Tokenizer::COMMENT_END_BANG: + case nsHtml5Tokenizer::COMMENT_START_DASH: + case nsHtml5Tokenizer::BOGUS_COMMENT: + case nsHtml5Tokenizer::BOGUS_COMMENT_HYPHEN: + AddClass(sComment); + break; + case nsHtml5Tokenizer::CDATA_RSQB_RSQB: + AddClass(sCdata); + break; + case nsHtml5Tokenizer::DECIMAL_NRC_LOOP: + case nsHtml5Tokenizer::HEX_NCR_LOOP: + // XXX need tokenizer help here + break; + case nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME: + case nsHtml5Tokenizer::DOCTYPE_NAME: + case nsHtml5Tokenizer::AFTER_DOCTYPE_NAME: + case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_KEYWORD: + case nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: + case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: + case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER: + case nsHtml5Tokenizer::BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: + case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: + case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER: + case nsHtml5Tokenizer::BOGUS_DOCTYPE: + case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_KEYWORD: + case nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: + case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: + AddClass(sDoctype); + break; + default: + break; + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + treeOp->Init(mozilla::AsVariant(opStreamEnded())); + return FlushOps().isOk(); +} + +void nsHtml5Highlighter::SetBuffer(nsHtml5UTF16Buffer* aBuffer) { + MOZ_ASSERT(!mBuffer, "Old buffer still here!"); + mBuffer = aBuffer; + mCStart = aBuffer->getStart(); +} + +void nsHtml5Highlighter::DropBuffer(int32_t aPos) { + MOZ_ASSERT(mBuffer, "No buffer to drop!"); + mPos = aPos; + FlushChars(); + mBuffer = nullptr; +} + +void nsHtml5Highlighter::StartSpan() { + FlushChars(); + Push(nsGkAtoms::span, nullptr, NS_NewHTMLSpanElement); + ++mInlinesOpen; +} + +void nsHtml5Highlighter::StartSpan(const char16_t* aClass) { + StartSpan(); + AddClass(aClass); +} + +void nsHtml5Highlighter::EndSpanOrA() { + FlushChars(); + Pop(); + --mInlinesOpen; +} + +void nsHtml5Highlighter::StartCharacters() { + MOZ_ASSERT(!mInCharacters, "Already in characters!"); + FlushChars(); + Push(nsGkAtoms::span, nullptr, NS_NewHTMLSpanElement); + mCurrentRun = CurrentNode(); + mInCharacters = true; +} + +void nsHtml5Highlighter::EndCharactersAndStartMarkupRun() { + MOZ_ASSERT(mInCharacters, "Not in characters!"); + FlushChars(); + Pop(); + mInCharacters = false; + // Now start markup run + StartSpan(); + mCurrentRun = CurrentNode(); +} + +void nsHtml5Highlighter::StartA() { + FlushChars(); + Push(nsGkAtoms::a, nullptr, NS_NewHTMLAnchorElement); + AddClass(sAttributeValue); + ++mInlinesOpen; +} + +void nsHtml5Highlighter::FinishTag() { + while (mInlinesOpen > 1) { + EndSpanOrA(); + } + FlushCurrent(); // > + EndSpanOrA(); // DATA + NS_ASSERTION(!mInlinesOpen, "mInlinesOpen got out of sync!"); + StartCharacters(); +} + +void nsHtml5Highlighter::FlushChars() { + if (mCStart < mPos) { + char16_t* buf = mBuffer->getBuffer(); + int32_t i = mCStart; + while (i < mPos) { + char16_t c = buf[i]; + switch (c) { + case '\r': + // The input this code sees has been normalized so that there are + // CR breaks and LF breaks but no CRLF breaks. Overwrite CR with LF + // to show consistent LF line breaks to layout. It is OK to mutate + // the input data, because there are no reparses in the View Source + // case, so we won't need the original data in the buffer anymore. + buf[i] = '\n'; + [[fallthrough]]; + case '\n': { + ++i; + if (mCStart < i) { + int32_t len = i - mCStart; + AppendCharacters(buf, mCStart, len); + mCStart = i; + } + ++mLineNumber; + Push(nsGkAtoms::span, nullptr, NS_NewHTMLSpanElement); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + opAddLineNumberId operation(CurrentNode(), mLineNumber); + treeOp->Init(mozilla::AsVariant(operation)); + Pop(); + break; + } + default: + ++i; + break; + } + } + if (mCStart < mPos) { + int32_t len = mPos - mCStart; + AppendCharacters(buf, mCStart, len); + mCStart = mPos; + } + } +} + +void nsHtml5Highlighter::FlushCurrent() { + mPos++; + FlushChars(); +} + +bool nsHtml5Highlighter::ShouldFlushOps() { + // Arbitrary threshold that doesn't have an exact justification. + // The general idea is to flush much, much sooner than reaching + // the maximum size of `nsTArray`. + return mOpQueue.Length() > 100000; +} + +mozilla::Result<bool, nsresult> nsHtml5Highlighter::FlushOps() { + bool hasOps = !mOpQueue.IsEmpty(); + if (hasOps) { + if (!mOpSink->MoveOpsFrom(mOpQueue)) { + return Err(NS_ERROR_OUT_OF_MEMORY); + } + } + return hasOps; +} + +void nsHtml5Highlighter::MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName, + nsHtml5String aValue) { + if (!(nsHtml5AttributeName::ATTR_HREF == aName || + nsHtml5AttributeName::ATTR_SRC == aName || + nsHtml5AttributeName::ATTR_ACTION == aName || + nsHtml5AttributeName::ATTR_CITE == aName || + nsHtml5AttributeName::ATTR_BACKGROUND == aName || + nsHtml5AttributeName::ATTR_LONGDESC == aName || + nsHtml5AttributeName::ATTR_XLINK_HREF == aName || + nsHtml5AttributeName::ATTR_DEFINITIONURL == aName)) { + return; + } + AddViewSourceHref(aValue); +} + +void nsHtml5Highlighter::CompletedNamedCharacterReference() { + AddClass(sEntity); +} + +nsIContent** nsHtml5Highlighter::AllocateContentHandle() { + if (mHandlesUsed == NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH) { + mOldHandles.AppendElement(std::move(mHandles)); + mHandles = + MakeUnique<nsIContent*[]>(NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH); + mHandlesUsed = 0; + } +#ifdef DEBUG + mHandles[mHandlesUsed] = reinterpret_cast<nsIContent*>(uintptr_t(0xC0DEDBAD)); +#endif + return &mHandles[mHandlesUsed++]; +} + +nsIContent** nsHtml5Highlighter::CreateElement( + nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + nsIContent** aIntendedParent, + mozilla::dom::HTMLContentCreatorFunction aCreator) { + MOZ_ASSERT(aName, "Got null name."); + nsIContent** content = AllocateContentHandle(); + opCreateHTMLElement opeation(content, aName, aAttributes, aCreator, + aIntendedParent, + mozilla::dom::FROM_PARSER_NETWORK); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(opeation)); + return content; +} + +nsIContent** nsHtml5Highlighter::CurrentNode() { + MOZ_ASSERT(mStack.Length() >= 1, "Must have something on stack."); + return mStack[mStack.Length() - 1]; +} + +void nsHtml5Highlighter::Push( + nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::HTMLContentCreatorFunction aCreator) { + MOZ_ASSERT(mStack.Length() >= 1, "Pushing without root."); + nsIContent** elt = CreateElement(aName, aAttributes, CurrentNode(), + aCreator); // Don't inline below! + opAppend operation(elt, CurrentNode(), mozilla::dom::FROM_PARSER_NETWORK); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); + mStack.AppendElement(elt); +} + +void nsHtml5Highlighter::Pop() { + MOZ_ASSERT(mStack.Length() >= 2, "Popping when stack too short."); + mStack.RemoveLastElement(); +} + +void nsHtml5Highlighter::AppendCharacters(const char16_t* aBuffer, + int32_t aStart, int32_t aLength) { + MOZ_ASSERT(aBuffer, "Null buffer"); + + char16_t* bufferCopy = new char16_t[aLength]; + memcpy(bufferCopy, aBuffer + aStart, aLength * sizeof(char16_t)); + + opAppendText operation(CurrentNode(), bufferCopy, aLength); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddClass(const char16_t* aClass) { + opAddClass operation(CurrentNode(), (char16_t*)aClass); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddViewSourceHref(nsHtml5String aValue) { + char16_t* bufferCopy = new char16_t[aValue.Length() + 1]; + aValue.CopyToBuffer(bufferCopy); + bufferCopy[aValue.Length()] = 0; + + opAddViewSourceHref operation(CurrentNode(), bufferCopy, aValue.Length()); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddBase(nsHtml5String aValue) { + if (mSeenBase) { + return; + } + mSeenBase = true; + char16_t* bufferCopy = new char16_t[aValue.Length() + 1]; + aValue.CopyToBuffer(bufferCopy); + bufferCopy[aValue.Length()] = 0; + + opAddViewSourceBase operation(bufferCopy, aValue.Length()); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddErrorToCurrentNode(const char* aMsgId) { + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + opAddErrorType operation(CurrentNode(), (char*)aMsgId); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId) { + MOZ_ASSERT(mCurrentRun, "Adding error to run without one!"); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + opAddErrorType operation(mCurrentRun, (char*)aMsgId); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId, + nsAtom* aName) { + MOZ_ASSERT(mCurrentRun, "Adding error to run without one!"); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + opAddErrorType operation(mCurrentRun, (char*)aMsgId, aName); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId, nsAtom* aName, + nsAtom* aOther) { + MOZ_ASSERT(mCurrentRun, "Adding error to run without one!"); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + opAddErrorType operation(mCurrentRun, (char*)aMsgId, aName, aOther); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddErrorToCurrentAmpersand(const char* aMsgId) { + MOZ_ASSERT(mAmpersand, "Adding error to ampersand without one!"); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + opAddErrorType operation(mAmpersand, (char*)aMsgId); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5Highlighter::AddErrorToCurrentSlash(const char* aMsgId) { + MOZ_ASSERT(mSlash, "Adding error to slash without one!"); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + opAddErrorType operation(mSlash, (char*)aMsgId); + treeOp->Init(mozilla::AsVariant(operation)); +} diff --git a/parser/html/nsHtml5Highlighter.h b/parser/html/nsHtml5Highlighter.h new file mode 100644 index 0000000000..4966b21608 --- /dev/null +++ b/parser/html/nsHtml5Highlighter.h @@ -0,0 +1,444 @@ +/* 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/. */ +#ifndef nsHtml5Highlighter_h +#define nsHtml5Highlighter_h + +#include "nsCOMPtr.h" +#include "nsHtml5TreeOperation.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsHtml5TreeOperation.h" +#include "nsAHtml5TreeOpSink.h" + +#define NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH 512 + +/** + * A state machine for generating HTML for display in View Source based on + * the transitions the tokenizer makes on the source being viewed. + */ +class nsHtml5Highlighter { + public: + /** + * The constructor. + * + * @param aOpSink the sink for the tree ops generated by this highlighter + */ + explicit nsHtml5Highlighter(nsAHtml5TreeOpSink* aOpSink); + + /** + * The destructor. + */ + ~nsHtml5Highlighter(); + + /** + * Set the op sink (for speculation). + */ + void SetOpSink(nsAHtml5TreeOpSink* aOpSink); + + /** + * Reset state to after generated head but before processing any of the input + * stream. + */ + void Rewind(); + + /** + * Starts the generated document. + */ + void Start(const nsAutoString& aTitle); + + /** + * Updates the charset source via the op queue. + */ + void UpdateCharsetSource(nsCharsetSource aCharsetSource); + + /** + * Report a tokenizer state transition. + * + * @param aState the state being transitioned to + * @param aReconsume whether this is a reconsuming transition + * @param aPos the tokenizer's current position into the buffer + */ + int32_t Transition(int32_t aState, bool aReconsume, int32_t aPos); + + /** + * Report end of file. + * + * Returns `true` normally and `false` on OOM. + */ + [[nodiscard]] bool End(); + + /** + * Set the current buffer being tokenized + */ + void SetBuffer(nsHtml5UTF16Buffer* aBuffer); + + /** + * Let go of the buffer being tokenized but first, flush text from it. + * + * @param aPos the first UTF-16 code unit not to flush + */ + void DropBuffer(int32_t aPos); + + /** + * Query whether there are some many ops in the queue + * that they should be flushed now. + * + * @return true if FlushOps() should be called now + */ + bool ShouldFlushOps(); + + /** + * Flush the tree ops into the sink. + * + * @return Ok(true) if there were ops to flush, Ok(false) + * if there were no ops to flush and Err() on OOM. + */ + mozilla::Result<bool, nsresult> FlushOps(); + + /** + * Linkify the current attribute value if the attribute name is one of + * known URL attributes. (When executing tree ops, javascript: URLs will + * not be linkified, though.) + * + * @param aName the name of the attribute + * @param aValue the value of the attribute + */ + void MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName, + nsHtml5String aValue); + + /** + * Inform the highlighter that the tokenizer successfully completed a + * named character reference. + */ + void CompletedNamedCharacterReference(); + + /** + * Adds an error annotation to the node that's currently on top of + * mStack. + * + * @param aMsgId the id of the message in the property file + */ + void AddErrorToCurrentNode(const char* aMsgId); + + /** + * Adds an error annotation to the node that corresponds to the most + * recently opened markup declaration/tag span, character reference or + * run of text. + * + * @param aMsgId the id of the message in the property file + */ + void AddErrorToCurrentRun(const char* aMsgId); + + /** + * Adds an error annotation to the node that corresponds to the most + * recently opened markup declaration/tag span, character reference or + * run of text with one atom to use when formatting the message. + * + * @param aMsgId the id of the message in the property file + * @param aName the atom + */ + void AddErrorToCurrentRun(const char* aMsgId, nsAtom* aName); + + /** + * Adds an error annotation to the node that corresponds to the most + * recently opened markup declaration/tag span, character reference or + * run of text with two atoms to use when formatting the message. + * + * @param aMsgId the id of the message in the property file + * @param aName the first atom + * @param aOther the second atom + */ + void AddErrorToCurrentRun(const char* aMsgId, nsAtom* aName, nsAtom* aOther); + + /** + * Adds an error annotation to the node that corresponds to the most + * recent potentially character reference-starting ampersand. + * + * @param aMsgId the id of the message in the property file + */ + void AddErrorToCurrentAmpersand(const char* aMsgId); + + /** + * Adds an error annotation to the node that corresponds to the most + * recent potentially self-closing slash. + * + * @param aMsgId the id of the message in the property file + */ + void AddErrorToCurrentSlash(const char* aMsgId); + + /** + * Enqueues a tree op for adding base to the urls with the view-source: + * + * @param aValue the base URL to add + */ + void AddBase(nsHtml5String aValue); + + /** + * Starts a wrapper around a run of characters. + */ + void StartCharacters(); + + private: + /** + * Starts a span with no class. + */ + void StartSpan(); + + /** + * Starts a <span> and sets the class attribute on it. + * + * @param aClass the class to set (MUST be a static string that does not + * need to be released!) + */ + void StartSpan(const char16_t* aClass); + + /** + * End the current <span> or <a> in the highlighter output. + */ + void EndSpanOrA(); + + /** + * Ends a wrapper around a run of characters. + */ + void EndCharactersAndStartMarkupRun(); + + /** + * Starts an <a>. + */ + void StartA(); + + /** + * Flushes characters up to but not including the current one. + */ + void FlushChars(); + + /** + * Flushes characters up to and including the current one. + */ + void FlushCurrent(); + + /** + * Finishes highlighting a tag in the input data by closing the open + * <span> and <a> elements in the highlighter output and then starts + * another <span> for potentially highlighting characters potentially + * appearing next. + */ + void FinishTag(); + + /** + * Adds a class attribute to the current node. + * + * @param aClass the class to set (MUST be a static string that does not + * need to be released!) + */ + void AddClass(const char16_t* aClass); + + /** + * Allocates a handle for an element. + * + * See the documentation for nsHtml5TreeBuilder::AllocateContentHandle() + * in nsHtml5TreeBuilderHSupplement.h. + * + * @return the handle + */ + nsIContent** AllocateContentHandle(); + + /** + * Enqueues an element creation tree operation. + * + * @param aName the name of the element + * @param aAttributes the attribute holder (ownership will be taken) or + * nullptr for no attributes + * @param aIntendedParent the intended parent node for the created element + * @param aCreator the content creator function + * @return the handle for the element that will be created + */ + nsIContent** CreateElement(nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + nsIContent** aIntendedParent, + mozilla::dom::HTMLContentCreatorFunction aCreator); + + /** + * Gets the handle for the current node. May be called only after the + * root element has been set. + * + * @return the handle for the current node + */ + nsIContent** CurrentNode(); + + /** + * Create an element and push it (its handle) on the stack. + * + * @param aName the name of the element + * @param aAttributes the attribute holder (ownership will be taken) or + * nullptr for no attributes + * @param aCreator the content creator function + */ + void Push(nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::HTMLContentCreatorFunction aCreator); + + /** + * Pops the current node off the stack. + */ + void Pop(); + + /** + * Appends text content to the current node. + * + * @param aBuffer the buffer to copy from + * @param aStart the index of the first code unit to copy + * @param aLength the number of code units to copy + */ + void AppendCharacters(const char16_t* aBuffer, int32_t aStart, + int32_t aLength); + + /** + * Enqueues a tree op for adding an href attribute with the view-source: + * URL scheme to the current node. + * + * @param aValue the (potentially relative) URL to link to + */ + void AddViewSourceHref(nsHtml5String aValue); + + /** + * The state we are transitioning away from. + */ + int32_t mState; + + /** + * The index of the first UTF-16 code unit in mBuffer that hasn't been + * flushed yet. + */ + int32_t mCStart; + + /** + * The position of the code unit in mBuffer that caused the current + * transition. + */ + int32_t mPos; + + /** + * The current line number. + */ + int32_t mLineNumber; + + /** + * The number of inline elements open inside the <pre> excluding the + * span potentially wrapping a run of characters. + */ + int32_t mInlinesOpen; + + /** + * Whether there's a span wrapping a run of characters (excluding CDATA + * section) open. + */ + bool mInCharacters; + + /** + * The current buffer being tokenized. + */ + nsHtml5UTF16Buffer* mBuffer; + + /** + * The outgoing tree op queue. + */ + nsTArray<nsHtml5TreeOperation> mOpQueue; + + /** + * The tree op stage for the tree op executor or a speculation when looking + * for meta charset. + * + * The op sink is owned by the nsHtml5TreeOpExecutor, which outlives this + * object, because this object is owned by the nsHtml5Tokenizer instance that + * is owned by the nsHtml5StreamParser, which keeps the executor alive via + * nsHtml5Streamparser::mExecutorFlusher. + */ + nsAHtml5TreeOpSink* mOpSink; + + /** + * The most recently opened markup declaration/tag or run of characters. + */ + nsIContent** mCurrentRun; + + /** + * The most recent ampersand in a place where character references were + * allowed. + */ + nsIContent** mAmpersand; + + /** + * The most recent slash that might become a self-closing slash. + */ + nsIContent** mSlash; + + /** + * Memory for element handles. + */ + mozilla::UniquePtr<nsIContent*[]> mHandles; + + /** + * Number of handles used in mHandles + */ + int32_t mHandlesUsed; + + /** + * A holder for old contents of mHandles + */ + nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles; + + /** + * The element stack. + */ + nsTArray<nsIContent**> mStack; + + /** + * The string "comment" + */ + static char16_t sComment[]; + + /** + * The string "cdata" + */ + static char16_t sCdata[]; + + /** + * The string "start-tag" + */ + static char16_t sStartTag[]; + + /** + * The string "attribute-name" + */ + static char16_t sAttributeName[]; + + /** + * The string "attribute-value" + */ + static char16_t sAttributeValue[]; + + /** + * The string "end-tag" + */ + static char16_t sEndTag[]; + + /** + * The string "doctype" + */ + static char16_t sDoctype[]; + + /** + * The string "entity" + */ + static char16_t sEntity[]; + + /** + * The string "pi" + */ + static char16_t sPi[]; + + /** + * Whether base is already visited once. + */ + bool mSeenBase; +}; + +#endif // nsHtml5Highlighter_h diff --git a/parser/html/nsHtml5HtmlAttributes.cpp b/parser/html/nsHtml5HtmlAttributes.cpp new file mode 100644 index 0000000000..c2cd97de50 --- /dev/null +++ b/parser/html/nsHtml5HtmlAttributes.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2008-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. + */ + +#define nsHtml5HtmlAttributes_cpp__ + +#include "jArray.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsAtom.h" +#include "nsHtml5ArrayCopy.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsHtml5String.h" +#include "nsIContent.h" +#include "nsIContentHandle.h" +#include "nsNameSpaceManager.h" +#include "nsTraceRefcnt.h" + +#include "nsHtml5AttributeName.h" +#include "nsHtml5ElementName.h" +#include "nsHtml5Portability.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5UTF16Buffer.h" + +#include "nsHtml5HtmlAttributes.h" + +nsHtml5HtmlAttributes* nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES = nullptr; + +nsHtml5HtmlAttributes::nsHtml5HtmlAttributes(int32_t aMode) : mMode(aMode) { + MOZ_COUNT_CTOR(nsHtml5HtmlAttributes); +} + +nsHtml5HtmlAttributes::~nsHtml5HtmlAttributes() { + MOZ_COUNT_DTOR(nsHtml5HtmlAttributes); + clear(0); +} + +int32_t nsHtml5HtmlAttributes::getIndex(nsHtml5AttributeName* aName) { + for (size_t i = 0; i < mStorage.Length(); i++) { + if (mStorage[i].GetLocal(nsHtml5AttributeName::HTML) == + aName->getLocal(nsHtml5AttributeName::HTML)) { + // It's release asserted elsewhere that i can't be too large. + return i; + } + } + return -1; +} + +nsHtml5String nsHtml5HtmlAttributes::getValue(nsHtml5AttributeName* aName) { + int32_t index = getIndex(aName); + if (index == -1) { + return nullptr; + } else { + return getValueNoBoundsCheck(index); + } +} + +int32_t nsHtml5HtmlAttributes::getLength() { return mStorage.Length(); } + +nsAtom* nsHtml5HtmlAttributes::getLocalNameNoBoundsCheck(int32_t aIndex) { + MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0, + "Index out of bounds"); + return mStorage[aIndex].GetLocal(mMode); +} + +int32_t nsHtml5HtmlAttributes::getURINoBoundsCheck(int32_t aIndex) { + MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0, + "Index out of bounds"); + return mStorage[aIndex].GetUri(mMode); +} + +nsAtom* nsHtml5HtmlAttributes::getPrefixNoBoundsCheck(int32_t aIndex) { + MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0, + "Index out of bounds"); + return mStorage[aIndex].GetPrefix(mMode); +} + +nsHtml5String nsHtml5HtmlAttributes::getValueNoBoundsCheck(int32_t aIndex) { + MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0, + "Index out of bounds"); + return mStorage[aIndex].GetValue(); +} + +int32_t nsHtml5HtmlAttributes::getLineNoBoundsCheck(int32_t aIndex) { + MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0, + "Index out of bounds"); + return mStorage[aIndex].GetLine(); +} + +void nsHtml5HtmlAttributes::addAttribute(nsHtml5AttributeName* aName, + nsHtml5String aValue, int32_t aLine) { + mStorage.AppendElement(nsHtml5AttributeEntry(aName, aValue, aLine)); + MOZ_RELEASE_ASSERT(mStorage.Length() <= INT32_MAX, + "Can't handle this many attributes."); +} + +// Isindex-only, so doesn't need to deal with SVG and MathML +void nsHtml5HtmlAttributes::AddAttributeWithLocal(nsAtom* aName, + nsHtml5String aValue, + int32_t aLine) { + mStorage.AppendElement(nsHtml5AttributeEntry(aName, aValue, aLine)); + MOZ_RELEASE_ASSERT(mStorage.Length() <= INT32_MAX, + "Can't handle this many attributes."); +} + +void nsHtml5HtmlAttributes::clear(int32_t aMode) { + for (nsHtml5AttributeEntry& entry : mStorage) { + entry.ReleaseValue(); + } + mStorage.TruncateLength(0); + mMode = aMode; +} + +void nsHtml5HtmlAttributes::releaseValue(int32_t aIndex) { + mStorage[aIndex].ReleaseValue(); +} + +void nsHtml5HtmlAttributes::clearWithoutReleasingContents() { + mStorage.TruncateLength(0); +} + +bool nsHtml5HtmlAttributes::contains(nsHtml5AttributeName* aName) { + for (size_t i = 0; i < mStorage.Length(); i++) { + if (mStorage[i].GetLocal(nsHtml5AttributeName::HTML) == + aName->getLocal(nsHtml5AttributeName::HTML)) { + return true; + } + } + return false; +} + +void nsHtml5HtmlAttributes::adjustForMath() { + mMode = nsHtml5AttributeName::MATHML; +} + +void nsHtml5HtmlAttributes::adjustForSvg() { + mMode = nsHtml5AttributeName::SVG; +} + +nsHtml5HtmlAttributes* nsHtml5HtmlAttributes::cloneAttributes() { + MOZ_ASSERT(mStorage.IsEmpty() || !mMode); + nsHtml5HtmlAttributes* clone = + new nsHtml5HtmlAttributes(nsHtml5AttributeName::HTML); + for (nsHtml5AttributeEntry& entry : mStorage) { + clone->AddEntry(entry.Clone()); + } + return clone; +} + +bool nsHtml5HtmlAttributes::equalsAnother(nsHtml5HtmlAttributes* aOther) { + MOZ_ASSERT(!mMode, "Trying to compare attributes in foreign content."); + if (mStorage.Length() != aOther->mStorage.Length()) { + return false; + } + for (nsHtml5AttributeEntry& entry : mStorage) { + bool found = false; + nsAtom* ownLocal = entry.GetLocal(nsHtml5AttributeName::HTML); + for (nsHtml5AttributeEntry& otherEntry : aOther->mStorage) { + if (ownLocal == otherEntry.GetLocal(nsHtml5AttributeName::HTML)) { + found = true; + if (!entry.GetValue().Equals(otherEntry.GetValue())) { + return false; + } + break; + } + } + if (!found) { + return false; + } + } + return true; +} + +void nsHtml5HtmlAttributes::AddEntry(nsHtml5AttributeEntry&& aEntry) { + mStorage.AppendElement(aEntry); +} + +void nsHtml5HtmlAttributes::initializeStatics() { + EMPTY_ATTRIBUTES = new nsHtml5HtmlAttributes(nsHtml5AttributeName::HTML); +} + +void nsHtml5HtmlAttributes::releaseStatics() { delete EMPTY_ATTRIBUTES; } diff --git a/parser/html/nsHtml5HtmlAttributes.h b/parser/html/nsHtml5HtmlAttributes.h new file mode 100644 index 0000000000..f840f0cc3e --- /dev/null +++ b/parser/html/nsHtml5HtmlAttributes.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2008-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. + */ + +#ifndef nsHtml5HtmlAttributes_h +#define nsHtml5HtmlAttributes_h + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsTArray.h" +#include "nsHtml5AttributeEntry.h" + +class nsHtml5StreamParser; + +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5AttributeName; +class nsHtml5ElementName; +class nsHtml5UTF16Buffer; +class nsHtml5StateSnapshot; +class nsHtml5Portability; + +class nsHtml5HtmlAttributes { + public: + static nsHtml5HtmlAttributes* EMPTY_ATTRIBUTES; + + private: + AutoTArray<nsHtml5AttributeEntry, 5> mStorage; + int32_t mMode; + void AddEntry(nsHtml5AttributeEntry&& aEntry); + + public: + explicit nsHtml5HtmlAttributes(int32_t aMode); + ~nsHtml5HtmlAttributes(); + + // Remove getIndex when removing isindex support + int32_t getIndex(nsHtml5AttributeName* aName); + + nsHtml5String getValue(nsHtml5AttributeName* aName); + int32_t getLength(); + nsAtom* getLocalNameNoBoundsCheck(int32_t aIndex); + int32_t getURINoBoundsCheck(int32_t aIndex); + nsAtom* getPrefixNoBoundsCheck(int32_t aIndex); + nsHtml5String getValueNoBoundsCheck(int32_t aIndex); + nsHtml5AttributeName* getAttributeNameNoBoundsCheck(int32_t aIndex); + int32_t getLineNoBoundsCheck(int32_t aIndex); + void addAttribute(nsHtml5AttributeName* aName, nsHtml5String aValue, + int32_t aLine); + void AddAttributeWithLocal(nsAtom* aName, nsHtml5String aValue, + int32_t aLine); + void clear(int32_t aMode); + void releaseValue(int32_t aIndex); + void clearWithoutReleasingContents(); + bool contains(nsHtml5AttributeName* aName); + void adjustForMath(); + void adjustForSvg(); + nsHtml5HtmlAttributes* cloneAttributes(); + bool equalsAnother(nsHtml5HtmlAttributes* aOther); + static void initializeStatics(); + static void releaseStatics(); +}; + +#endif diff --git a/parser/html/nsHtml5Macros.h b/parser/html/nsHtml5Macros.h new file mode 100644 index 0000000000..751d4dc04e --- /dev/null +++ b/parser/html/nsHtml5Macros.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010 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. + */ + +#ifndef nsHtml5Macros_h +#define nsHtml5Macros_h + +#define NS_HTML5_CONTINUE(target) goto target + +#define NS_HTML5_BREAK(target) goto target##_end + +#endif /* nsHtml5Macros_h */ diff --git a/parser/html/nsHtml5Module.cpp b/parser/html/nsHtml5Module.cpp new file mode 100644 index 0000000000..366a63e54f --- /dev/null +++ b/parser/html/nsHtml5Module.cpp @@ -0,0 +1,123 @@ +/* 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/. */ + +#include "nsHtml5Module.h" +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Attributes.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/StaticPrefs_html5.h" +#include "nsCOMPtr.h" +#include "nsHtml5AttributeName.h" +#include "nsHtml5ElementName.h" +#include "nsHtml5HtmlAttributes.h" +#include "nsHtml5NamedCharacters.h" +#include "nsHtml5Portability.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsIObserverService.h" + +using namespace mozilla; + +// static +nsIThread* nsHtml5Module::sStreamParserThread = nullptr; + +class nsHtml5ParserThreadTerminator final : public nsIObserver { + public: + NS_DECL_ISUPPORTS + explicit nsHtml5ParserThreadTerminator(nsIThread* aThread) + : mThread(aThread) {} + NS_IMETHOD Observe(nsISupports*, const char* topic, + const char16_t*) override { + NS_ASSERTION(!strcmp(topic, "xpcom-shutdown-threads"), "Unexpected topic"); + mThread->Shutdown(); + mThread = nullptr; + NS_IF_RELEASE(nsHtml5Module::sStreamParserThread); + nsHtml5Module::sStreamParserThread = nullptr; + return NS_OK; + } + + private: + ~nsHtml5ParserThreadTerminator() = default; + + nsCOMPtr<nsIThread> mThread; +}; + +NS_IMPL_ISUPPORTS(nsHtml5ParserThreadTerminator, nsIObserver) + +// static +void nsHtml5Module::InitializeStatics() { + nsHtml5AttributeName::initializeStatics(); + nsHtml5ElementName::initializeStatics(); + nsHtml5HtmlAttributes::initializeStatics(); + nsHtml5NamedCharacters::initializeStatics(); + nsHtml5Portability::initializeStatics(); + nsHtml5StackNode::initializeStatics(); + nsHtml5Tokenizer::initializeStatics(); + nsHtml5TreeBuilder::initializeStatics(); + nsHtml5UTF16Buffer::initializeStatics(); + + NS_NewNamedThread("HTML5 Parser", &sStreamParserThread); + if (sStreamParserThread) { + nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); + if (os) { + os->AddObserver(new nsHtml5ParserThreadTerminator(sStreamParserThread), + "xpcom-shutdown-threads", false); + } else { + MOZ_ASSERT(false, + "How come we failed to create get the observer service?"); + } + } else { + MOZ_ASSERT(false, "How come we failed to create the parser thread?"); + } + +#ifdef DEBUG + sNsHtml5ModuleInitialized = true; +#endif +} + +// static +void nsHtml5Module::ReleaseStatics() { +#ifdef DEBUG + sNsHtml5ModuleInitialized = false; +#endif + nsHtml5AttributeName::releaseStatics(); + nsHtml5ElementName::releaseStatics(); + nsHtml5HtmlAttributes::releaseStatics(); + nsHtml5NamedCharacters::releaseStatics(); + nsHtml5Portability::releaseStatics(); + nsHtml5StackNode::releaseStatics(); + nsHtml5Tokenizer::releaseStatics(); + nsHtml5TreeBuilder::releaseStatics(); + nsHtml5UTF16Buffer::releaseStatics(); + NS_IF_RELEASE(sStreamParserThread); +} + +// static +already_AddRefed<nsHtml5Parser> nsHtml5Module::NewHtml5Parser() { + MOZ_ASSERT(sNsHtml5ModuleInitialized, "nsHtml5Module not initialized."); + RefPtr<nsHtml5Parser> rv = new nsHtml5Parser(); + return rv.forget(); +} + +// static +already_AddRefed<nsISerialEventTarget> +nsHtml5Module::GetStreamParserEventTarget() { + MOZ_ASSERT(sNsHtml5ModuleInitialized, "nsHtml5Module not initialized."); + if (sStreamParserThread) { + nsCOMPtr<nsISerialEventTarget> target = sStreamParserThread; + return target.forget(); + } + nsCOMPtr<nsIThread> mainThread; + NS_GetMainThread(getter_AddRefs(mainThread)); + MOZ_RELEASE_ASSERT(mainThread); // Unrecoverable situation + nsCOMPtr<nsISerialEventTarget> target = mainThread; + return target.forget(); +} + +#ifdef DEBUG +bool nsHtml5Module::sNsHtml5ModuleInitialized = false; +#endif diff --git a/parser/html/nsHtml5Module.h b/parser/html/nsHtml5Module.h new file mode 100644 index 0000000000..950de37e53 --- /dev/null +++ b/parser/html/nsHtml5Module.h @@ -0,0 +1,28 @@ +/* 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/. */ + +#ifndef nsHtml5Module_h +#define nsHtml5Module_h + +#include "nsIThread.h" + +class nsHtml5Parser; + +class nsHtml5Module { + friend class nsHtml5ParserThreadTerminator; + + public: + static void InitializeStatics(); + static void ReleaseStatics(); + static already_AddRefed<nsHtml5Parser> NewHtml5Parser(); + static already_AddRefed<nsISerialEventTarget> GetStreamParserEventTarget(); + + private: +#ifdef DEBUG + static bool sNsHtml5ModuleInitialized; +#endif + static nsIThread* sStreamParserThread; +}; + +#endif // nsHtml5Module_h diff --git a/parser/html/nsHtml5NamedCharacters.cpp b/parser/html/nsHtml5NamedCharacters.cpp new file mode 100644 index 0000000000..5181d7538e --- /dev/null +++ b/parser/html/nsHtml5NamedCharacters.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2008-2010 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. + */ + +#define nsHtml5NamedCharacters_cpp_ +#include "jArray.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/Logging.h" +#include "nsDebug.h" +#include "nscore.h" + +#include "nsHtml5NamedCharacters.h" + +const char16_t nsHtml5NamedCharacters::VALUES[][2] = { +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) {VALUE}, +#include "nsHtml5NamedCharactersInclude.h" +#undef NAMED_CHARACTER_REFERENCE + {0, 0}}; + +char16_t** nsHtml5NamedCharacters::WINDOWS_1252; +static char16_t const WINDOWS_1252_DATA[] = { + 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, + 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178}; + +/** + * To avoid having lots of pointers in the |charData| array, below, + * which would cause us to have to do lots of relocations at library + * load time, store all the string data for the names in one big array. + * Then use tricks with enums to help us build an array that contains + * the positions of each within the big arrays. + */ + +static const int8_t ALL_NAMES[] = { +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) CHARS, +#include "nsHtml5NamedCharactersInclude.h" +#undef NAMED_CHARACTER_REFERENCE +}; + +enum NamePositions { + DUMMY_INITIAL_NAME_POSITION = 0, +/* enums don't take up space, so generate _START and _END */ +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ + NAME_##N##_DUMMY, /* automatically one higher than previous */ \ + NAME_##N##_START = NAME_##N##_DUMMY - 1, \ + NAME_##N##_END = NAME_##N##_START + LEN + FLAG, +#include "nsHtml5NamedCharactersInclude.h" +#undef NAMED_CHARACTER_REFERENCE + DUMMY_FINAL_NAME_VALUE +}; + +static_assert(MOZ_ARRAY_LENGTH(ALL_NAMES) < 0x10000, + "Start positions should fit in 16 bits"); + +const nsHtml5CharacterName nsHtml5NamedCharacters::NAMES[] = { +#ifdef DEBUG +# define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ + {NAME_##N##_START, LEN, N}, +#else +# define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ + { \ + NAME_##N##_START, \ + LEN, \ + }, +#endif +#include "nsHtml5NamedCharactersInclude.h" +#undef NAMED_CHARACTER_REFERENCE +}; + +int32_t nsHtml5CharacterName::length() const { return nameLen; } + +char16_t nsHtml5CharacterName::charAt(int32_t index) const { + return static_cast<char16_t>(ALL_NAMES[nameStart + index]); +} + +void nsHtml5NamedCharacters::initializeStatics() { + WINDOWS_1252 = new char16_t*[32]; + for (int32_t i = 0; i < 32; ++i) { + WINDOWS_1252[i] = (char16_t*)&(WINDOWS_1252_DATA[i]); + } +} + +void nsHtml5NamedCharacters::releaseStatics() { delete[] WINDOWS_1252; } diff --git a/parser/html/nsHtml5NamedCharacters.h b/parser/html/nsHtml5NamedCharacters.h new file mode 100644 index 0000000000..379c2c17b9 --- /dev/null +++ b/parser/html/nsHtml5NamedCharacters.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2008-2010 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. + */ + +#ifndef nsHtml5NamedCharacters_h +#define nsHtml5NamedCharacters_h + +#include "jArray.h" +#include "nscore.h" +#include "nsDebug.h" +#include "mozilla/Logging.h" + +struct nsHtml5CharacterName { + uint16_t nameStart; + uint16_t nameLen; +#ifdef DEBUG + int32_t n; +#endif + int32_t length() const; + char16_t charAt(int32_t index) const; +}; + +class nsHtml5NamedCharacters { + public: + static const nsHtml5CharacterName NAMES[]; + static const char16_t VALUES[][2]; + static char16_t** WINDOWS_1252; + static void initializeStatics(); + static void releaseStatics(); +}; + +#endif // nsHtml5NamedCharacters_h diff --git a/parser/html/nsHtml5NamedCharactersAccel.cpp b/parser/html/nsHtml5NamedCharactersAccel.cpp new file mode 100644 index 0000000000..a486c102d2 --- /dev/null +++ b/parser/html/nsHtml5NamedCharactersAccel.cpp @@ -0,0 +1,463 @@ +/* + * Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and Opera + * Software ASA. + * + * You are granted a license to use, reproduce and create derivative works of + * this document. + */ + +#include "nsHtml5NamedCharactersAccel.h" + +static int32_t const HILO_ACCEL_65[] = { + 0, 0, 0, 0, 0, 0, 0, 12386493, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 40174181, 0, 0, + 0, 0, 60162966, 0, 0, 0, 75367550, 0, 0, + 0, 82183396, 0, 0, 0, 0, 0, 115148507, 0, + 0, 135989275, 139397199, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_66[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 28770743, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82248935, 0, + 0, 0, 0, 0, 115214046, 0, 0, 0, 139528272, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_68[] = { + 0, 0, 0, 4980811, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38470219, 0, 0, 0, 0, + 0, 0, 0, 0, 64553944, 0, 0, 0, 0, 0, 0, 0, 92145022, + 0, 0, 0, 0, 0, 0, 0, 0, 139593810, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_69[] = { + 65536, 0, 0, 0, 0, 0, 0, 0, 13172937, 0, 0, 0, 0, 0, + 25297282, 0, 0, 28901816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 71500866, 0, 0, 0, 0, 82380008, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_71[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94897574, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_72[] = { + 0, 0, 2555943, 0, 0, 0, 0, 0, 0, 0, 15532269, + 0, 0, 0, 0, 0, 0, 0, 31785444, 34406924, 0, 0, + 0, 0, 0, 40895088, 0, 0, 0, 60228503, 0, 0, 0, + 0, 0, 0, 0, 82445546, 0, 0, 0, 0, 0, 115279583, + 0, 0, 136054812, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_73[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 40239718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_74[] = { + 0, 0, 0, 5046349, 0, 0, 10944679, 0, 13238474, 0, 15597806, + 16056565, 0, 20578618, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_76[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 95225257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_77[] = { + 196610, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_78[] = { + 0, 0, 0, 0, 8454273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 46072511, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_79[] = { + 0, 0, 2687016, 0, 0, 0, 0, 0, 13304011, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31850982, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_82[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 34472462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 95290798, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_83[] = { + 0, 0, 0, 5111886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 34603535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 105776718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_84[] = { + 0, 0, 0, 0, 8585346, 0, 11075752, 0, 0, 0, 0, 16187638, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_85[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28508594, 0, + 0, 0, 0, 0, 0, 0, 40305255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_86[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 95421871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_90[] = { + 0, 0, 0, 5177423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_97[] = { + 327684, 1900571, 2949162, 5374032, 8716420, 0, 11206826, + 12517566, 13435084, 0, 15663343, 16515320, 19988785, 20644155, + 25428355, 27197855, 0, 29163962, 31916519, 34734609, 36045347, + 0, 0, 0, 40436328, 40960625, 41615994, 46596800, + 54264627, 60556184, 64750554, 68879387, 71763012, 75826303, 77268122, + 0, 81462490, 83952875, 92865919, 96142769, 105973327, 110167691, + 0, 116917984, 121833283, 132253665, 136251421, 140707923, 0, + 0, 144574620, 145361066}; + +static int32_t const HILO_ACCEL_98[] = { + 393222, 0, 0, 0, 0, 0, 11272364, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 36176423, + 38535756, 0, 0, 0, 0, 41681532, 46727880, + 0, 60687261, 0, 0, 71828552, 75891846, 0, + 0, 0, 84411650, 0, 96404924, 0, 0, + 0, 117376761, 121898820, 132319203, 136382496, 0, 0, + 0, 0, 0}; + +static int32_t const HILO_ACCEL_99[] = { + 589831, 1966110, 3276846, 5505107, 8978566, 10420383, 11468973, + 12583104, 13631694, 15139046, 15794416, 16711933, 20054322, 20840764, + 25624965, 27263392, 0, 29360574, 32244200, 34931219, 36373033, + 38601293, 39584348, 0, 40567402, 41091698, 42205821, 46858954, + 54723389, 60818335, 65143773, 68944924, 71959625, 75957383, 77530268, + 80938194, 81593564, 84739337, 92997002, 96863680, 106235474, 110233234, + 0, 117704448, 122816325, 132515812, 136579106, 140773476, 142149753, + 143001732, 144705695, 145492139}; + +static int32_t const HILO_ACCEL_100[] = { + 0, 0, 3342387, 0, 9044106, 0, 11534512, + 0, 13697233, 0, 0, 0, 0, 0, + 25690504, 0, 0, 0, 0, 0, 36438572, + 38732366, 0, 0, 0, 41157236, 0, 46924492, + 54788932, 61080481, 65209315, 0, 72025163, 0, 0, + 0, 0, 85132558, 93062540, 96929223, 106563158, 0, + 0, 118032133, 123012947, 132581351, 136775717, 140839013, 0, + 143067271, 0, 145557677}; + +static int32_t const HILO_ACCEL_101[] = { + 0, 2162719, 3473460, 5636181, 0, 0, 0, + 0, 0, 0, 0, 18809088, 20185395, 21299519, + 0, 0, 0, 29622721, 0, 0, 0, + 39256656, 39649885, 0, 0, 41288309, 42336901, 47448781, + 55182149, 61342629, 65274852, 69010461, 72811596, 76219528, 77726880, + 0, 0, 86967572, 93128077, 97650120, 106628699, 110560915, + 0, 118490890, 123733846, 132646888, 0, 141232230, 142411898, + 0, 144836769, 145688750}; + +static int32_t const HILO_ACCEL_102[] = { + 655370, 2228258, 3538998, 5701719, 9109643, 10485920, 11600049, + 12648641, 13762770, 15204584, 15859954, 18874656, 20250933, 21365062, + 25756041, 27328929, 28574132, 29688261, 32309741, 34996758, 36504109, + 39322200, 39715422, 39912033, 40632940, 41353847, 42467975, 47514325, + 55247691, 61473705, 65405925, 69272606, 72877144, 76285068, 77857955, + 81003732, 81659102, 87164208, 93193614, 97715667, 106759772, 110626456, + 114296528, 118687505, 123864929, 132712425, 136906792, 141297772, 142477438, + 143132808, 144902307, 145754288}; + +static int32_t const HILO_ACCEL_103[] = { + 786443, 0, 0, 0, 9240716, 0, 11665586, 0, + 13893843, 0, 0, 0, 0, 0, 25887114, 0, + 0, 0, 0, 0, 36635182, 0, 0, 0, + 0, 0, 42599049, 0, 0, 0, 65733607, 0, + 73008217, 0, 77989029, 0, 81724639, 87295283, 0, 98305492, + 107021918, 0, 0, 0, 0, 0, 137037866, 0, + 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_104[] = { + 0, 0, 3604535, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 27394466, 0, 29753798, 32571886, 35258903, 0, + 0, 0, 0, 0, 0, 0, 0, + 55509836, 61604779, 0, 0, 0, 0, 0, + 0, 81790176, 87557429, 93259151, 98502109, 107152994, 110888601, + 0, 119015188, 124323683, 133498858, 137234476, 0, 0, + 143263881, 0, 145819825}; + +static int32_t const HILO_ACCEL_105[] = { + 0, 0, 3866680, 6160472, 0, 10616993, 0, + 12714178, 0, 0, 0, 0, 20316470, 0, + 0, 27460003, 0, 31261127, 32637426, 35521051, 0, + 0, 0, 39977570, 0, 0, 0, 48366294, + 56492880, 62391213, 0, 69338146, 73073755, 0, 78316711, + 0, 0, 0, 93980048, 98764256, 107218532, 111085213, + 114362065, 119736089, 125241194, 133957622, 0, 0, 0, + 143329419, 144967844, 145885362}; + +static int32_t const HILO_ACCEL_106[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 62456761, 0, 69403683, 73139292, 0, 78382252, 0, + 81855713, 87622969, 0, 98829796, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_107[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 48431843, 0, 0, 0, 0, 0, 76416141, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_108[] = { + 851981, 0, 4063292, 0, 9306254, 0, 0, + 0, 0, 0, 0, 19005729, 0, 0, + 0, 27525540, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42795659, 49152740, + 56623967, 62587834, 66061292, 69600292, 73401437, 0, 0, + 0, 0, 87950650, 94111131, 99878373, 107546213, 112002720, + 0, 119932708, 125306744, 0, 137496623, 141363309, 0, + 143460492, 0, 0}; + +static int32_t const HILO_ACCEL_109[] = { + 917518, 0, 0, 0, 9502863, 0, 0, + 0, 14155989, 0, 0, 19071267, 0, 0, + 26083724, 0, 0, 0, 32702963, 0, 36700720, + 0, 0, 0, 0, 0, 43057806, 0, + 0, 0, 66520049, 0, 0, 0, 78841005, + 81069269, 0, 88147263, 0, 99943925, 107873898, 112068270, + 0, 120063783, 125831033, 0, 137693235, 0, 0, + 143526030, 0, 0}; + +static int32_t const HILO_ACCEL_110[] = { + 983055, 0, 0, 0, 0, 0, 0, + 0, 14483673, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37093937, + 0, 0, 0, 0, 0, 44565138, 49349359, + 0, 0, 66651128, 69665831, 73860193, 0, 79561908, + 0, 0, 88606018, 94176669, 0, 0, 0, + 0, 120129321, 0, 0, 0, 141494382, 0, + 143591567, 0, 0}; + +static int32_t const HILO_ACCEL_111[] = { + 1114128, 2293795, 4587583, 8257631, 9633938, 10813603, 11731123, + 12845251, 14680286, 15270121, 15925491, 19661092, 20382007, 24969543, + 26149263, 27656613, 28639669, 31392222, 32768500, 35586591, 37225015, + 39387737, 39780959, 40043107, 40698477, 41419384, 44696233, 52495090, + 57738081, 63439804, 66782202, 69927976, 73925736, 76809359, 79824063, + 81134806, 81921250, 89785673, 94307742, 100795894, 107939439, 112330415, + 114427602, 120588074, 126158721, 134416381, 137824310, 141559920, 142542975, + 143853712, 145033381, 145950899}; + +static int32_t const HILO_ACCEL_112[] = { + 1179666, 0, 0, 0, 9699476, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 26280336, 0, 0, 0, 0, 0, 38076985, + 0, 0, 0, 0, 0, 45220523, 52560674, + 0, 0, 67175420, 69993516, 0, 0, 79889603, + 0, 0, 89916763, 94373280, 101451267, 108136048, 0, + 114493139, 120784689, 126355334, 134481924, 138414136, 141625457, 142608512, + 0, 0, 0}; + +static int32_t const HILO_ACCEL_113[] = { + 0, 0, 0, 0, 9896085, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 33292789, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67830786, 0, 0, 0, 80020676, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 127403913, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_114[] = { + 1310739, 2359332, 4653127, 0, 0, 0, 12189876, + 0, 0, 0, 0, 0, 0, 0, + 26345874, 28246439, 0, 31457760, 0, 35652128, 38142534, + 0, 0, 0, 0, 0, 45351603, 52757283, + 57869170, 63636425, 67961868, 71304237, 73991273, 0, 0, + 0, 0, 90309981, 0, 101910029, 108988019, 114034355, + 0, 120850228, 127469465, 135464965, 138741825, 141690994, 142739585, + 143984788, 0, 0}; + +static int32_t const HILO_ACCEL_115[] = { + 1441813, 2424869, 4718664, 8388735, 10027160, 10879142, 12255419, + 12976325, 14745825, 15401194, 15991028, 19857709, 20447544, 25035134, + 26542483, 28377520, 28705206, 31588833, 33358333, 35783201, 38208071, + 39453274, 39846496, 40108644, 40764014, 41484921, 45613749, 53216038, + 58196852, 63898572, 68158478, 71369793, 74253418, 77005973, 80479430, + 81265879, 81986787, 90965347, 94504353, 103679508, 109250176, 114165453, + 114558676, 121243445, 127731610, 135727124, 138807366, 142018675, 142805123, + 144115862, 145098918, 146016436}; + +static int32_t const HILO_ACCEL_116[] = { + 1572887, 0, 0, 0, 10092698, 0, 12320956, + 0, 14811362, 0, 0, 19923248, 0, 25166207, + 26739094, 0, 0, 0, 33423870, 0, 38273608, + 0, 0, 0, 0, 0, 45744825, 0, + 58262393, 64095184, 68355089, 0, 75170926, 0, 80610509, + 0, 0, 91817325, 0, 104203823, 109512324, 0, + 0, 121636667, 128059294, 0, 139069511, 0, 0, + 0, 0, 0}; + +static int32_t const HILO_ACCEL_117[] = { + 1703961, 2490406, 4849737, 0, 10223771, 0, 0, + 13107399, 15007971, 15466732, 0, 0, 20513081, 25231745, + 26870169, 0, 0, 31654371, 34275839, 0, 38404681, + 0, 0, 0, 40829551, 0, 45875899, 53609261, + 59900794, 64226259, 68551700, 0, 0, 0, 80807119, + 81331417, 0, 91948410, 94700963, 104465975, 109643400, 114230991, + 114951893, 121702209, 131663779, 0, 139266123, 0, 0, + 144246936, 145295527, 0}; + +static int32_t const HILO_ACCEL_118[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 27132315, 0, 0, 0, + 0, 0, 0, 39518811, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 75302012, 0, 0, 0, + 0, 92079484, 0, 105383483, 109708938, 0, 0, 0, 0, + 0, 0, 0, 0, 144312474, 0, 0}; + +static int32_t const HILO_ACCEL_119[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 46006973, 0, 60031891, 64291797, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 105711177, + 0, 0, 0, 0, 131991514, 135923736, 139331662, 0, 0, 144378011, + 0, 146147509}; + +static int32_t const HILO_ACCEL_120[] = { + 0, 0, 0, 0, 10354845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68813847, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 121767746, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_121[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60097429, 0, 0, 0, 0, 77137048, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int32_t const HILO_ACCEL_122[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64422870, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 132122591, 0, 0, 142084216, 0, 0, 0, 0}; + +const int32_t* const nsHtml5NamedCharactersAccel::HILO_ACCEL[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + HILO_ACCEL_65, + HILO_ACCEL_66, + 0, + HILO_ACCEL_68, + HILO_ACCEL_69, + 0, + HILO_ACCEL_71, + HILO_ACCEL_72, + HILO_ACCEL_73, + HILO_ACCEL_74, + 0, + HILO_ACCEL_76, + HILO_ACCEL_77, + HILO_ACCEL_78, + HILO_ACCEL_79, + 0, + 0, + HILO_ACCEL_82, + HILO_ACCEL_83, + HILO_ACCEL_84, + HILO_ACCEL_85, + HILO_ACCEL_86, + 0, + 0, + 0, + HILO_ACCEL_90, + 0, + 0, + 0, + 0, + 0, + 0, + HILO_ACCEL_97, + HILO_ACCEL_98, + HILO_ACCEL_99, + HILO_ACCEL_100, + HILO_ACCEL_101, + HILO_ACCEL_102, + HILO_ACCEL_103, + HILO_ACCEL_104, + HILO_ACCEL_105, + HILO_ACCEL_106, + HILO_ACCEL_107, + HILO_ACCEL_108, + HILO_ACCEL_109, + HILO_ACCEL_110, + HILO_ACCEL_111, + HILO_ACCEL_112, + HILO_ACCEL_113, + HILO_ACCEL_114, + HILO_ACCEL_115, + HILO_ACCEL_116, + HILO_ACCEL_117, + HILO_ACCEL_118, + HILO_ACCEL_119, + HILO_ACCEL_120, + HILO_ACCEL_121, + HILO_ACCEL_122}; diff --git a/parser/html/nsHtml5NamedCharactersAccel.h b/parser/html/nsHtml5NamedCharactersAccel.h new file mode 100644 index 0000000000..de21f67c45 --- /dev/null +++ b/parser/html/nsHtml5NamedCharactersAccel.h @@ -0,0 +1,22 @@ +/* + * Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and Opera + * Software ASA. + * + * You are granted a license to use, reproduce and create derivative works of + * this document. + */ + +#ifndef nsHtml5NamedCharactersAccel_h +#define nsHtml5NamedCharactersAccel_h + +#include "jArray.h" +#include "nscore.h" +#include "nsDebug.h" +#include "mozilla/Logging.h" + +class nsHtml5NamedCharactersAccel { + public: + static const int32_t* const HILO_ACCEL[]; +}; + +#endif // nsHtml5NamedCharactersAccel_h diff --git a/parser/html/nsHtml5NamedCharactersInclude.h b/parser/html/nsHtml5NamedCharactersInclude.h new file mode 100644 index 0000000000..1d178937a4 --- /dev/null +++ b/parser/html/nsHtml5NamedCharactersInclude.h @@ -0,0 +1,5467 @@ +/* + * Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and Opera + * Software ASA. + * + * You are granted a license to use, reproduce and create derivative works of + * this document. + */ + +/* Data generated from the table of named character references found at + * + * http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html#named-character-references + * + * Files that #include this file must #define NAMED_CHARACTER_REFERENCE as a + * macro of four parameters: + * + * 1. a unique integer N identifying the Nth [0,1,..] macro expansion in this + * file, + * 2. a comma-separated sequence of characters comprising the character name, + * without the first two letters or 0 if the sequence would be empty. + * See Tokenizer.java. + * 3. the length of this sequence of characters, + * 4. placeholder flag (0 if argument #is not a placeholder and 1 if it is), + * 5. a comma-separated sequence of char16_t literals corresponding + * to the code-point(s) of the named character. + * + * The macro expansion doesn't have to refer to all or any of these parameters, + * but common sense dictates that it should involve at least one of them. + */ + +// This #define allows the NAMED_CHARACTER_REFERENCE macro to accept comma- +// separated sequences as single macro arguments. Using commas directly would +// split the sequence into multiple macro arguments. +#define _ , + +NAMED_CHARACTER_REFERENCE(0, /* A E */ 'l' _ 'i' _ 'g', 3, 0, 0x00c6 _ 0) +NAMED_CHARACTER_REFERENCE(1, /* A E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00c6 _ 0) +NAMED_CHARACTER_REFERENCE(2, /* A M */ 'P', 1, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(3, /* A M */ 'P' _ ';', 2, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(4, /* A a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c1 _ 0) +NAMED_CHARACTER_REFERENCE(5, + /* A a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00c1 _ 0) +NAMED_CHARACTER_REFERENCE(6, + /* A b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, + 0x0102 _ 0) +NAMED_CHARACTER_REFERENCE(7, /* A c */ 'i' _ 'r' _ 'c', 3, 0, 0x00c2 _ 0) +NAMED_CHARACTER_REFERENCE(8, /* A c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00c2 _ 0) +NAMED_CHARACTER_REFERENCE(9, /* A c */ 'y' _ ';', 2, 0, 0x0410 _ 0) +NAMED_CHARACTER_REFERENCE(10, /* A f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd04) +NAMED_CHARACTER_REFERENCE(11, /* A g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c0 _ 0) +NAMED_CHARACTER_REFERENCE(12, + /* A g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00c0 _ 0) +NAMED_CHARACTER_REFERENCE(13, /* A l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x0391 _ 0) +NAMED_CHARACTER_REFERENCE(14, /* A m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0100 _ 0) +NAMED_CHARACTER_REFERENCE(15, /* A n */ 'd' _ ';', 2, 0, 0x2a53 _ 0) +NAMED_CHARACTER_REFERENCE(16, /* A o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0104 _ 0) +NAMED_CHARACTER_REFERENCE(17, /* A o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd38) +NAMED_CHARACTER_REFERENCE( + 18, + /* A p */ + 'p' _ 'l' _ 'y' _ 'F' _ 'u' _ 'n' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12, + 0, 0x2061 _ 0) +NAMED_CHARACTER_REFERENCE(19, /* A r */ 'i' _ 'n' _ 'g', 3, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(20, /* A r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(21, /* A s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9c) +NAMED_CHARACTER_REFERENCE(22, + /* A s */ 's' _ 'i' _ 'g' _ 'n' _ ';', 5, 0, + 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(23, /* A t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00c3 _ 0) +NAMED_CHARACTER_REFERENCE(24, + /* A t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x00c3 _ 0) +NAMED_CHARACTER_REFERENCE(25, /* A u */ 'm' _ 'l', 2, 0, 0x00c4 _ 0) +NAMED_CHARACTER_REFERENCE(26, /* A u */ 'm' _ 'l' _ ';', 3, 0, 0x00c4 _ 0) +NAMED_CHARACTER_REFERENCE( + 27, + /* B a */ 'c' _ 'k' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 8, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(28, /* B a */ 'r' _ 'v' _ ';', 3, 0, 0x2ae7 _ 0) +NAMED_CHARACTER_REFERENCE(29, + /* B a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0, + 0x2306 _ 0) +NAMED_CHARACTER_REFERENCE(30, /* B c */ 'y' _ ';', 2, 0, 0x0411 _ 0) +NAMED_CHARACTER_REFERENCE(31, + /* B e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0, + 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE( + 32, + /* B e */ 'r' _ 'n' _ 'o' _ 'u' _ 'l' _ 'l' _ 'i' _ 's' _ ';', 9, 0, + 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(33, /* B e */ 't' _ 'a' _ ';', 3, 0, 0x0392 _ 0) +NAMED_CHARACTER_REFERENCE(34, /* B f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd05) +NAMED_CHARACTER_REFERENCE(35, /* B o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd39) +NAMED_CHARACTER_REFERENCE(36, /* B r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0) +NAMED_CHARACTER_REFERENCE(37, /* B s */ 'c' _ 'r' _ ';', 3, 0, 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(38, + /* B u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0, + 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(39, /* C H */ 'c' _ 'y' _ ';', 3, 0, 0x0427 _ 0) +NAMED_CHARACTER_REFERENCE(40, /* C O */ 'P' _ 'Y', 2, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(41, /* C O */ 'P' _ 'Y' _ ';', 3, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(42, + /* C a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0106 _ 0) +NAMED_CHARACTER_REFERENCE(43, /* C a */ 'p' _ ';', 2, 0, 0x22d2 _ 0) +NAMED_CHARACTER_REFERENCE( + 44, + /* C a */ + 'p' _ 'i' _ 't' _ 'a' _ 'l' _ 'D' _ 'i' _ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', + 19, 0, 0x2145 _ 0) +NAMED_CHARACTER_REFERENCE(45, + /* C a */ 'y' _ 'l' _ 'e' _ 'y' _ 's' _ ';', 6, 0, + 0x212d _ 0) +NAMED_CHARACTER_REFERENCE(46, + /* C c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x010c _ 0) +NAMED_CHARACTER_REFERENCE(47, /* C c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00c7 _ 0) +NAMED_CHARACTER_REFERENCE(48, + /* C c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x00c7 _ 0) +NAMED_CHARACTER_REFERENCE(49, /* C c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0108 _ 0) +NAMED_CHARACTER_REFERENCE(50, + /* C c */ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 6, 0, + 0x2230 _ 0) +NAMED_CHARACTER_REFERENCE(51, /* C d */ 'o' _ 't' _ ';', 3, 0, 0x010a _ 0) +NAMED_CHARACTER_REFERENCE(52, + /* C e */ 'd' _ 'i' _ 'l' _ 'l' _ 'a' _ ';', 6, 0, + 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE( + 53, + /* C e */ 'n' _ 't' _ 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(54, /* C f */ 'r' _ ';', 2, 0, 0x212d _ 0) +NAMED_CHARACTER_REFERENCE(55, /* C h */ 'i' _ ';', 2, 0, 0x03a7 _ 0) +NAMED_CHARACTER_REFERENCE( + 56, + /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x2299 _ 0) +NAMED_CHARACTER_REFERENCE( + 57, + /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 10, 0, + 0x2296 _ 0) +NAMED_CHARACTER_REFERENCE( + 58, + /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 9, 0, + 0x2295 _ 0) +NAMED_CHARACTER_REFERENCE( + 59, + /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 10, 0, + 0x2297 _ 0) +NAMED_CHARACTER_REFERENCE( + 60, + /* C l */ + 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', + 23, 0, 0x2232 _ 0) +NAMED_CHARACTER_REFERENCE( + 61, + /* C l */ + 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', + 20, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE( + 62, + /* C l */ + 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', + 14, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(63, /* C o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x2237 _ 0) +NAMED_CHARACTER_REFERENCE(64, + /* C o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0, + 0x2a74 _ 0) +NAMED_CHARACTER_REFERENCE( + 65, + /* C o */ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 8, 0, 0x2261 _ 0) +NAMED_CHARACTER_REFERENCE(66, + /* C o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0, + 0x222f _ 0) +NAMED_CHARACTER_REFERENCE( + 67, + /* C o */ + 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', + 14, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(68, /* C o */ 'p' _ 'f' _ ';', 3, 0, 0x2102 _ 0) +NAMED_CHARACTER_REFERENCE( + 69, + /* C o */ 'p' _ 'r' _ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 8, 0, 0x2210 _ 0) +NAMED_CHARACTER_REFERENCE( + 70, + /* C o */ + 'u' _ 'n' _ 't' _ 'e' _ 'r' _ 'C' _ 'l' _ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', + 30, 0, 0x2233 _ 0) +NAMED_CHARACTER_REFERENCE(71, /* C r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2a2f _ 0) +NAMED_CHARACTER_REFERENCE(72, /* C s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9e) +NAMED_CHARACTER_REFERENCE(73, /* C u */ 'p' _ ';', 2, 0, 0x22d3 _ 0) +NAMED_CHARACTER_REFERENCE(74, + /* C u */ 'p' _ 'C' _ 'a' _ 'p' _ ';', 5, 0, + 0x224d _ 0) +NAMED_CHARACTER_REFERENCE(75, /* D D */ ';', 1, 0, 0x2145 _ 0) +NAMED_CHARACTER_REFERENCE(76, + /* D D */ 'o' _ 't' _ 'r' _ 'a' _ 'h' _ 'd' _ ';', 7, + 0, 0x2911 _ 0) +NAMED_CHARACTER_REFERENCE(77, /* D J */ 'c' _ 'y' _ ';', 3, 0, 0x0402 _ 0) +NAMED_CHARACTER_REFERENCE(78, /* D S */ 'c' _ 'y' _ ';', 3, 0, 0x0405 _ 0) +NAMED_CHARACTER_REFERENCE(79, /* D Z */ 'c' _ 'y' _ ';', 3, 0, 0x040f _ 0) +NAMED_CHARACTER_REFERENCE(80, + /* D a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0, + 0x2021 _ 0) +NAMED_CHARACTER_REFERENCE(81, /* D a */ 'r' _ 'r' _ ';', 3, 0, 0x21a1 _ 0) +NAMED_CHARACTER_REFERENCE(82, /* D a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x2ae4 _ 0) +NAMED_CHARACTER_REFERENCE(83, + /* D c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x010e _ 0) +NAMED_CHARACTER_REFERENCE(84, /* D c */ 'y' _ ';', 2, 0, 0x0414 _ 0) +NAMED_CHARACTER_REFERENCE(85, /* D e */ 'l' _ ';', 2, 0, 0x2207 _ 0) +NAMED_CHARACTER_REFERENCE(86, /* D e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x0394 _ 0) +NAMED_CHARACTER_REFERENCE(87, /* D f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd07) +NAMED_CHARACTER_REFERENCE( + 88, + /* D i */ + 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', + 15, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE( + 89, + /* D i */ + 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 't' _ ';', + 13, 0, 0x02d9 _ 0) +NAMED_CHARACTER_REFERENCE( + 90, + /* D i */ + 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', + 21, 0, 0x02dd _ 0) +NAMED_CHARACTER_REFERENCE( + 91, + /* D i */ + 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'G' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', + 15, 0, 0x0060 _ 0) +NAMED_CHARACTER_REFERENCE( + 92, + /* D i */ + 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', + 15, 0, 0x02dc _ 0) +NAMED_CHARACTER_REFERENCE(93, + /* D i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0, + 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE( + 94, + /* D i */ + 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 12, + 0, 0x2146 _ 0) +NAMED_CHARACTER_REFERENCE(95, /* D o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3b) +NAMED_CHARACTER_REFERENCE(96, /* D o */ 't' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(97, + /* D o */ 't' _ 'D' _ 'o' _ 't' _ ';', 5, 0, + 0x20dc _ 0) +NAMED_CHARACTER_REFERENCE(98, + /* D o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, + 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE( + 99, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', + 20, 0, 0x222f _ 0) +NAMED_CHARACTER_REFERENCE( + 100, + /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE( + 101, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE( + 102, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE( + 103, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 19, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE( + 104, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 12, + 0, 0x2ae4 _ 0) +NAMED_CHARACTER_REFERENCE( + 105, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 18, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE( + 106, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 23, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE( + 107, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 19, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE( + 108, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 15, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE( + 109, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', + 13, 0, 0x22a8 _ 0) +NAMED_CHARACTER_REFERENCE( + 110, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, + 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE( + 111, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 16, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE( + 112, + /* D o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', + 16, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE( + 113, + /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE( + 114, + /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', + 11, 0, 0x2913 _ 0) +NAMED_CHARACTER_REFERENCE( + 115, + /* D o */ + 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 15, 0, 0x21f5 _ 0) +NAMED_CHARACTER_REFERENCE( + 116, + /* D o */ 'w' _ 'n' _ 'B' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 8, 0, 0x0311 _ 0) +NAMED_CHARACTER_REFERENCE( + 117, + /* D o */ + 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 18, 0, 0x2950 _ 0) +NAMED_CHARACTER_REFERENCE( + 118, + /* D o */ + 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 16, 0, 0x295e _ 0) +NAMED_CHARACTER_REFERENCE( + 119, + /* D o */ + 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 13, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE( + 120, + /* D o */ + 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', + 16, 0, 0x2956 _ 0) +NAMED_CHARACTER_REFERENCE( + 121, + /* D o */ + 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 17, 0, 0x295f _ 0) +NAMED_CHARACTER_REFERENCE( + 122, + /* D o */ + 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 14, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE( + 123, + /* D o */ + 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', + 17, 0, 0x2957 _ 0) +NAMED_CHARACTER_REFERENCE(124, + /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ ';', 6, 0, + 0x22a4 _ 0) +NAMED_CHARACTER_REFERENCE( + 125, + /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 11, 0, 0x21a7 _ 0) +NAMED_CHARACTER_REFERENCE( + 126, + /* D o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(127, /* D s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9f) +NAMED_CHARACTER_REFERENCE(128, + /* D s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0110 _ 0) +NAMED_CHARACTER_REFERENCE(129, /* E N */ 'G' _ ';', 2, 0, 0x014a _ 0) +NAMED_CHARACTER_REFERENCE(130, /* E T */ 'H', 1, 0, 0x00d0 _ 0) +NAMED_CHARACTER_REFERENCE(131, /* E T */ 'H' _ ';', 2, 0, 0x00d0 _ 0) +NAMED_CHARACTER_REFERENCE(132, + /* E a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c9 _ 0) +NAMED_CHARACTER_REFERENCE(133, + /* E a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00c9 _ 0) +NAMED_CHARACTER_REFERENCE(134, + /* E c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x011a _ 0) +NAMED_CHARACTER_REFERENCE(135, /* E c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ca _ 0) +NAMED_CHARACTER_REFERENCE(136, + /* E c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ca _ 0) +NAMED_CHARACTER_REFERENCE(137, /* E c */ 'y' _ ';', 2, 0, 0x042d _ 0) +NAMED_CHARACTER_REFERENCE(138, /* E d */ 'o' _ 't' _ ';', 3, 0, 0x0116 _ 0) +NAMED_CHARACTER_REFERENCE(139, /* E f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd08) +NAMED_CHARACTER_REFERENCE(140, + /* E g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c8 _ 0) +NAMED_CHARACTER_REFERENCE(141, + /* E g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00c8 _ 0) +NAMED_CHARACTER_REFERENCE(142, + /* E l */ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 6, 0, + 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(143, + /* E m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0112 _ 0) +NAMED_CHARACTER_REFERENCE( + 144, + /* E m */ + 'p' _ 't' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', + 15, 0, 0x25fb _ 0) +NAMED_CHARACTER_REFERENCE( + 145, + /* E m */ + 'p' _ 't' _ 'y' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', + 19, 0, 0x25ab _ 0) +NAMED_CHARACTER_REFERENCE(146, + /* E o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0118 _ 0) +NAMED_CHARACTER_REFERENCE(147, /* E o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3c) +NAMED_CHARACTER_REFERENCE(148, + /* E p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, + 0x0395 _ 0) +NAMED_CHARACTER_REFERENCE(149, + /* E q */ 'u' _ 'a' _ 'l' _ ';', 4, 0, 0x2a75 _ 0) +NAMED_CHARACTER_REFERENCE( + 150, + /* E q */ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0, + 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE( + 151, + /* E q */ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 10, 0, + 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(152, /* E s */ 'c' _ 'r' _ ';', 3, 0, 0x2130 _ 0) +NAMED_CHARACTER_REFERENCE(153, /* E s */ 'i' _ 'm' _ ';', 3, 0, 0x2a73 _ 0) +NAMED_CHARACTER_REFERENCE(154, /* E t */ 'a' _ ';', 2, 0, 0x0397 _ 0) +NAMED_CHARACTER_REFERENCE(155, /* E u */ 'm' _ 'l', 2, 0, 0x00cb _ 0) +NAMED_CHARACTER_REFERENCE(156, /* E u */ 'm' _ 'l' _ ';', 3, 0, 0x00cb _ 0) +NAMED_CHARACTER_REFERENCE(157, + /* E x */ 'i' _ 's' _ 't' _ 's' _ ';', 5, 0, + 0x2203 _ 0) +NAMED_CHARACTER_REFERENCE( + 158, + /* E x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'E' _ ';', + 11, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(159, /* F c */ 'y' _ ';', 2, 0, 0x0424 _ 0) +NAMED_CHARACTER_REFERENCE(160, /* F f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd09) +NAMED_CHARACTER_REFERENCE( + 161, + /* F i */ + 'l' _ 'l' _ 'e' _ 'd' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', + 16, 0, 0x25fc _ 0) +NAMED_CHARACTER_REFERENCE( + 162, + /* F i */ + 'l' _ 'l' _ 'e' _ 'd' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', + 20, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(163, /* F o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3d) +NAMED_CHARACTER_REFERENCE(164, + /* F o */ 'r' _ 'A' _ 'l' _ 'l' _ ';', 5, 0, + 0x2200 _ 0) +NAMED_CHARACTER_REFERENCE( + 165, + /* F o */ 'u' _ 'r' _ 'i' _ 'e' _ 'r' _ 't' _ 'r' _ 'f' _ ';', 9, 0, + 0x2131 _ 0) +NAMED_CHARACTER_REFERENCE(166, /* F s */ 'c' _ 'r' _ ';', 3, 0, 0x2131 _ 0) +NAMED_CHARACTER_REFERENCE(167, /* G J */ 'c' _ 'y' _ ';', 3, 0, 0x0403 _ 0) +NAMED_CHARACTER_REFERENCE(168, /* G T */ 0, 0, 1, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(169, /* G T */ ';', 1, 0, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(170, + /* G a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x0393 _ 0) +NAMED_CHARACTER_REFERENCE(171, + /* G a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0, + 0x03dc _ 0) +NAMED_CHARACTER_REFERENCE(172, + /* G b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, + 0x011e _ 0) +NAMED_CHARACTER_REFERENCE(173, + /* G c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0122 _ 0) +NAMED_CHARACTER_REFERENCE(174, + /* G c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011c _ 0) +NAMED_CHARACTER_REFERENCE(175, /* G c */ 'y' _ ';', 2, 0, 0x0413 _ 0) +NAMED_CHARACTER_REFERENCE(176, /* G d */ 'o' _ 't' _ ';', 3, 0, 0x0120 _ 0) +NAMED_CHARACTER_REFERENCE(177, /* G f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0a) +NAMED_CHARACTER_REFERENCE(178, /* G g */ ';', 1, 0, 0x22d9 _ 0) +NAMED_CHARACTER_REFERENCE(179, /* G o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3e) +NAMED_CHARACTER_REFERENCE( + 180, + /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 11, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE( + 181, + /* G r */ + 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'L' _ 'e' _ 's' _ 's' _ ';', + 15, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE( + 182, + /* G r */ + 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 15, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE( + 183, + /* G r */ + 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', + 13, 0, 0x2aa2 _ 0) +NAMED_CHARACTER_REFERENCE( + 184, + /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0, + 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE( + 185, + /* G r */ + 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 16, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE( + 186, + /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', + 11, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(187, /* G s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca2) +NAMED_CHARACTER_REFERENCE(188, /* G t */ ';', 1, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(189, + /* H A */ 'R' _ 'D' _ 'c' _ 'y' _ ';', 5, 0, + 0x042a _ 0) +NAMED_CHARACTER_REFERENCE(190, + /* H a */ 'c' _ 'e' _ 'k' _ ';', 4, 0, 0x02c7 _ 0) +NAMED_CHARACTER_REFERENCE(191, /* H a */ 't' _ ';', 2, 0, 0x005e _ 0) +NAMED_CHARACTER_REFERENCE(192, + /* H c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0124 _ 0) +NAMED_CHARACTER_REFERENCE(193, /* H f */ 'r' _ ';', 2, 0, 0x210c _ 0) +NAMED_CHARACTER_REFERENCE( + 194, + /* H i */ 'l' _ 'b' _ 'e' _ 'r' _ 't' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', + 11, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(195, /* H o */ 'p' _ 'f' _ ';', 3, 0, 0x210d _ 0) +NAMED_CHARACTER_REFERENCE( + 196, + /* H o */ + 'r' _ 'i' _ 'z' _ 'o' _ 'n' _ 't' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', + 13, 0, 0x2500 _ 0) +NAMED_CHARACTER_REFERENCE(197, /* H s */ 'c' _ 'r' _ ';', 3, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(198, + /* H s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0126 _ 0) +NAMED_CHARACTER_REFERENCE( + 199, + /* H u */ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';', + 11, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE( + 200, + /* H u */ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 8, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(201, /* I E */ 'c' _ 'y' _ ';', 3, 0, 0x0415 _ 0) +NAMED_CHARACTER_REFERENCE(202, + /* I J */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0132 _ 0) +NAMED_CHARACTER_REFERENCE(203, /* I O */ 'c' _ 'y' _ ';', 3, 0, 0x0401 _ 0) +NAMED_CHARACTER_REFERENCE(204, + /* I a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00cd _ 0) +NAMED_CHARACTER_REFERENCE(205, + /* I a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00cd _ 0) +NAMED_CHARACTER_REFERENCE(206, /* I c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ce _ 0) +NAMED_CHARACTER_REFERENCE(207, + /* I c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ce _ 0) +NAMED_CHARACTER_REFERENCE(208, /* I c */ 'y' _ ';', 2, 0, 0x0418 _ 0) +NAMED_CHARACTER_REFERENCE(209, /* I d */ 'o' _ 't' _ ';', 3, 0, 0x0130 _ 0) +NAMED_CHARACTER_REFERENCE(210, /* I f */ 'r' _ ';', 2, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(211, + /* I g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00cc _ 0) +NAMED_CHARACTER_REFERENCE(212, + /* I g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00cc _ 0) +NAMED_CHARACTER_REFERENCE(213, /* I m */ ';', 1, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(214, + /* I m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012a _ 0) +NAMED_CHARACTER_REFERENCE( + 215, + /* I m */ 'a' _ 'g' _ 'i' _ 'n' _ 'a' _ 'r' _ 'y' _ 'I' _ ';', 9, 0, + 0x2148 _ 0) +NAMED_CHARACTER_REFERENCE(216, + /* I m */ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 6, 0, + 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(217, /* I n */ 't' _ ';', 2, 0, 0x222c _ 0) +NAMED_CHARACTER_REFERENCE(218, + /* I n */ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 7, + 0, 0x222b _ 0) +NAMED_CHARACTER_REFERENCE( + 219, + /* I n */ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', + 11, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE( + 220, + /* I n */ + 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', + 13, 0, 0x2063 _ 0) +NAMED_CHARACTER_REFERENCE( + 221, + /* I n */ + 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', + 13, 0, 0x2062 _ 0) +NAMED_CHARACTER_REFERENCE(222, + /* I o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012e _ 0) +NAMED_CHARACTER_REFERENCE(223, /* I o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd40) +NAMED_CHARACTER_REFERENCE(224, /* I o */ 't' _ 'a' _ ';', 3, 0, 0x0399 _ 0) +NAMED_CHARACTER_REFERENCE(225, /* I s */ 'c' _ 'r' _ ';', 3, 0, 0x2110 _ 0) +NAMED_CHARACTER_REFERENCE(226, + /* I t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x0128 _ 0) +NAMED_CHARACTER_REFERENCE(227, + /* I u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0406 _ 0) +NAMED_CHARACTER_REFERENCE(228, /* I u */ 'm' _ 'l', 2, 0, 0x00cf _ 0) +NAMED_CHARACTER_REFERENCE(229, /* I u */ 'm' _ 'l' _ ';', 3, 0, 0x00cf _ 0) +NAMED_CHARACTER_REFERENCE(230, + /* J c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0134 _ 0) +NAMED_CHARACTER_REFERENCE(231, /* J c */ 'y' _ ';', 2, 0, 0x0419 _ 0) +NAMED_CHARACTER_REFERENCE(232, /* J f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0d) +NAMED_CHARACTER_REFERENCE(233, /* J o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd41) +NAMED_CHARACTER_REFERENCE(234, /* J s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca5) +NAMED_CHARACTER_REFERENCE(235, + /* J s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0, + 0x0408 _ 0) +NAMED_CHARACTER_REFERENCE(236, + /* J u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0404 _ 0) +NAMED_CHARACTER_REFERENCE(237, /* K H */ 'c' _ 'y' _ ';', 3, 0, 0x0425 _ 0) +NAMED_CHARACTER_REFERENCE(238, /* K J */ 'c' _ 'y' _ ';', 3, 0, 0x040c _ 0) +NAMED_CHARACTER_REFERENCE(239, + /* K a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x039a _ 0) +NAMED_CHARACTER_REFERENCE(240, + /* K c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0136 _ 0) +NAMED_CHARACTER_REFERENCE(241, /* K c */ 'y' _ ';', 2, 0, 0x041a _ 0) +NAMED_CHARACTER_REFERENCE(242, /* K f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0e) +NAMED_CHARACTER_REFERENCE(243, /* K o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd42) +NAMED_CHARACTER_REFERENCE(244, /* K s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca6) +NAMED_CHARACTER_REFERENCE(245, /* L J */ 'c' _ 'y' _ ';', 3, 0, 0x0409 _ 0) +NAMED_CHARACTER_REFERENCE(246, /* L T */ 0, 0, 1, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(247, /* L T */ ';', 1, 0, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(248, + /* L a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0139 _ 0) +NAMED_CHARACTER_REFERENCE(249, + /* L a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0, + 0x039b _ 0) +NAMED_CHARACTER_REFERENCE(250, /* L a */ 'n' _ 'g' _ ';', 3, 0, 0x27ea _ 0) +NAMED_CHARACTER_REFERENCE( + 251, + /* L a */ 'p' _ 'l' _ 'a' _ 'c' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 9, 0, + 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(252, /* L a */ 'r' _ 'r' _ ';', 3, 0, 0x219e _ 0) +NAMED_CHARACTER_REFERENCE(253, + /* L c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x013d _ 0) +NAMED_CHARACTER_REFERENCE(254, + /* L c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x013b _ 0) +NAMED_CHARACTER_REFERENCE(255, /* L c */ 'y' _ ';', 2, 0, 0x041b _ 0) +NAMED_CHARACTER_REFERENCE( + 256, + /* L e */ + 'f' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', + 15, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE( + 257, + /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE( + 258, + /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', + 11, 0, 0x21e4 _ 0) +NAMED_CHARACTER_REFERENCE( + 259, + /* L e */ + 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 18, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE( + 260, + /* L e */ 'f' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 10, 0, + 0x2308 _ 0) +NAMED_CHARACTER_REFERENCE( + 261, + /* L e */ + 'f' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', + 16, 0, 0x27e6 _ 0) +NAMED_CHARACTER_REFERENCE( + 262, + /* L e */ + 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 16, 0, 0x2961 _ 0) +NAMED_CHARACTER_REFERENCE( + 263, + /* L e */ + 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 13, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE( + 264, + /* L e */ + 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', + 16, 0, 0x2959 _ 0) +NAMED_CHARACTER_REFERENCE( + 265, + /* L e */ 'f' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 8, 0, 0x230a _ 0) +NAMED_CHARACTER_REFERENCE( + 266, + /* L e */ + 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE( + 267, + /* L e */ + 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 14, 0, 0x294e _ 0) +NAMED_CHARACTER_REFERENCE(268, + /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 6, 0, + 0x22a3 _ 0) +NAMED_CHARACTER_REFERENCE( + 269, + /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 11, 0, 0x21a4 _ 0) +NAMED_CHARACTER_REFERENCE( + 270, + /* L e */ + 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, + 0, 0x295a _ 0) +NAMED_CHARACTER_REFERENCE( + 271, + /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', + 11, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE( + 272, + /* L e */ + 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', + 14, 0, 0x29cf _ 0) +NAMED_CHARACTER_REFERENCE( + 273, + /* L e */ + 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 16, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE( + 274, + /* L e */ + 'f' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 15, 0, 0x2951 _ 0) +NAMED_CHARACTER_REFERENCE( + 275, + /* L e */ + 'f' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 14, 0, 0x2960 _ 0) +NAMED_CHARACTER_REFERENCE( + 276, + /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 11, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE( + 277, + /* L e */ + 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', + 14, 0, 0x2958 _ 0) +NAMED_CHARACTER_REFERENCE( + 278, + /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 9, 0, + 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE( + 279, + /* L e */ + 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 12, + 0, 0x2952 _ 0) +NAMED_CHARACTER_REFERENCE( + 280, + /* L e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE( + 281, + /* L e */ + 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE( + 282, + /* L e */ + 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', + 15, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE( + 283, + /* L e */ + 's' _ 's' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, + 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE( + 284, + /* L e */ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 10, 0, + 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(285, + /* L e */ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 7, + 0, 0x2aa1 _ 0) +NAMED_CHARACTER_REFERENCE( + 286, + /* L e */ + 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 13, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE( + 287, + /* L e */ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 8, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(288, /* L f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0f) +NAMED_CHARACTER_REFERENCE(289, /* L l */ ';', 1, 0, 0x22d8 _ 0) +NAMED_CHARACTER_REFERENCE( + 290, + /* L l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, + 0x21da _ 0) +NAMED_CHARACTER_REFERENCE(291, + /* L m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x013f _ 0) +NAMED_CHARACTER_REFERENCE( + 292, + /* L o */ + 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, + 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE( + 293, + /* L o */ + 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 17, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE( + 294, + /* L o */ + 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE( + 295, + /* L o */ + 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, + 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE( + 296, + /* L o */ + 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 17, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE( + 297, + /* L o */ + 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(298, /* L o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd43) +NAMED_CHARACTER_REFERENCE( + 299, + /* L o */ + 'w' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE( + 300, + /* L o */ + 'w' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(301, /* L s */ 'c' _ 'r' _ ';', 3, 0, 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(302, /* L s */ 'h' _ ';', 2, 0, 0x21b0 _ 0) +NAMED_CHARACTER_REFERENCE(303, + /* L s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0141 _ 0) +NAMED_CHARACTER_REFERENCE(304, /* L t */ ';', 1, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(305, /* M a */ 'p' _ ';', 2, 0, 0x2905 _ 0) +NAMED_CHARACTER_REFERENCE(306, /* M c */ 'y' _ ';', 2, 0, 0x041c _ 0) +NAMED_CHARACTER_REFERENCE( + 307, + /* M e */ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 10, 0, + 0x205f _ 0) +NAMED_CHARACTER_REFERENCE( + 308, + /* M e */ 'l' _ 'l' _ 'i' _ 'n' _ 't' _ 'r' _ 'f' _ ';', 8, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(309, /* M f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd10) +NAMED_CHARACTER_REFERENCE( + 310, + /* M i */ 'n' _ 'u' _ 's' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(311, /* M o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd44) +NAMED_CHARACTER_REFERENCE(312, /* M s */ 'c' _ 'r' _ ';', 3, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(313, /* M u */ ';', 1, 0, 0x039c _ 0) +NAMED_CHARACTER_REFERENCE(314, /* N J */ 'c' _ 'y' _ ';', 3, 0, 0x040a _ 0) +NAMED_CHARACTER_REFERENCE(315, + /* N a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0143 _ 0) +NAMED_CHARACTER_REFERENCE(316, + /* N c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0147 _ 0) +NAMED_CHARACTER_REFERENCE(317, + /* N c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0145 _ 0) +NAMED_CHARACTER_REFERENCE(318, /* N c */ 'y' _ ';', 2, 0, 0x041d _ 0) +NAMED_CHARACTER_REFERENCE( + 319, + /* N e */ + 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'M' _ 'e' _ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', + 18, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE( + 320, + /* N e */ + 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', + 17, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE( + 321, + /* N e */ + 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', + 16, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE( + 322, + /* N e */ + 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'V' _ 'e' _ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', + 20, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE( + 323, + /* N e */ + 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', + 19, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE( + 324, + /* N e */ + 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', + 13, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(325, + /* N e */ 'w' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 6, 0, + 0x000a _ 0) +NAMED_CHARACTER_REFERENCE(326, /* N f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd11) +NAMED_CHARACTER_REFERENCE(327, + /* N o */ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ ';', 6, 0, + 0x2060 _ 0) +NAMED_CHARACTER_REFERENCE( + 328, + /* N o */ + 'n' _ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ 'i' _ 'n' _ 'g' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', + 15, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(329, /* N o */ 'p' _ 'f' _ ';', 3, 0, 0x2115 _ 0) +NAMED_CHARACTER_REFERENCE(330, /* N o */ 't' _ ';', 2, 0, 0x2aec _ 0) +NAMED_CHARACTER_REFERENCE( + 331, + /* N o */ 't' _ 'C' _ 'o' _ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', + 11, 0, 0x2262 _ 0) +NAMED_CHARACTER_REFERENCE( + 332, + /* N o */ 't' _ 'C' _ 'u' _ 'p' _ 'C' _ 'a' _ 'p' _ ';', 8, 0, 0x226d _ 0) +NAMED_CHARACTER_REFERENCE( + 333, + /* N o */ + 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', + 19, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE( + 334, + /* N o */ 't' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0, + 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(335, + /* N o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, + 0, 0x2260 _ 0) +NAMED_CHARACTER_REFERENCE( + 336, + /* N o */ + 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, + 0, 0x2242 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 337, + /* N o */ 't' _ 'E' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0, 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE( + 338, + /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 9, 0, + 0x226f _ 0) +NAMED_CHARACTER_REFERENCE( + 339, + /* N o */ + 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 14, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE( + 340, + /* N o */ + 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 18, 0, 0x2267 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 341, + /* N o */ + 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', + 16, 0, 0x226b _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 342, + /* N o */ + 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', + 13, 0, 0x2279 _ 0) +NAMED_CHARACTER_REFERENCE( + 343, + /* N o */ + 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 19, 0, 0x2a7e _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 344, + /* N o */ + 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', + 14, 0, 0x2275 _ 0) +NAMED_CHARACTER_REFERENCE( + 345, + /* N o */ + 't' _ 'H' _ 'u' _ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';', + 14, 0, 0x224e _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 346, + /* N o */ 't' _ 'H' _ 'u' _ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 11, 0, 0x224f _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 347, + /* N o */ + 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', + 14, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE( + 348, + /* N o */ + 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', + 17, 0, 0x29cf _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 349, + /* N o */ + 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 19, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(350, + /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ ';', 6, 0, + 0x226e _ 0) +NAMED_CHARACTER_REFERENCE( + 351, + /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 11, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE( + 352, + /* N o */ + 't' _ 'L' _ 'e' _ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', + 13, 0, 0x2278 _ 0) +NAMED_CHARACTER_REFERENCE( + 353, + /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0, + 0x226a _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 354, + /* N o */ + 't' _ 'L' _ 'e' _ 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 16, 0, 0x2a7d _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 355, + /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', + 11, 0, 0x2274 _ 0) +NAMED_CHARACTER_REFERENCE( + 356, + /* N o */ + 't' _ 'N' _ 'e' _ 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', + 22, 0, 0x2aa2 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 357, + /* N o */ + 't' _ 'N' _ 'e' _ 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', + 16, 0, 0x2aa1 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 358, + /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 10, 0, + 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE( + 359, + /* N o */ + 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 15, 0, 0x2aaf _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 360, + /* N o */ + 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 20, 0, 0x22e0 _ 0) +NAMED_CHARACTER_REFERENCE( + 361, + /* N o */ + 't' _ 'R' _ 'e' _ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', + 16, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE( + 362, + /* N o */ + 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', + 15, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE( + 363, + /* N o */ + 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', + 18, 0, 0x29d0 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 364, + /* N o */ + 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 20, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE( + 365, + /* N o */ + 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', + 14, 0, 0x228f _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 366, + /* N o */ + 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 19, 0, 0x22e2 _ 0) +NAMED_CHARACTER_REFERENCE( + 367, + /* N o */ + 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', + 16, 0, 0x2290 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 368, + /* N o */ + 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 21, 0, 0x22e3 _ 0) +NAMED_CHARACTER_REFERENCE( + 369, + /* N o */ 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 8, 0, + 0x2282 _ 0x20d2) +NAMED_CHARACTER_REFERENCE( + 370, + /* N o */ + 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 13, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE( + 371, + /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 10, 0, + 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE( + 372, + /* N o */ + 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 15, 0, 0x2ab0 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 373, + /* N o */ + 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 20, 0, 0x22e1 _ 0) +NAMED_CHARACTER_REFERENCE( + 374, + /* N o */ + 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', + 15, 0, 0x227f _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 375, + /* N o */ 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 10, 0, + 0x2283 _ 0x20d2) +NAMED_CHARACTER_REFERENCE( + 376, + /* N o */ + 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 15, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(377, + /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, + 0, 0x2241 _ 0) +NAMED_CHARACTER_REFERENCE( + 378, + /* N o */ + 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, + 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE( + 379, + /* N o */ + 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 16, 0, 0x2247 _ 0) +NAMED_CHARACTER_REFERENCE( + 380, + /* N o */ + 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, + 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE( + 381, + /* N o */ + 't' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', + 13, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(382, /* N s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca9) +NAMED_CHARACTER_REFERENCE(383, + /* N t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d1 _ 0) +NAMED_CHARACTER_REFERENCE(384, + /* N t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x00d1 _ 0) +NAMED_CHARACTER_REFERENCE(385, /* N u */ ';', 1, 0, 0x039d _ 0) +NAMED_CHARACTER_REFERENCE(386, + /* O E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0152 _ 0) +NAMED_CHARACTER_REFERENCE(387, + /* O a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00d3 _ 0) +NAMED_CHARACTER_REFERENCE(388, + /* O a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00d3 _ 0) +NAMED_CHARACTER_REFERENCE(389, /* O c */ 'i' _ 'r' _ 'c', 3, 0, 0x00d4 _ 0) +NAMED_CHARACTER_REFERENCE(390, + /* O c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00d4 _ 0) +NAMED_CHARACTER_REFERENCE(391, /* O c */ 'y' _ ';', 2, 0, 0x041e _ 0) +NAMED_CHARACTER_REFERENCE(392, + /* O d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, + 0x0150 _ 0) +NAMED_CHARACTER_REFERENCE(393, /* O f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd12) +NAMED_CHARACTER_REFERENCE(394, + /* O g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d2 _ 0) +NAMED_CHARACTER_REFERENCE(395, + /* O g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00d2 _ 0) +NAMED_CHARACTER_REFERENCE(396, + /* O m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014c _ 0) +NAMED_CHARACTER_REFERENCE(397, + /* O m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03a9 _ 0) +NAMED_CHARACTER_REFERENCE(398, + /* O m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0, + 0x039f _ 0) +NAMED_CHARACTER_REFERENCE(399, /* O o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd46) +NAMED_CHARACTER_REFERENCE( + 400, + /* O p */ + 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', + 19, 0, 0x201c _ 0) +NAMED_CHARACTER_REFERENCE( + 401, + /* O p */ + 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', + 13, 0, 0x2018 _ 0) +NAMED_CHARACTER_REFERENCE(402, /* O r */ ';', 1, 0, 0x2a54 _ 0) +NAMED_CHARACTER_REFERENCE(403, /* O s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaa) +NAMED_CHARACTER_REFERENCE(404, + /* O s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00d8 _ 0) +NAMED_CHARACTER_REFERENCE(405, + /* O s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x00d8 _ 0) +NAMED_CHARACTER_REFERENCE(406, + /* O t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d5 _ 0) +NAMED_CHARACTER_REFERENCE(407, + /* O t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x00d5 _ 0) +NAMED_CHARACTER_REFERENCE(408, + /* O t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, + 0x2a37 _ 0) +NAMED_CHARACTER_REFERENCE(409, /* O u */ 'm' _ 'l', 2, 0, 0x00d6 _ 0) +NAMED_CHARACTER_REFERENCE(410, /* O u */ 'm' _ 'l' _ ';', 3, 0, 0x00d6 _ 0) +NAMED_CHARACTER_REFERENCE(411, + /* O v */ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 6, 0, + 0x203e _ 0) +NAMED_CHARACTER_REFERENCE( + 412, + /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x23de _ 0) +NAMED_CHARACTER_REFERENCE( + 413, + /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 10, 0, + 0x23b4 _ 0) +NAMED_CHARACTER_REFERENCE( + 414, + /* O v */ + 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', + 14, 0, 0x23dc _ 0) +NAMED_CHARACTER_REFERENCE(415, + /* P a */ 'r' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 7, + 0, 0x2202 _ 0) +NAMED_CHARACTER_REFERENCE(416, /* P c */ 'y' _ ';', 2, 0, 0x041f _ 0) +NAMED_CHARACTER_REFERENCE(417, /* P f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd13) +NAMED_CHARACTER_REFERENCE(418, /* P h */ 'i' _ ';', 2, 0, 0x03a6 _ 0) +NAMED_CHARACTER_REFERENCE(419, /* P i */ ';', 1, 0, 0x03a0 _ 0) +NAMED_CHARACTER_REFERENCE( + 420, + /* P l */ 'u' _ 's' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 8, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE( + 421, + /* P o */ + 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ 'p' _ 'l' _ 'a' _ 'n' _ 'e' _ ';', 12, + 0, 0x210c _ 0) +NAMED_CHARACTER_REFERENCE(422, /* P o */ 'p' _ 'f' _ ';', 3, 0, 0x2119 _ 0) +NAMED_CHARACTER_REFERENCE(423, /* P r */ ';', 1, 0, 0x2abb _ 0) +NAMED_CHARACTER_REFERENCE(424, + /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 7, + 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE( + 425, + /* P r */ + 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, + 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE( + 426, + /* P r */ + 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 17, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE( + 427, + /* P r */ + 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, + 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(428, + /* P r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2033 _ 0) +NAMED_CHARACTER_REFERENCE(429, + /* P r */ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 6, 0, + 0x220f _ 0) +NAMED_CHARACTER_REFERENCE( + 430, + /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 9, 0, + 0x2237 _ 0) +NAMED_CHARACTER_REFERENCE( + 431, + /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ ';', + 11, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(432, /* P s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcab) +NAMED_CHARACTER_REFERENCE(433, /* P s */ 'i' _ ';', 2, 0, 0x03a8 _ 0) +NAMED_CHARACTER_REFERENCE(434, /* Q U */ 'O' _ 'T', 2, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(435, /* Q U */ 'O' _ 'T' _ ';', 3, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(436, /* Q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd14) +NAMED_CHARACTER_REFERENCE(437, /* Q o */ 'p' _ 'f' _ ';', 3, 0, 0x211a _ 0) +NAMED_CHARACTER_REFERENCE(438, /* Q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcac) +NAMED_CHARACTER_REFERENCE(439, + /* R B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2910 _ 0) +NAMED_CHARACTER_REFERENCE(440, /* R E */ 'G', 1, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(441, /* R E */ 'G' _ ';', 2, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(442, + /* R a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0154 _ 0) +NAMED_CHARACTER_REFERENCE(443, /* R a */ 'n' _ 'g' _ ';', 3, 0, 0x27eb _ 0) +NAMED_CHARACTER_REFERENCE(444, /* R a */ 'r' _ 'r' _ ';', 3, 0, 0x21a0 _ 0) +NAMED_CHARACTER_REFERENCE(445, + /* R a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, + 0x2916 _ 0) +NAMED_CHARACTER_REFERENCE(446, + /* R c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0158 _ 0) +NAMED_CHARACTER_REFERENCE(447, + /* R c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0156 _ 0) +NAMED_CHARACTER_REFERENCE(448, /* R c */ 'y' _ ';', 2, 0, 0x0420 _ 0) +NAMED_CHARACTER_REFERENCE(449, /* R e */ ';', 1, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE( + 450, + /* R e */ + 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', + 13, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE( + 451, + /* R e */ + 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', + 17, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE( + 452, + /* R e */ + 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'U' _ 'p' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', + 19, 0, 0x296f _ 0) +NAMED_CHARACTER_REFERENCE(453, /* R f */ 'r' _ ';', 2, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(454, /* R h */ 'o' _ ';', 2, 0, 0x03a1 _ 0) +NAMED_CHARACTER_REFERENCE( + 455, + /* R i */ + 'g' _ 'h' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', + 16, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE( + 456, + /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, + 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE( + 457, + /* R i */ + 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 12, + 0, 0x21e5 _ 0) +NAMED_CHARACTER_REFERENCE( + 458, + /* R i */ + 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 18, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE( + 459, + /* R i */ 'g' _ 'h' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', + 11, 0, 0x2309 _ 0) +NAMED_CHARACTER_REFERENCE( + 460, + /* R i */ + 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', + 17, 0, 0x27e7 _ 0) +NAMED_CHARACTER_REFERENCE( + 461, + /* R i */ + 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 17, 0, 0x295d _ 0) +NAMED_CHARACTER_REFERENCE( + 462, + /* R i */ + 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 14, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE( + 463, + /* R i */ + 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', + 17, 0, 0x2955 _ 0) +NAMED_CHARACTER_REFERENCE( + 464, + /* R i */ 'g' _ 'h' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 9, 0, + 0x230b _ 0) +NAMED_CHARACTER_REFERENCE(465, + /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 7, + 0, 0x22a2 _ 0) +NAMED_CHARACTER_REFERENCE( + 466, + /* R i */ + 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, + 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE( + 467, + /* R i */ + 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 13, 0, 0x295b _ 0) +NAMED_CHARACTER_REFERENCE( + 468, + /* R i */ + 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, + 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE( + 469, + /* R i */ + 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', + 15, 0, 0x29d0 _ 0) +NAMED_CHARACTER_REFERENCE( + 470, + /* R i */ + 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 17, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE( + 471, + /* R i */ + 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 16, 0, 0x294f _ 0) +NAMED_CHARACTER_REFERENCE( + 472, + /* R i */ + 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', + 15, 0, 0x295c _ 0) +NAMED_CHARACTER_REFERENCE( + 473, + /* R i */ + 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, + 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE( + 474, + /* R i */ + 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', + 15, 0, 0x2954 _ 0) +NAMED_CHARACTER_REFERENCE( + 475, + /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 10, 0, + 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE( + 476, + /* R i */ + 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', + 13, 0, 0x2953 _ 0) +NAMED_CHARACTER_REFERENCE( + 477, + /* R i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, + 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(478, /* R o */ 'p' _ 'f' _ ';', 3, 0, 0x211d _ 0) +NAMED_CHARACTER_REFERENCE( + 479, + /* R o */ 'u' _ 'n' _ 'd' _ 'I' _ 'm' _ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', + 11, 0, 0x2970 _ 0) +NAMED_CHARACTER_REFERENCE( + 480, + /* R r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, + 0x21db _ 0) +NAMED_CHARACTER_REFERENCE(481, /* R s */ 'c' _ 'r' _ ';', 3, 0, 0x211b _ 0) +NAMED_CHARACTER_REFERENCE(482, /* R s */ 'h' _ ';', 2, 0, 0x21b1 _ 0) +NAMED_CHARACTER_REFERENCE( + 483, + /* R u */ 'l' _ 'e' _ 'D' _ 'e' _ 'l' _ 'a' _ 'y' _ 'e' _ 'd' _ ';', 10, 0, + 0x29f4 _ 0) +NAMED_CHARACTER_REFERENCE(484, + /* S H */ 'C' _ 'H' _ 'c' _ 'y' _ ';', 5, 0, + 0x0429 _ 0) +NAMED_CHARACTER_REFERENCE(485, /* S H */ 'c' _ 'y' _ ';', 3, 0, 0x0428 _ 0) +NAMED_CHARACTER_REFERENCE(486, + /* S O */ 'F' _ 'T' _ 'c' _ 'y' _ ';', 5, 0, + 0x042c _ 0) +NAMED_CHARACTER_REFERENCE(487, + /* S a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x015a _ 0) +NAMED_CHARACTER_REFERENCE(488, /* S c */ ';', 1, 0, 0x2abc _ 0) +NAMED_CHARACTER_REFERENCE(489, + /* S c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0160 _ 0) +NAMED_CHARACTER_REFERENCE(490, + /* S c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x015e _ 0) +NAMED_CHARACTER_REFERENCE(491, + /* S c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015c _ 0) +NAMED_CHARACTER_REFERENCE(492, /* S c */ 'y' _ ';', 2, 0, 0x0421 _ 0) +NAMED_CHARACTER_REFERENCE(493, /* S f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd16) +NAMED_CHARACTER_REFERENCE( + 494, + /* S h */ + 'o' _ 'r' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE( + 495, + /* S h */ + 'o' _ 'r' _ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE( + 496, + /* S h */ + 'o' _ 'r' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE( + 497, + /* S h */ 'o' _ 'r' _ 't' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 11, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(498, + /* S i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03a3 _ 0) +NAMED_CHARACTER_REFERENCE( + 499, + /* S m */ 'a' _ 'l' _ 'l' _ 'C' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ ';', 10, 0, + 0x2218 _ 0) +NAMED_CHARACTER_REFERENCE(500, /* S o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4a) +NAMED_CHARACTER_REFERENCE(501, /* S q */ 'r' _ 't' _ ';', 3, 0, 0x221a _ 0) +NAMED_CHARACTER_REFERENCE(502, + /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, + 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE( + 503, + /* S q */ + 'u' _ 'a' _ 'r' _ 'e' _ 'I' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', + 17, 0, 0x2293 _ 0) +NAMED_CHARACTER_REFERENCE( + 504, + /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', + 11, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE( + 505, + /* S q */ + 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 16, 0, 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE( + 506, + /* S q */ + 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', + 13, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE( + 507, + /* S q */ + 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 18, 0, 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE( + 508, + /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'U' _ 'n' _ 'i' _ 'o' _ 'n' _ ';', 10, 0, + 0x2294 _ 0) +NAMED_CHARACTER_REFERENCE(509, /* S s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcae) +NAMED_CHARACTER_REFERENCE(510, /* S t */ 'a' _ 'r' _ ';', 3, 0, 0x22c6 _ 0) +NAMED_CHARACTER_REFERENCE(511, /* S u */ 'b' _ ';', 2, 0, 0x22d0 _ 0) +NAMED_CHARACTER_REFERENCE(512, + /* S u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0, + 0x22d0 _ 0) +NAMED_CHARACTER_REFERENCE( + 513, + /* S u */ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 10, 0, + 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(514, + /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 7, + 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE( + 515, + /* S u */ + 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, + 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE( + 516, + /* S u */ + 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 17, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE( + 517, + /* S u */ + 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, + 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(518, + /* S u */ 'c' _ 'h' _ 'T' _ 'h' _ 'a' _ 't' _ ';', 7, + 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(519, /* S u */ 'm' _ ';', 2, 0, 0x2211 _ 0) +NAMED_CHARACTER_REFERENCE(520, /* S u */ 'p' _ ';', 2, 0, 0x22d1 _ 0) +NAMED_CHARACTER_REFERENCE(521, + /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 7, + 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE( + 522, + /* S u */ + 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, + 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(523, + /* S u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0, + 0x22d1 _ 0) +NAMED_CHARACTER_REFERENCE(524, /* T H */ 'O' _ 'R' _ 'N', 3, 0, 0x00de _ 0) +NAMED_CHARACTER_REFERENCE(525, + /* T H */ 'O' _ 'R' _ 'N' _ ';', 4, 0, 0x00de _ 0) +NAMED_CHARACTER_REFERENCE(526, + /* T R */ 'A' _ 'D' _ 'E' _ ';', 4, 0, 0x2122 _ 0) +NAMED_CHARACTER_REFERENCE(527, + /* T S */ 'H' _ 'c' _ 'y' _ ';', 4, 0, 0x040b _ 0) +NAMED_CHARACTER_REFERENCE(528, /* T S */ 'c' _ 'y' _ ';', 3, 0, 0x0426 _ 0) +NAMED_CHARACTER_REFERENCE(529, /* T a */ 'b' _ ';', 2, 0, 0x0009 _ 0) +NAMED_CHARACTER_REFERENCE(530, /* T a */ 'u' _ ';', 2, 0, 0x03a4 _ 0) +NAMED_CHARACTER_REFERENCE(531, + /* T c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0164 _ 0) +NAMED_CHARACTER_REFERENCE(532, + /* T c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0162 _ 0) +NAMED_CHARACTER_REFERENCE(533, /* T c */ 'y' _ ';', 2, 0, 0x0422 _ 0) +NAMED_CHARACTER_REFERENCE(534, /* T f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd17) +NAMED_CHARACTER_REFERENCE( + 535, + /* T h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(536, + /* T h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x0398 _ 0) +NAMED_CHARACTER_REFERENCE( + 537, + /* T h */ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 9, 0, + 0x205f _ 0x200a) +NAMED_CHARACTER_REFERENCE( + 538, + /* T h */ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x2009 _ 0) +NAMED_CHARACTER_REFERENCE(539, + /* T i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE( + 540, + /* T i */ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 9, 0, + 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE( + 541, + /* T i */ + 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', + 13, 0, 0x2245 _ 0) +NAMED_CHARACTER_REFERENCE( + 542, + /* T i */ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0, + 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(543, /* T o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4b) +NAMED_CHARACTER_REFERENCE( + 544, + /* T r */ 'i' _ 'p' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x20db _ 0) +NAMED_CHARACTER_REFERENCE(545, /* T s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaf) +NAMED_CHARACTER_REFERENCE(546, + /* T s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0166 _ 0) +NAMED_CHARACTER_REFERENCE(547, + /* U a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00da _ 0) +NAMED_CHARACTER_REFERENCE(548, + /* U a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00da _ 0) +NAMED_CHARACTER_REFERENCE(549, /* U a */ 'r' _ 'r' _ ';', 3, 0, 0x219f _ 0) +NAMED_CHARACTER_REFERENCE(550, + /* U a */ 'r' _ 'r' _ 'o' _ 'c' _ 'i' _ 'r' _ ';', 7, + 0, 0x2949 _ 0) +NAMED_CHARACTER_REFERENCE(551, + /* U b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x040e _ 0) +NAMED_CHARACTER_REFERENCE(552, + /* U b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, + 0x016c _ 0) +NAMED_CHARACTER_REFERENCE(553, /* U c */ 'i' _ 'r' _ 'c', 3, 0, 0x00db _ 0) +NAMED_CHARACTER_REFERENCE(554, + /* U c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00db _ 0) +NAMED_CHARACTER_REFERENCE(555, /* U c */ 'y' _ ';', 2, 0, 0x0423 _ 0) +NAMED_CHARACTER_REFERENCE(556, + /* U d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, + 0x0170 _ 0) +NAMED_CHARACTER_REFERENCE(557, /* U f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd18) +NAMED_CHARACTER_REFERENCE(558, + /* U g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d9 _ 0) +NAMED_CHARACTER_REFERENCE(559, + /* U g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00d9 _ 0) +NAMED_CHARACTER_REFERENCE(560, + /* U m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016a _ 0) +NAMED_CHARACTER_REFERENCE(561, + /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 7, + 0, 0x005f _ 0) +NAMED_CHARACTER_REFERENCE( + 562, + /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 9, 0, + 0x23df _ 0) +NAMED_CHARACTER_REFERENCE( + 563, + /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', + 11, 0, 0x23b5 _ 0) +NAMED_CHARACTER_REFERENCE( + 564, + /* U n */ + 'd' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', + 15, 0, 0x23dd _ 0) +NAMED_CHARACTER_REFERENCE(565, + /* U n */ 'i' _ 'o' _ 'n' _ ';', 4, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE( + 566, + /* U n */ 'i' _ 'o' _ 'n' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x228e _ 0) +NAMED_CHARACTER_REFERENCE(567, + /* U o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0172 _ 0) +NAMED_CHARACTER_REFERENCE(568, /* U o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4c) +NAMED_CHARACTER_REFERENCE(569, + /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE( + 570, + /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 9, 0, + 0x2912 _ 0) +NAMED_CHARACTER_REFERENCE( + 571, + /* U p */ + 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 15, 0, 0x21c5 _ 0) +NAMED_CHARACTER_REFERENCE( + 572, + /* U p */ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, + 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE( + 573, + /* U p */ + 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 12, + 0, 0x296e _ 0) +NAMED_CHARACTER_REFERENCE(574, + /* U p */ 'T' _ 'e' _ 'e' _ ';', 4, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE( + 575, + /* U p */ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, + 0x21a5 _ 0) +NAMED_CHARACTER_REFERENCE(576, + /* U p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE( + 577, + /* U p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, + 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE( + 578, + /* U p */ + 'p' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE( + 579, + /* U p */ + 'p' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(580, /* U p */ 's' _ 'i' _ ';', 3, 0, 0x03d2 _ 0) +NAMED_CHARACTER_REFERENCE(581, + /* U p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, + 0x03a5 _ 0) +NAMED_CHARACTER_REFERENCE(582, + /* U r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016e _ 0) +NAMED_CHARACTER_REFERENCE(583, /* U s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb0) +NAMED_CHARACTER_REFERENCE(584, + /* U t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x0168 _ 0) +NAMED_CHARACTER_REFERENCE(585, /* U u */ 'm' _ 'l', 2, 0, 0x00dc _ 0) +NAMED_CHARACTER_REFERENCE(586, /* U u */ 'm' _ 'l' _ ';', 3, 0, 0x00dc _ 0) +NAMED_CHARACTER_REFERENCE(587, + /* V D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22ab _ 0) +NAMED_CHARACTER_REFERENCE(588, /* V b */ 'a' _ 'r' _ ';', 3, 0, 0x2aeb _ 0) +NAMED_CHARACTER_REFERENCE(589, /* V c */ 'y' _ ';', 2, 0, 0x0412 _ 0) +NAMED_CHARACTER_REFERENCE(590, + /* V d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a9 _ 0) +NAMED_CHARACTER_REFERENCE(591, + /* V d */ 'a' _ 's' _ 'h' _ 'l' _ ';', 5, 0, + 0x2ae6 _ 0) +NAMED_CHARACTER_REFERENCE(592, /* V e */ 'e' _ ';', 2, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(593, + /* V e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x2016 _ 0) +NAMED_CHARACTER_REFERENCE(594, /* V e */ 'r' _ 't' _ ';', 3, 0, 0x2016 _ 0) +NAMED_CHARACTER_REFERENCE( + 595, + /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 10, 0, + 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE( + 596, + /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', + 11, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE( + 597, + /* V e */ + 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'S' _ 'e' _ 'p' _ 'a' _ 'r' _ 'a' _ 't' _ 'o' _ 'r' _ ';', + 16, 0, 0x2758 _ 0) +NAMED_CHARACTER_REFERENCE( + 598, + /* V e */ + 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, + 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE( + 599, + /* V e */ + 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 12, + 0, 0x200a _ 0) +NAMED_CHARACTER_REFERENCE(600, /* V f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd19) +NAMED_CHARACTER_REFERENCE(601, /* V o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4d) +NAMED_CHARACTER_REFERENCE(602, /* V s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb1) +NAMED_CHARACTER_REFERENCE(603, + /* V v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x22aa _ 0) +NAMED_CHARACTER_REFERENCE(604, + /* W c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0174 _ 0) +NAMED_CHARACTER_REFERENCE(605, + /* W e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(606, /* W f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1a) +NAMED_CHARACTER_REFERENCE(607, /* W o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4e) +NAMED_CHARACTER_REFERENCE(608, /* W s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb2) +NAMED_CHARACTER_REFERENCE(609, /* X f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1b) +NAMED_CHARACTER_REFERENCE(610, /* X i */ ';', 1, 0, 0x039e _ 0) +NAMED_CHARACTER_REFERENCE(611, /* X o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4f) +NAMED_CHARACTER_REFERENCE(612, /* X s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb3) +NAMED_CHARACTER_REFERENCE(613, /* Y A */ 'c' _ 'y' _ ';', 3, 0, 0x042f _ 0) +NAMED_CHARACTER_REFERENCE(614, /* Y I */ 'c' _ 'y' _ ';', 3, 0, 0x0407 _ 0) +NAMED_CHARACTER_REFERENCE(615, /* Y U */ 'c' _ 'y' _ ';', 3, 0, 0x042e _ 0) +NAMED_CHARACTER_REFERENCE(616, + /* Y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00dd _ 0) +NAMED_CHARACTER_REFERENCE(617, + /* Y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00dd _ 0) +NAMED_CHARACTER_REFERENCE(618, + /* Y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0176 _ 0) +NAMED_CHARACTER_REFERENCE(619, /* Y c */ 'y' _ ';', 2, 0, 0x042b _ 0) +NAMED_CHARACTER_REFERENCE(620, /* Y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1c) +NAMED_CHARACTER_REFERENCE(621, /* Y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd50) +NAMED_CHARACTER_REFERENCE(622, /* Y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb4) +NAMED_CHARACTER_REFERENCE(623, /* Y u */ 'm' _ 'l' _ ';', 3, 0, 0x0178 _ 0) +NAMED_CHARACTER_REFERENCE(624, /* Z H */ 'c' _ 'y' _ ';', 3, 0, 0x0416 _ 0) +NAMED_CHARACTER_REFERENCE(625, + /* Z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0179 _ 0) +NAMED_CHARACTER_REFERENCE(626, + /* Z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x017d _ 0) +NAMED_CHARACTER_REFERENCE(627, /* Z c */ 'y' _ ';', 2, 0, 0x0417 _ 0) +NAMED_CHARACTER_REFERENCE(628, /* Z d */ 'o' _ 't' _ ';', 3, 0, 0x017b _ 0) +NAMED_CHARACTER_REFERENCE( + 629, + /* Z e */ + 'r' _ 'o' _ 'W' _ 'i' _ 'd' _ 't' _ 'h' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', + 13, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(630, /* Z e */ 't' _ 'a' _ ';', 3, 0, 0x0396 _ 0) +NAMED_CHARACTER_REFERENCE(631, /* Z f */ 'r' _ ';', 2, 0, 0x2128 _ 0) +NAMED_CHARACTER_REFERENCE(632, /* Z o */ 'p' _ 'f' _ ';', 3, 0, 0x2124 _ 0) +NAMED_CHARACTER_REFERENCE(633, /* Z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb5) +NAMED_CHARACTER_REFERENCE(634, + /* a a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e1 _ 0) +NAMED_CHARACTER_REFERENCE(635, + /* a a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00e1 _ 0) +NAMED_CHARACTER_REFERENCE(636, + /* a b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, + 0x0103 _ 0) +NAMED_CHARACTER_REFERENCE(637, /* a c */ ';', 1, 0, 0x223e _ 0) +NAMED_CHARACTER_REFERENCE(638, /* a c */ 'E' _ ';', 2, 0, 0x223e _ 0x0333) +NAMED_CHARACTER_REFERENCE(639, /* a c */ 'd' _ ';', 2, 0, 0x223f _ 0) +NAMED_CHARACTER_REFERENCE(640, /* a c */ 'i' _ 'r' _ 'c', 3, 0, 0x00e2 _ 0) +NAMED_CHARACTER_REFERENCE(641, + /* a c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00e2 _ 0) +NAMED_CHARACTER_REFERENCE(642, /* a c */ 'u' _ 't' _ 'e', 3, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(643, + /* a c */ 'u' _ 't' _ 'e' _ ';', 4, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(644, /* a c */ 'y' _ ';', 2, 0, 0x0430 _ 0) +NAMED_CHARACTER_REFERENCE(645, /* a e */ 'l' _ 'i' _ 'g', 3, 0, 0x00e6 _ 0) +NAMED_CHARACTER_REFERENCE(646, + /* a e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00e6 _ 0) +NAMED_CHARACTER_REFERENCE(647, /* a f */ ';', 1, 0, 0x2061 _ 0) +NAMED_CHARACTER_REFERENCE(648, /* a f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1e) +NAMED_CHARACTER_REFERENCE(649, + /* a g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e0 _ 0) +NAMED_CHARACTER_REFERENCE(650, + /* a g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00e0 _ 0) +NAMED_CHARACTER_REFERENCE(651, + /* a l */ 'e' _ 'f' _ 's' _ 'y' _ 'm' _ ';', 6, 0, + 0x2135 _ 0) +NAMED_CHARACTER_REFERENCE(652, + /* a l */ 'e' _ 'p' _ 'h' _ ';', 4, 0, 0x2135 _ 0) +NAMED_CHARACTER_REFERENCE(653, + /* a l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x03b1 _ 0) +NAMED_CHARACTER_REFERENCE(654, + /* a m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0101 _ 0) +NAMED_CHARACTER_REFERENCE(655, + /* a m */ 'a' _ 'l' _ 'g' _ ';', 4, 0, 0x2a3f _ 0) +NAMED_CHARACTER_REFERENCE(656, /* a m */ 'p', 1, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(657, /* a m */ 'p' _ ';', 2, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(658, /* a n */ 'd' _ ';', 2, 0, 0x2227 _ 0) +NAMED_CHARACTER_REFERENCE(659, + /* a n */ 'd' _ 'a' _ 'n' _ 'd' _ ';', 5, 0, + 0x2a55 _ 0) +NAMED_CHARACTER_REFERENCE(660, /* a n */ 'd' _ 'd' _ ';', 3, 0, 0x2a5c _ 0) +NAMED_CHARACTER_REFERENCE(661, + /* a n */ 'd' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 7, + 0, 0x2a58 _ 0) +NAMED_CHARACTER_REFERENCE(662, /* a n */ 'd' _ 'v' _ ';', 3, 0, 0x2a5a _ 0) +NAMED_CHARACTER_REFERENCE(663, /* a n */ 'g' _ ';', 2, 0, 0x2220 _ 0) +NAMED_CHARACTER_REFERENCE(664, /* a n */ 'g' _ 'e' _ ';', 3, 0, 0x29a4 _ 0) +NAMED_CHARACTER_REFERENCE(665, + /* a n */ 'g' _ 'l' _ 'e' _ ';', 4, 0, 0x2220 _ 0) +NAMED_CHARACTER_REFERENCE(666, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ ';', 5, 0, + 0x2221 _ 0) +NAMED_CHARACTER_REFERENCE(667, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'a' _ ';', 7, + 0, 0x29a8 _ 0) +NAMED_CHARACTER_REFERENCE(668, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'b' _ ';', 7, + 0, 0x29a9 _ 0) +NAMED_CHARACTER_REFERENCE(669, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'c' _ ';', 7, + 0, 0x29aa _ 0) +NAMED_CHARACTER_REFERENCE(670, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'd' _ ';', 7, + 0, 0x29ab _ 0) +NAMED_CHARACTER_REFERENCE(671, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'e' _ ';', 7, + 0, 0x29ac _ 0) +NAMED_CHARACTER_REFERENCE(672, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'f' _ ';', 7, + 0, 0x29ad _ 0) +NAMED_CHARACTER_REFERENCE(673, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'g' _ ';', 7, + 0, 0x29ae _ 0) +NAMED_CHARACTER_REFERENCE(674, + /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'h' _ ';', 7, + 0, 0x29af _ 0) +NAMED_CHARACTER_REFERENCE(675, + /* a n */ 'g' _ 'r' _ 't' _ ';', 4, 0, 0x221f _ 0) +NAMED_CHARACTER_REFERENCE(676, + /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ ';', 6, 0, + 0x22be _ 0) +NAMED_CHARACTER_REFERENCE(677, + /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ 'd' _ ';', 7, + 0, 0x299d _ 0) +NAMED_CHARACTER_REFERENCE(678, + /* a n */ 'g' _ 's' _ 'p' _ 'h' _ ';', 5, 0, + 0x2222 _ 0) +NAMED_CHARACTER_REFERENCE(679, + /* a n */ 'g' _ 's' _ 't' _ ';', 4, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(680, + /* a n */ 'g' _ 'z' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, + 0x237c _ 0) +NAMED_CHARACTER_REFERENCE(681, + /* a o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0105 _ 0) +NAMED_CHARACTER_REFERENCE(682, /* a o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd52) +NAMED_CHARACTER_REFERENCE(683, /* a p */ ';', 1, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(684, /* a p */ 'E' _ ';', 2, 0, 0x2a70 _ 0) +NAMED_CHARACTER_REFERENCE(685, + /* a p */ 'a' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, + 0x2a6f _ 0) +NAMED_CHARACTER_REFERENCE(686, /* a p */ 'e' _ ';', 2, 0, 0x224a _ 0) +NAMED_CHARACTER_REFERENCE(687, /* a p */ 'i' _ 'd' _ ';', 3, 0, 0x224b _ 0) +NAMED_CHARACTER_REFERENCE(688, /* a p */ 'o' _ 's' _ ';', 3, 0, 0x0027 _ 0) +NAMED_CHARACTER_REFERENCE(689, + /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ ';', 5, 0, + 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(690, + /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ 'e' _ 'q' _ ';', 7, + 0, 0x224a _ 0) +NAMED_CHARACTER_REFERENCE(691, /* a r */ 'i' _ 'n' _ 'g', 3, 0, 0x00e5 _ 0) +NAMED_CHARACTER_REFERENCE(692, + /* a r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00e5 _ 0) +NAMED_CHARACTER_REFERENCE(693, /* a s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb6) +NAMED_CHARACTER_REFERENCE(694, /* a s */ 't' _ ';', 2, 0, 0x002a _ 0) +NAMED_CHARACTER_REFERENCE(695, + /* a s */ 'y' _ 'm' _ 'p' _ ';', 4, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(696, + /* a s */ 'y' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 6, 0, + 0x224d _ 0) +NAMED_CHARACTER_REFERENCE(697, + /* a t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00e3 _ 0) +NAMED_CHARACTER_REFERENCE(698, + /* a t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x00e3 _ 0) +NAMED_CHARACTER_REFERENCE(699, /* a u */ 'm' _ 'l', 2, 0, 0x00e4 _ 0) +NAMED_CHARACTER_REFERENCE(700, /* a u */ 'm' _ 'l' _ ';', 3, 0, 0x00e4 _ 0) +NAMED_CHARACTER_REFERENCE(701, + /* a w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, + 0, 0x2233 _ 0) +NAMED_CHARACTER_REFERENCE(702, + /* a w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2a11 _ 0) +NAMED_CHARACTER_REFERENCE(703, /* b N */ 'o' _ 't' _ ';', 3, 0, 0x2aed _ 0) +NAMED_CHARACTER_REFERENCE(704, + /* b a */ 'c' _ 'k' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 7, + 0, 0x224c _ 0) +NAMED_CHARACTER_REFERENCE( + 705, + /* b a */ 'c' _ 'k' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 10, 0, + 0x03f6 _ 0) +NAMED_CHARACTER_REFERENCE( + 706, + /* b a */ 'c' _ 'k' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 8, 0, 0x2035 _ 0) +NAMED_CHARACTER_REFERENCE(707, + /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 6, 0, + 0x223d _ 0) +NAMED_CHARACTER_REFERENCE( + 708, + /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 8, 0, 0x22cd _ 0) +NAMED_CHARACTER_REFERENCE(709, + /* b a */ 'r' _ 'v' _ 'e' _ 'e' _ ';', 5, 0, + 0x22bd _ 0) +NAMED_CHARACTER_REFERENCE(710, + /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0, + 0x2305 _ 0) +NAMED_CHARACTER_REFERENCE(711, + /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, + 0, 0x2305 _ 0) +NAMED_CHARACTER_REFERENCE(712, /* b b */ 'r' _ 'k' _ ';', 3, 0, 0x23b5 _ 0) +NAMED_CHARACTER_REFERENCE(713, + /* b b */ 'r' _ 'k' _ 't' _ 'b' _ 'r' _ 'k' _ ';', 7, + 0, 0x23b6 _ 0) +NAMED_CHARACTER_REFERENCE(714, + /* b c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x224c _ 0) +NAMED_CHARACTER_REFERENCE(715, /* b c */ 'y' _ ';', 2, 0, 0x0431 _ 0) +NAMED_CHARACTER_REFERENCE(716, + /* b d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201e _ 0) +NAMED_CHARACTER_REFERENCE(717, + /* b e */ 'c' _ 'a' _ 'u' _ 's' _ ';', 5, 0, + 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(718, + /* b e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0, + 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(719, + /* b e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, + 0x29b0 _ 0) +NAMED_CHARACTER_REFERENCE(720, + /* b e */ 'p' _ 's' _ 'i' _ ';', 4, 0, 0x03f6 _ 0) +NAMED_CHARACTER_REFERENCE(721, + /* b e */ 'r' _ 'n' _ 'o' _ 'u' _ ';', 5, 0, + 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(722, /* b e */ 't' _ 'a' _ ';', 3, 0, 0x03b2 _ 0) +NAMED_CHARACTER_REFERENCE(723, /* b e */ 't' _ 'h' _ ';', 3, 0, 0x2136 _ 0) +NAMED_CHARACTER_REFERENCE(724, + /* b e */ 't' _ 'w' _ 'e' _ 'e' _ 'n' _ ';', 6, 0, + 0x226c _ 0) +NAMED_CHARACTER_REFERENCE(725, /* b f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1f) +NAMED_CHARACTER_REFERENCE(726, + /* b i */ 'g' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, + 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(727, + /* b i */ 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0, + 0x25ef _ 0) +NAMED_CHARACTER_REFERENCE(728, + /* b i */ 'g' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, + 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(729, + /* b i */ 'g' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0, + 0x2a00 _ 0) +NAMED_CHARACTER_REFERENCE(730, + /* b i */ 'g' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, + 0, 0x2a01 _ 0) +NAMED_CHARACTER_REFERENCE( + 731, + /* b i */ 'g' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0, 0x2a02 _ 0) +NAMED_CHARACTER_REFERENCE(732, + /* b i */ 'g' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7, + 0, 0x2a06 _ 0) +NAMED_CHARACTER_REFERENCE(733, + /* b i */ 'g' _ 's' _ 't' _ 'a' _ 'r' _ ';', 6, 0, + 0x2605 _ 0) +NAMED_CHARACTER_REFERENCE( + 734, + /* b i */ + 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', + 14, 0, 0x25bd _ 0) +NAMED_CHARACTER_REFERENCE( + 735, + /* b i */ + 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'u' _ 'p' _ ';', 12, + 0, 0x25b3 _ 0) +NAMED_CHARACTER_REFERENCE(736, + /* b i */ 'g' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, + 0, 0x2a04 _ 0) +NAMED_CHARACTER_REFERENCE(737, + /* b i */ 'g' _ 'v' _ 'e' _ 'e' _ ';', 5, 0, + 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(738, + /* b i */ 'g' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, + 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(739, + /* b k */ 'a' _ 'r' _ 'o' _ 'w' _ ';', 5, 0, + 0x290d _ 0) +NAMED_CHARACTER_REFERENCE( + 740, + /* b l */ 'a' _ 'c' _ 'k' _ 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', + 11, 0, 0x29eb _ 0) +NAMED_CHARACTER_REFERENCE( + 741, + /* b l */ 'a' _ 'c' _ 'k' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0, + 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE( + 742, + /* b l */ + 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, + 0, 0x25b4 _ 0) +NAMED_CHARACTER_REFERENCE( + 743, + /* b l */ + 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', + 16, 0, 0x25be _ 0) +NAMED_CHARACTER_REFERENCE( + 744, + /* b l */ + 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', + 16, 0, 0x25c2 _ 0) +NAMED_CHARACTER_REFERENCE( + 745, + /* b l */ + 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 17, 0, 0x25b8 _ 0) +NAMED_CHARACTER_REFERENCE(746, + /* b l */ 'a' _ 'n' _ 'k' _ ';', 4, 0, 0x2423 _ 0) +NAMED_CHARACTER_REFERENCE(747, + /* b l */ 'k' _ '1' _ '2' _ ';', 4, 0, 0x2592 _ 0) +NAMED_CHARACTER_REFERENCE(748, + /* b l */ 'k' _ '1' _ '4' _ ';', 4, 0, 0x2591 _ 0) +NAMED_CHARACTER_REFERENCE(749, + /* b l */ 'k' _ '3' _ '4' _ ';', 4, 0, 0x2593 _ 0) +NAMED_CHARACTER_REFERENCE(750, + /* b l */ 'o' _ 'c' _ 'k' _ ';', 4, 0, 0x2588 _ 0) +NAMED_CHARACTER_REFERENCE(751, /* b n */ 'e' _ ';', 2, 0, 0x003d _ 0x20e5) +NAMED_CHARACTER_REFERENCE(752, + /* b n */ 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ ';', 6, 0, + 0x2261 _ 0x20e5) +NAMED_CHARACTER_REFERENCE(753, /* b n */ 'o' _ 't' _ ';', 3, 0, 0x2310 _ 0) +NAMED_CHARACTER_REFERENCE(754, /* b o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd53) +NAMED_CHARACTER_REFERENCE(755, /* b o */ 't' _ ';', 2, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(756, + /* b o */ 't' _ 't' _ 'o' _ 'm' _ ';', 5, 0, + 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(757, + /* b o */ 'w' _ 't' _ 'i' _ 'e' _ ';', 5, 0, + 0x22c8 _ 0) +NAMED_CHARACTER_REFERENCE(758, + /* b o */ 'x' _ 'D' _ 'L' _ ';', 4, 0, 0x2557 _ 0) +NAMED_CHARACTER_REFERENCE(759, + /* b o */ 'x' _ 'D' _ 'R' _ ';', 4, 0, 0x2554 _ 0) +NAMED_CHARACTER_REFERENCE(760, + /* b o */ 'x' _ 'D' _ 'l' _ ';', 4, 0, 0x2556 _ 0) +NAMED_CHARACTER_REFERENCE(761, + /* b o */ 'x' _ 'D' _ 'r' _ ';', 4, 0, 0x2553 _ 0) +NAMED_CHARACTER_REFERENCE(762, /* b o */ 'x' _ 'H' _ ';', 3, 0, 0x2550 _ 0) +NAMED_CHARACTER_REFERENCE(763, + /* b o */ 'x' _ 'H' _ 'D' _ ';', 4, 0, 0x2566 _ 0) +NAMED_CHARACTER_REFERENCE(764, + /* b o */ 'x' _ 'H' _ 'U' _ ';', 4, 0, 0x2569 _ 0) +NAMED_CHARACTER_REFERENCE(765, + /* b o */ 'x' _ 'H' _ 'd' _ ';', 4, 0, 0x2564 _ 0) +NAMED_CHARACTER_REFERENCE(766, + /* b o */ 'x' _ 'H' _ 'u' _ ';', 4, 0, 0x2567 _ 0) +NAMED_CHARACTER_REFERENCE(767, + /* b o */ 'x' _ 'U' _ 'L' _ ';', 4, 0, 0x255d _ 0) +NAMED_CHARACTER_REFERENCE(768, + /* b o */ 'x' _ 'U' _ 'R' _ ';', 4, 0, 0x255a _ 0) +NAMED_CHARACTER_REFERENCE(769, + /* b o */ 'x' _ 'U' _ 'l' _ ';', 4, 0, 0x255c _ 0) +NAMED_CHARACTER_REFERENCE(770, + /* b o */ 'x' _ 'U' _ 'r' _ ';', 4, 0, 0x2559 _ 0) +NAMED_CHARACTER_REFERENCE(771, /* b o */ 'x' _ 'V' _ ';', 3, 0, 0x2551 _ 0) +NAMED_CHARACTER_REFERENCE(772, + /* b o */ 'x' _ 'V' _ 'H' _ ';', 4, 0, 0x256c _ 0) +NAMED_CHARACTER_REFERENCE(773, + /* b o */ 'x' _ 'V' _ 'L' _ ';', 4, 0, 0x2563 _ 0) +NAMED_CHARACTER_REFERENCE(774, + /* b o */ 'x' _ 'V' _ 'R' _ ';', 4, 0, 0x2560 _ 0) +NAMED_CHARACTER_REFERENCE(775, + /* b o */ 'x' _ 'V' _ 'h' _ ';', 4, 0, 0x256b _ 0) +NAMED_CHARACTER_REFERENCE(776, + /* b o */ 'x' _ 'V' _ 'l' _ ';', 4, 0, 0x2562 _ 0) +NAMED_CHARACTER_REFERENCE(777, + /* b o */ 'x' _ 'V' _ 'r' _ ';', 4, 0, 0x255f _ 0) +NAMED_CHARACTER_REFERENCE(778, + /* b o */ 'x' _ 'b' _ 'o' _ 'x' _ ';', 5, 0, + 0x29c9 _ 0) +NAMED_CHARACTER_REFERENCE(779, + /* b o */ 'x' _ 'd' _ 'L' _ ';', 4, 0, 0x2555 _ 0) +NAMED_CHARACTER_REFERENCE(780, + /* b o */ 'x' _ 'd' _ 'R' _ ';', 4, 0, 0x2552 _ 0) +NAMED_CHARACTER_REFERENCE(781, + /* b o */ 'x' _ 'd' _ 'l' _ ';', 4, 0, 0x2510 _ 0) +NAMED_CHARACTER_REFERENCE(782, + /* b o */ 'x' _ 'd' _ 'r' _ ';', 4, 0, 0x250c _ 0) +NAMED_CHARACTER_REFERENCE(783, /* b o */ 'x' _ 'h' _ ';', 3, 0, 0x2500 _ 0) +NAMED_CHARACTER_REFERENCE(784, + /* b o */ 'x' _ 'h' _ 'D' _ ';', 4, 0, 0x2565 _ 0) +NAMED_CHARACTER_REFERENCE(785, + /* b o */ 'x' _ 'h' _ 'U' _ ';', 4, 0, 0x2568 _ 0) +NAMED_CHARACTER_REFERENCE(786, + /* b o */ 'x' _ 'h' _ 'd' _ ';', 4, 0, 0x252c _ 0) +NAMED_CHARACTER_REFERENCE(787, + /* b o */ 'x' _ 'h' _ 'u' _ ';', 4, 0, 0x2534 _ 0) +NAMED_CHARACTER_REFERENCE(788, + /* b o */ 'x' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, + 0, 0x229f _ 0) +NAMED_CHARACTER_REFERENCE(789, + /* b o */ 'x' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, + 0x229e _ 0) +NAMED_CHARACTER_REFERENCE(790, + /* b o */ 'x' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, + 0, 0x22a0 _ 0) +NAMED_CHARACTER_REFERENCE(791, + /* b o */ 'x' _ 'u' _ 'L' _ ';', 4, 0, 0x255b _ 0) +NAMED_CHARACTER_REFERENCE(792, + /* b o */ 'x' _ 'u' _ 'R' _ ';', 4, 0, 0x2558 _ 0) +NAMED_CHARACTER_REFERENCE(793, + /* b o */ 'x' _ 'u' _ 'l' _ ';', 4, 0, 0x2518 _ 0) +NAMED_CHARACTER_REFERENCE(794, + /* b o */ 'x' _ 'u' _ 'r' _ ';', 4, 0, 0x2514 _ 0) +NAMED_CHARACTER_REFERENCE(795, /* b o */ 'x' _ 'v' _ ';', 3, 0, 0x2502 _ 0) +NAMED_CHARACTER_REFERENCE(796, + /* b o */ 'x' _ 'v' _ 'H' _ ';', 4, 0, 0x256a _ 0) +NAMED_CHARACTER_REFERENCE(797, + /* b o */ 'x' _ 'v' _ 'L' _ ';', 4, 0, 0x2561 _ 0) +NAMED_CHARACTER_REFERENCE(798, + /* b o */ 'x' _ 'v' _ 'R' _ ';', 4, 0, 0x255e _ 0) +NAMED_CHARACTER_REFERENCE(799, + /* b o */ 'x' _ 'v' _ 'h' _ ';', 4, 0, 0x253c _ 0) +NAMED_CHARACTER_REFERENCE(800, + /* b o */ 'x' _ 'v' _ 'l' _ ';', 4, 0, 0x2524 _ 0) +NAMED_CHARACTER_REFERENCE(801, + /* b o */ 'x' _ 'v' _ 'r' _ ';', 4, 0, 0x251c _ 0) +NAMED_CHARACTER_REFERENCE(802, + /* b p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, + 0x2035 _ 0) +NAMED_CHARACTER_REFERENCE(803, + /* b r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0) +NAMED_CHARACTER_REFERENCE(804, + /* b r */ 'v' _ 'b' _ 'a' _ 'r', 4, 0, 0x00a6 _ 0) +NAMED_CHARACTER_REFERENCE(805, + /* b r */ 'v' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x00a6 _ 0) +NAMED_CHARACTER_REFERENCE(806, /* b s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb7) +NAMED_CHARACTER_REFERENCE(807, + /* b s */ 'e' _ 'm' _ 'i' _ ';', 4, 0, 0x204f _ 0) +NAMED_CHARACTER_REFERENCE(808, /* b s */ 'i' _ 'm' _ ';', 3, 0, 0x223d _ 0) +NAMED_CHARACTER_REFERENCE(809, + /* b s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x22cd _ 0) +NAMED_CHARACTER_REFERENCE(810, /* b s */ 'o' _ 'l' _ ';', 3, 0, 0x005c _ 0) +NAMED_CHARACTER_REFERENCE(811, + /* b s */ 'o' _ 'l' _ 'b' _ ';', 4, 0, 0x29c5 _ 0) +NAMED_CHARACTER_REFERENCE(812, + /* b s */ 'o' _ 'l' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 7, + 0, 0x27c8 _ 0) +NAMED_CHARACTER_REFERENCE(813, /* b u */ 'l' _ 'l' _ ';', 3, 0, 0x2022 _ 0) +NAMED_CHARACTER_REFERENCE(814, + /* b u */ 'l' _ 'l' _ 'e' _ 't' _ ';', 5, 0, + 0x2022 _ 0) +NAMED_CHARACTER_REFERENCE(815, /* b u */ 'm' _ 'p' _ ';', 3, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(816, + /* b u */ 'm' _ 'p' _ 'E' _ ';', 4, 0, 0x2aae _ 0) +NAMED_CHARACTER_REFERENCE(817, + /* b u */ 'm' _ 'p' _ 'e' _ ';', 4, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(818, + /* b u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0, + 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(819, + /* c a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0107 _ 0) +NAMED_CHARACTER_REFERENCE(820, /* c a */ 'p' _ ';', 2, 0, 0x2229 _ 0) +NAMED_CHARACTER_REFERENCE(821, + /* c a */ 'p' _ 'a' _ 'n' _ 'd' _ ';', 5, 0, + 0x2a44 _ 0) +NAMED_CHARACTER_REFERENCE(822, + /* c a */ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 7, + 0, 0x2a49 _ 0) +NAMED_CHARACTER_REFERENCE(823, + /* c a */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, + 0x2a4b _ 0) +NAMED_CHARACTER_REFERENCE(824, + /* c a */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, + 0x2a47 _ 0) +NAMED_CHARACTER_REFERENCE(825, + /* c a */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2a40 _ 0) +NAMED_CHARACTER_REFERENCE(826, /* c a */ 'p' _ 's' _ ';', 3, 0, 0x2229 _ 0xfe00) +NAMED_CHARACTER_REFERENCE(827, + /* c a */ 'r' _ 'e' _ 't' _ ';', 4, 0, 0x2041 _ 0) +NAMED_CHARACTER_REFERENCE(828, + /* c a */ 'r' _ 'o' _ 'n' _ ';', 4, 0, 0x02c7 _ 0) +NAMED_CHARACTER_REFERENCE(829, + /* c c */ 'a' _ 'p' _ 's' _ ';', 4, 0, 0x2a4d _ 0) +NAMED_CHARACTER_REFERENCE(830, + /* c c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x010d _ 0) +NAMED_CHARACTER_REFERENCE(831, + /* c c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00e7 _ 0) +NAMED_CHARACTER_REFERENCE(832, + /* c c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x00e7 _ 0) +NAMED_CHARACTER_REFERENCE(833, + /* c c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0109 _ 0) +NAMED_CHARACTER_REFERENCE(834, + /* c c */ 'u' _ 'p' _ 's' _ ';', 4, 0, 0x2a4c _ 0) +NAMED_CHARACTER_REFERENCE(835, + /* c c */ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 6, 0, + 0x2a50 _ 0) +NAMED_CHARACTER_REFERENCE(836, /* c d */ 'o' _ 't' _ ';', 3, 0, 0x010b _ 0) +NAMED_CHARACTER_REFERENCE(837, /* c e */ 'd' _ 'i' _ 'l', 3, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(838, + /* c e */ 'd' _ 'i' _ 'l' _ ';', 4, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(839, + /* c e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, + 0x29b2 _ 0) +NAMED_CHARACTER_REFERENCE(840, /* c e */ 'n' _ 't', 2, 0, 0x00a2 _ 0) +NAMED_CHARACTER_REFERENCE(841, /* c e */ 'n' _ 't' _ ';', 3, 0, 0x00a2 _ 0) +NAMED_CHARACTER_REFERENCE( + 842, + /* c e */ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(843, /* c f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd20) +NAMED_CHARACTER_REFERENCE(844, /* c h */ 'c' _ 'y' _ ';', 3, 0, 0x0447 _ 0) +NAMED_CHARACTER_REFERENCE(845, + /* c h */ 'e' _ 'c' _ 'k' _ ';', 4, 0, 0x2713 _ 0) +NAMED_CHARACTER_REFERENCE( + 846, + /* c h */ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 8, 0, 0x2713 _ 0) +NAMED_CHARACTER_REFERENCE(847, /* c h */ 'i' _ ';', 2, 0, 0x03c7 _ 0) +NAMED_CHARACTER_REFERENCE(848, /* c i */ 'r' _ ';', 2, 0, 0x25cb _ 0) +NAMED_CHARACTER_REFERENCE(849, /* c i */ 'r' _ 'E' _ ';', 3, 0, 0x29c3 _ 0) +NAMED_CHARACTER_REFERENCE(850, /* c i */ 'r' _ 'c' _ ';', 3, 0, 0x02c6 _ 0) +NAMED_CHARACTER_REFERENCE(851, + /* c i */ 'r' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, + 0x2257 _ 0) +NAMED_CHARACTER_REFERENCE( + 852, + /* c i */ + 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', + 14, 0, 0x21ba _ 0) +NAMED_CHARACTER_REFERENCE( + 853, + /* c i */ + 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 15, 0, 0x21bb _ 0) +NAMED_CHARACTER_REFERENCE(854, + /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 7, + 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(855, + /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 7, + 0, 0x24c8 _ 0) +NAMED_CHARACTER_REFERENCE( + 856, + /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 9, 0, + 0x229b _ 0) +NAMED_CHARACTER_REFERENCE( + 857, + /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 10, 0, + 0x229a _ 0) +NAMED_CHARACTER_REFERENCE( + 858, + /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 10, 0, + 0x229d _ 0) +NAMED_CHARACTER_REFERENCE(859, /* c i */ 'r' _ 'e' _ ';', 3, 0, 0x2257 _ 0) +NAMED_CHARACTER_REFERENCE(860, + /* c i */ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, + 0, 0x2a10 _ 0) +NAMED_CHARACTER_REFERENCE(861, + /* c i */ 'r' _ 'm' _ 'i' _ 'd' _ ';', 5, 0, + 0x2aef _ 0) +NAMED_CHARACTER_REFERENCE(862, + /* c i */ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, + 0x29c2 _ 0) +NAMED_CHARACTER_REFERENCE(863, + /* c l */ 'u' _ 'b' _ 's' _ ';', 4, 0, 0x2663 _ 0) +NAMED_CHARACTER_REFERENCE(864, + /* c l */ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 7, + 0, 0x2663 _ 0) +NAMED_CHARACTER_REFERENCE(865, + /* c o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x003a _ 0) +NAMED_CHARACTER_REFERENCE(866, + /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0, + 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(867, + /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 6, 0, + 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(868, + /* c o */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x002c _ 0) +NAMED_CHARACTER_REFERENCE(869, + /* c o */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0, + 0x0040 _ 0) +NAMED_CHARACTER_REFERENCE(870, /* c o */ 'm' _ 'p' _ ';', 3, 0, 0x2201 _ 0) +NAMED_CHARACTER_REFERENCE(871, + /* c o */ 'm' _ 'p' _ 'f' _ 'n' _ ';', 5, 0, + 0x2218 _ 0) +NAMED_CHARACTER_REFERENCE( + 872, + /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0, + 0x2201 _ 0) +NAMED_CHARACTER_REFERENCE( + 873, + /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 8, 0, 0x2102 _ 0) +NAMED_CHARACTER_REFERENCE(874, /* c o */ 'n' _ 'g' _ ';', 3, 0, 0x2245 _ 0) +NAMED_CHARACTER_REFERENCE(875, + /* c o */ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 6, 0, + 0x2a6d _ 0) +NAMED_CHARACTER_REFERENCE(876, + /* c o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0, + 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(877, /* c o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd54) +NAMED_CHARACTER_REFERENCE(878, + /* c o */ 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0, + 0x2210 _ 0) +NAMED_CHARACTER_REFERENCE(879, /* c o */ 'p' _ 'y', 2, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(880, /* c o */ 'p' _ 'y' _ ';', 3, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(881, + /* c o */ 'p' _ 'y' _ 's' _ 'r' _ ';', 5, 0, + 0x2117 _ 0) +NAMED_CHARACTER_REFERENCE(882, + /* c r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21b5 _ 0) +NAMED_CHARACTER_REFERENCE(883, + /* c r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2717 _ 0) +NAMED_CHARACTER_REFERENCE(884, /* c s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb8) +NAMED_CHARACTER_REFERENCE(885, /* c s */ 'u' _ 'b' _ ';', 3, 0, 0x2acf _ 0) +NAMED_CHARACTER_REFERENCE(886, + /* c s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2ad1 _ 0) +NAMED_CHARACTER_REFERENCE(887, /* c s */ 'u' _ 'p' _ ';', 3, 0, 0x2ad0 _ 0) +NAMED_CHARACTER_REFERENCE(888, + /* c s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2ad2 _ 0) +NAMED_CHARACTER_REFERENCE(889, + /* c t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22ef _ 0) +NAMED_CHARACTER_REFERENCE(890, + /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 6, 0, + 0x2938 _ 0) +NAMED_CHARACTER_REFERENCE(891, + /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 6, 0, + 0x2935 _ 0) +NAMED_CHARACTER_REFERENCE(892, + /* c u */ 'e' _ 'p' _ 'r' _ ';', 4, 0, 0x22de _ 0) +NAMED_CHARACTER_REFERENCE(893, + /* c u */ 'e' _ 's' _ 'c' _ ';', 4, 0, 0x22df _ 0) +NAMED_CHARACTER_REFERENCE(894, + /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, + 0x21b6 _ 0) +NAMED_CHARACTER_REFERENCE(895, + /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 6, 0, + 0x293d _ 0) +NAMED_CHARACTER_REFERENCE(896, /* c u */ 'p' _ ';', 2, 0, 0x222a _ 0) +NAMED_CHARACTER_REFERENCE(897, + /* c u */ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 7, + 0, 0x2a48 _ 0) +NAMED_CHARACTER_REFERENCE(898, + /* c u */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, + 0x2a46 _ 0) +NAMED_CHARACTER_REFERENCE(899, + /* c u */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, + 0x2a4a _ 0) +NAMED_CHARACTER_REFERENCE(900, + /* c u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x228d _ 0) +NAMED_CHARACTER_REFERENCE(901, + /* c u */ 'p' _ 'o' _ 'r' _ ';', 4, 0, 0x2a45 _ 0) +NAMED_CHARACTER_REFERENCE(902, /* c u */ 'p' _ 's' _ ';', 3, 0, 0x222a _ 0xfe00) +NAMED_CHARACTER_REFERENCE(903, + /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, + 0x21b7 _ 0) +NAMED_CHARACTER_REFERENCE(904, + /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 6, 0, + 0x293c _ 0) +NAMED_CHARACTER_REFERENCE( + 905, + /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 10, 0, + 0x22de _ 0) +NAMED_CHARACTER_REFERENCE( + 906, + /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 10, 0, + 0x22df _ 0) +NAMED_CHARACTER_REFERENCE(907, + /* c u */ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 7, + 0, 0x22ce _ 0) +NAMED_CHARACTER_REFERENCE( + 908, + /* c u */ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 9, 0, + 0x22cf _ 0) +NAMED_CHARACTER_REFERENCE(909, + /* c u */ 'r' _ 'r' _ 'e' _ 'n', 4, 0, 0x00a4 _ 0) +NAMED_CHARACTER_REFERENCE(910, + /* c u */ 'r' _ 'r' _ 'e' _ 'n' _ ';', 5, 0, + 0x00a4 _ 0) +NAMED_CHARACTER_REFERENCE( + 911, + /* c u */ + 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', + 13, 0, 0x21b6 _ 0) +NAMED_CHARACTER_REFERENCE( + 912, + /* c u */ + 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 14, 0, 0x21b7 _ 0) +NAMED_CHARACTER_REFERENCE(913, + /* c u */ 'v' _ 'e' _ 'e' _ ';', 4, 0, 0x22ce _ 0) +NAMED_CHARACTER_REFERENCE(914, + /* c u */ 'w' _ 'e' _ 'd' _ ';', 4, 0, 0x22cf _ 0) +NAMED_CHARACTER_REFERENCE(915, + /* c w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, + 0, 0x2232 _ 0) +NAMED_CHARACTER_REFERENCE(916, + /* c w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2231 _ 0) +NAMED_CHARACTER_REFERENCE(917, + /* c y */ 'l' _ 'c' _ 't' _ 'y' _ ';', 5, 0, + 0x232d _ 0) +NAMED_CHARACTER_REFERENCE(918, /* d A */ 'r' _ 'r' _ ';', 3, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(919, /* d H */ 'a' _ 'r' _ ';', 3, 0, 0x2965 _ 0) +NAMED_CHARACTER_REFERENCE(920, + /* d a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0, + 0x2020 _ 0) +NAMED_CHARACTER_REFERENCE(921, + /* d a */ 'l' _ 'e' _ 't' _ 'h' _ ';', 5, 0, + 0x2138 _ 0) +NAMED_CHARACTER_REFERENCE(922, /* d a */ 'r' _ 'r' _ ';', 3, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(923, /* d a */ 's' _ 'h' _ ';', 3, 0, 0x2010 _ 0) +NAMED_CHARACTER_REFERENCE(924, + /* d a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x22a3 _ 0) +NAMED_CHARACTER_REFERENCE(925, + /* d b */ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x290f _ 0) +NAMED_CHARACTER_REFERENCE(926, + /* d b */ 'l' _ 'a' _ 'c' _ ';', 4, 0, 0x02dd _ 0) +NAMED_CHARACTER_REFERENCE(927, + /* d c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x010f _ 0) +NAMED_CHARACTER_REFERENCE(928, /* d c */ 'y' _ ';', 2, 0, 0x0434 _ 0) +NAMED_CHARACTER_REFERENCE(929, /* d d */ ';', 1, 0, 0x2146 _ 0) +NAMED_CHARACTER_REFERENCE(930, + /* d d */ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 6, 0, + 0x2021 _ 0) +NAMED_CHARACTER_REFERENCE(931, + /* d d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ca _ 0) +NAMED_CHARACTER_REFERENCE(932, + /* d d */ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 6, 0, + 0x2a77 _ 0) +NAMED_CHARACTER_REFERENCE(933, /* d e */ 'g', 1, 0, 0x00b0 _ 0) +NAMED_CHARACTER_REFERENCE(934, /* d e */ 'g' _ ';', 2, 0, 0x00b0 _ 0) +NAMED_CHARACTER_REFERENCE(935, + /* d e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x03b4 _ 0) +NAMED_CHARACTER_REFERENCE(936, + /* d e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, + 0x29b1 _ 0) +NAMED_CHARACTER_REFERENCE(937, + /* d f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, + 0x297f _ 0) +NAMED_CHARACTER_REFERENCE(938, /* d f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd21) +NAMED_CHARACTER_REFERENCE(939, + /* d h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE(940, + /* d h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(941, /* d i */ 'a' _ 'm' _ ';', 3, 0, 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE(942, + /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0, + 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE( + 943, + /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0, + 0x2666 _ 0) +NAMED_CHARACTER_REFERENCE(944, + /* d i */ 'a' _ 'm' _ 's' _ ';', 4, 0, 0x2666 _ 0) +NAMED_CHARACTER_REFERENCE(945, /* d i */ 'e' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(946, + /* d i */ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0, + 0x03dd _ 0) +NAMED_CHARACTER_REFERENCE(947, + /* d i */ 's' _ 'i' _ 'n' _ ';', 4, 0, 0x22f2 _ 0) +NAMED_CHARACTER_REFERENCE(948, /* d i */ 'v' _ ';', 2, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(949, + /* d i */ 'v' _ 'i' _ 'd' _ 'e', 4, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(950, + /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ ';', 5, 0, + 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE( + 951, + /* d i */ + 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 12, + 0, 0x22c7 _ 0) +NAMED_CHARACTER_REFERENCE(952, + /* d i */ 'v' _ 'o' _ 'n' _ 'x' _ ';', 5, 0, + 0x22c7 _ 0) +NAMED_CHARACTER_REFERENCE(953, /* d j */ 'c' _ 'y' _ ';', 3, 0, 0x0452 _ 0) +NAMED_CHARACTER_REFERENCE(954, + /* d l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, + 0x231e _ 0) +NAMED_CHARACTER_REFERENCE(955, + /* d l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, + 0x230d _ 0) +NAMED_CHARACTER_REFERENCE(956, + /* d o */ 'l' _ 'l' _ 'a' _ 'r' _ ';', 5, 0, + 0x0024 _ 0) +NAMED_CHARACTER_REFERENCE(957, /* d o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd55) +NAMED_CHARACTER_REFERENCE(958, /* d o */ 't' _ ';', 2, 0, 0x02d9 _ 0) +NAMED_CHARACTER_REFERENCE(959, + /* d o */ 't' _ 'e' _ 'q' _ ';', 4, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(960, + /* d o */ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 7, + 0, 0x2251 _ 0) +NAMED_CHARACTER_REFERENCE(961, + /* d o */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, + 0, 0x2238 _ 0) +NAMED_CHARACTER_REFERENCE(962, + /* d o */ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, + 0x2214 _ 0) +NAMED_CHARACTER_REFERENCE( + 963, + /* d o */ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 8, 0, 0x22a1 _ 0) +NAMED_CHARACTER_REFERENCE( + 964, + /* d o */ + 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', + 13, 0, 0x2306 _ 0) +NAMED_CHARACTER_REFERENCE( + 965, + /* d o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE( + 966, + /* d o */ + 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', + 13, 0, 0x21ca _ 0) +NAMED_CHARACTER_REFERENCE( + 967, + /* d o */ + 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', + 14, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE( + 968, + /* d o */ + 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 15, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(969, + /* d r */ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, + 0, 0x2910 _ 0) +NAMED_CHARACTER_REFERENCE(970, + /* d r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, + 0x231f _ 0) +NAMED_CHARACTER_REFERENCE(971, + /* d r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, + 0x230c _ 0) +NAMED_CHARACTER_REFERENCE(972, /* d s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb9) +NAMED_CHARACTER_REFERENCE(973, /* d s */ 'c' _ 'y' _ ';', 3, 0, 0x0455 _ 0) +NAMED_CHARACTER_REFERENCE(974, /* d s */ 'o' _ 'l' _ ';', 3, 0, 0x29f6 _ 0) +NAMED_CHARACTER_REFERENCE(975, + /* d s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0111 _ 0) +NAMED_CHARACTER_REFERENCE(976, + /* d t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f1 _ 0) +NAMED_CHARACTER_REFERENCE(977, /* d t */ 'r' _ 'i' _ ';', 3, 0, 0x25bf _ 0) +NAMED_CHARACTER_REFERENCE(978, + /* d t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25be _ 0) +NAMED_CHARACTER_REFERENCE(979, + /* d u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21f5 _ 0) +NAMED_CHARACTER_REFERENCE(980, + /* d u */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296f _ 0) +NAMED_CHARACTER_REFERENCE(981, + /* d w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0, + 0x29a6 _ 0) +NAMED_CHARACTER_REFERENCE(982, /* d z */ 'c' _ 'y' _ ';', 3, 0, 0x045f _ 0) +NAMED_CHARACTER_REFERENCE(983, + /* d z */ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, + 0, 0x27ff _ 0) +NAMED_CHARACTER_REFERENCE(984, + /* e D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2a77 _ 0) +NAMED_CHARACTER_REFERENCE(985, /* e D */ 'o' _ 't' _ ';', 3, 0, 0x2251 _ 0) +NAMED_CHARACTER_REFERENCE(986, + /* e a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e9 _ 0) +NAMED_CHARACTER_REFERENCE(987, + /* e a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00e9 _ 0) +NAMED_CHARACTER_REFERENCE(988, + /* e a */ 's' _ 't' _ 'e' _ 'r' _ ';', 5, 0, + 0x2a6e _ 0) +NAMED_CHARACTER_REFERENCE(989, + /* e c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x011b _ 0) +NAMED_CHARACTER_REFERENCE(990, /* e c */ 'i' _ 'r' _ ';', 3, 0, 0x2256 _ 0) +NAMED_CHARACTER_REFERENCE(991, /* e c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ea _ 0) +NAMED_CHARACTER_REFERENCE(992, + /* e c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ea _ 0) +NAMED_CHARACTER_REFERENCE(993, + /* e c */ 'o' _ 'l' _ 'o' _ 'n' _ ';', 5, 0, + 0x2255 _ 0) +NAMED_CHARACTER_REFERENCE(994, /* e c */ 'y' _ ';', 2, 0, 0x044d _ 0) +NAMED_CHARACTER_REFERENCE(995, /* e d */ 'o' _ 't' _ ';', 3, 0, 0x0117 _ 0) +NAMED_CHARACTER_REFERENCE(996, /* e e */ ';', 1, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(997, + /* e f */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2252 _ 0) +NAMED_CHARACTER_REFERENCE(998, /* e f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd22) +NAMED_CHARACTER_REFERENCE(999, /* e g */ ';', 1, 0, 0x2a9a _ 0) +NAMED_CHARACTER_REFERENCE(1000, + /* e g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e8 _ 0) +NAMED_CHARACTER_REFERENCE(1001, + /* e g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00e8 _ 0) +NAMED_CHARACTER_REFERENCE(1002, /* e g */ 's' _ ';', 2, 0, 0x2a96 _ 0) +NAMED_CHARACTER_REFERENCE(1003, + /* e g */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2a98 _ 0) +NAMED_CHARACTER_REFERENCE(1004, /* e l */ ';', 1, 0, 0x2a99 _ 0) +NAMED_CHARACTER_REFERENCE(1005, + /* e l */ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 7, + 0, 0x23e7 _ 0) +NAMED_CHARACTER_REFERENCE(1006, /* e l */ 'l' _ ';', 2, 0, 0x2113 _ 0) +NAMED_CHARACTER_REFERENCE(1007, /* e l */ 's' _ ';', 2, 0, 0x2a95 _ 0) +NAMED_CHARACTER_REFERENCE(1008, + /* e l */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2a97 _ 0) +NAMED_CHARACTER_REFERENCE(1009, + /* e m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0113 _ 0) +NAMED_CHARACTER_REFERENCE(1010, + /* e m */ 'p' _ 't' _ 'y' _ ';', 4, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(1011, + /* e m */ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 7, + 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(1012, + /* e m */ 'p' _ 't' _ 'y' _ 'v' _ ';', 5, 0, + 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(1013, + /* e m */ 's' _ 'p' _ '1' _ '3' _ ';', 5, 0, + 0x2004 _ 0) +NAMED_CHARACTER_REFERENCE(1014, + /* e m */ 's' _ 'p' _ '1' _ '4' _ ';', 5, 0, + 0x2005 _ 0) +NAMED_CHARACTER_REFERENCE(1015, /* e m */ 's' _ 'p' _ ';', 3, 0, 0x2003 _ 0) +NAMED_CHARACTER_REFERENCE(1016, /* e n */ 'g' _ ';', 2, 0, 0x014b _ 0) +NAMED_CHARACTER_REFERENCE(1017, /* e n */ 's' _ 'p' _ ';', 3, 0, 0x2002 _ 0) +NAMED_CHARACTER_REFERENCE(1018, + /* e o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0119 _ 0) +NAMED_CHARACTER_REFERENCE(1019, + /* e o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd56) +NAMED_CHARACTER_REFERENCE(1020, /* e p */ 'a' _ 'r' _ ';', 3, 0, 0x22d5 _ 0) +NAMED_CHARACTER_REFERENCE(1021, + /* e p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0, + 0x29e3 _ 0) +NAMED_CHARACTER_REFERENCE(1022, + /* e p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2a71 _ 0) +NAMED_CHARACTER_REFERENCE(1023, /* e p */ 's' _ 'i' _ ';', 3, 0, 0x03b5 _ 0) +NAMED_CHARACTER_REFERENCE(1024, + /* e p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, + 0x03b5 _ 0) +NAMED_CHARACTER_REFERENCE(1025, + /* e p */ 's' _ 'i' _ 'v' _ ';', 4, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(1026, + /* e q */ 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0, + 0x2256 _ 0) +NAMED_CHARACTER_REFERENCE(1027, + /* e q */ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, + 0x2255 _ 0) +NAMED_CHARACTER_REFERENCE(1028, + /* e q */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE( + 1029, + /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 9, 0, + 0x2a96 _ 0) +NAMED_CHARACTER_REFERENCE( + 1030, + /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0, + 0x2a95 _ 0) +NAMED_CHARACTER_REFERENCE(1031, + /* e q */ 'u' _ 'a' _ 'l' _ 's' _ ';', 5, 0, + 0x003d _ 0) +NAMED_CHARACTER_REFERENCE(1032, + /* e q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0, + 0x225f _ 0) +NAMED_CHARACTER_REFERENCE(1033, + /* e q */ 'u' _ 'i' _ 'v' _ ';', 4, 0, 0x2261 _ 0) +NAMED_CHARACTER_REFERENCE(1034, + /* e q */ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 6, 0, + 0x2a78 _ 0) +NAMED_CHARACTER_REFERENCE(1035, + /* e q */ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, + 0, 0x29e5 _ 0) +NAMED_CHARACTER_REFERENCE(1036, + /* e r */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2253 _ 0) +NAMED_CHARACTER_REFERENCE(1037, + /* e r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2971 _ 0) +NAMED_CHARACTER_REFERENCE(1038, /* e s */ 'c' _ 'r' _ ';', 3, 0, 0x212f _ 0) +NAMED_CHARACTER_REFERENCE(1039, + /* e s */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(1040, /* e s */ 'i' _ 'm' _ ';', 3, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE(1041, /* e t */ 'a' _ ';', 2, 0, 0x03b7 _ 0) +NAMED_CHARACTER_REFERENCE(1042, /* e t */ 'h', 1, 0, 0x00f0 _ 0) +NAMED_CHARACTER_REFERENCE(1043, /* e t */ 'h' _ ';', 2, 0, 0x00f0 _ 0) +NAMED_CHARACTER_REFERENCE(1044, /* e u */ 'm' _ 'l', 2, 0, 0x00eb _ 0) +NAMED_CHARACTER_REFERENCE(1045, /* e u */ 'm' _ 'l' _ ';', 3, 0, 0x00eb _ 0) +NAMED_CHARACTER_REFERENCE(1046, /* e u */ 'r' _ 'o' _ ';', 3, 0, 0x20ac _ 0) +NAMED_CHARACTER_REFERENCE(1047, /* e x */ 'c' _ 'l' _ ';', 3, 0, 0x0021 _ 0) +NAMED_CHARACTER_REFERENCE(1048, + /* e x */ 'i' _ 's' _ 't' _ ';', 4, 0, 0x2203 _ 0) +NAMED_CHARACTER_REFERENCE( + 1049, + /* e x */ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 10, 0, + 0x2130 _ 0) +NAMED_CHARACTER_REFERENCE( + 1050, + /* e x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';', + 11, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE( + 1051, + /* f a */ + 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 12, + 0, 0x2252 _ 0) +NAMED_CHARACTER_REFERENCE(1052, /* f c */ 'y' _ ';', 2, 0, 0x0444 _ 0) +NAMED_CHARACTER_REFERENCE(1053, + /* f e */ 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0, + 0x2640 _ 0) +NAMED_CHARACTER_REFERENCE(1054, + /* f f */ 'i' _ 'l' _ 'i' _ 'g' _ ';', 5, 0, + 0xfb03 _ 0) +NAMED_CHARACTER_REFERENCE(1055, + /* f f */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb00 _ 0) +NAMED_CHARACTER_REFERENCE(1056, + /* f f */ 'l' _ 'l' _ 'i' _ 'g' _ ';', 5, 0, + 0xfb04 _ 0) +NAMED_CHARACTER_REFERENCE(1057, /* f f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd23) +NAMED_CHARACTER_REFERENCE(1058, + /* f i */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb01 _ 0) +NAMED_CHARACTER_REFERENCE(1059, + /* f j */ 'l' _ 'i' _ 'g' _ ';', 4, 0, + 0x0066 _ 0x006a) +NAMED_CHARACTER_REFERENCE(1060, /* f l */ 'a' _ 't' _ ';', 3, 0, 0x266d _ 0) +NAMED_CHARACTER_REFERENCE(1061, + /* f l */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb02 _ 0) +NAMED_CHARACTER_REFERENCE(1062, + /* f l */ 't' _ 'n' _ 's' _ ';', 4, 0, 0x25b1 _ 0) +NAMED_CHARACTER_REFERENCE(1063, /* f n */ 'o' _ 'f' _ ';', 3, 0, 0x0192 _ 0) +NAMED_CHARACTER_REFERENCE(1064, + /* f o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd57) +NAMED_CHARACTER_REFERENCE(1065, + /* f o */ 'r' _ 'a' _ 'l' _ 'l' _ ';', 5, 0, + 0x2200 _ 0) +NAMED_CHARACTER_REFERENCE(1066, /* f o */ 'r' _ 'k' _ ';', 3, 0, 0x22d4 _ 0) +NAMED_CHARACTER_REFERENCE(1067, + /* f o */ 'r' _ 'k' _ 'v' _ ';', 4, 0, 0x2ad9 _ 0) +NAMED_CHARACTER_REFERENCE(1068, + /* f p */ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, + 0, 0x2a0d _ 0) +NAMED_CHARACTER_REFERENCE(1069, + /* f r */ 'a' _ 'c' _ '1' _ '2', 4, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1070, + /* f r */ 'a' _ 'c' _ '1' _ '2' _ ';', 5, 0, + 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1071, + /* f r */ 'a' _ 'c' _ '1' _ '3' _ ';', 5, 0, + 0x2153 _ 0) +NAMED_CHARACTER_REFERENCE(1072, + /* f r */ 'a' _ 'c' _ '1' _ '4', 4, 0, 0x00bc _ 0) +NAMED_CHARACTER_REFERENCE(1073, + /* f r */ 'a' _ 'c' _ '1' _ '4' _ ';', 5, 0, + 0x00bc _ 0) +NAMED_CHARACTER_REFERENCE(1074, + /* f r */ 'a' _ 'c' _ '1' _ '5' _ ';', 5, 0, + 0x2155 _ 0) +NAMED_CHARACTER_REFERENCE(1075, + /* f r */ 'a' _ 'c' _ '1' _ '6' _ ';', 5, 0, + 0x2159 _ 0) +NAMED_CHARACTER_REFERENCE(1076, + /* f r */ 'a' _ 'c' _ '1' _ '8' _ ';', 5, 0, + 0x215b _ 0) +NAMED_CHARACTER_REFERENCE(1077, + /* f r */ 'a' _ 'c' _ '2' _ '3' _ ';', 5, 0, + 0x2154 _ 0) +NAMED_CHARACTER_REFERENCE(1078, + /* f r */ 'a' _ 'c' _ '2' _ '5' _ ';', 5, 0, + 0x2156 _ 0) +NAMED_CHARACTER_REFERENCE(1079, + /* f r */ 'a' _ 'c' _ '3' _ '4', 4, 0, 0x00be _ 0) +NAMED_CHARACTER_REFERENCE(1080, + /* f r */ 'a' _ 'c' _ '3' _ '4' _ ';', 5, 0, + 0x00be _ 0) +NAMED_CHARACTER_REFERENCE(1081, + /* f r */ 'a' _ 'c' _ '3' _ '5' _ ';', 5, 0, + 0x2157 _ 0) +NAMED_CHARACTER_REFERENCE(1082, + /* f r */ 'a' _ 'c' _ '3' _ '8' _ ';', 5, 0, + 0x215c _ 0) +NAMED_CHARACTER_REFERENCE(1083, + /* f r */ 'a' _ 'c' _ '4' _ '5' _ ';', 5, 0, + 0x2158 _ 0) +NAMED_CHARACTER_REFERENCE(1084, + /* f r */ 'a' _ 'c' _ '5' _ '6' _ ';', 5, 0, + 0x215a _ 0) +NAMED_CHARACTER_REFERENCE(1085, + /* f r */ 'a' _ 'c' _ '5' _ '8' _ ';', 5, 0, + 0x215d _ 0) +NAMED_CHARACTER_REFERENCE(1086, + /* f r */ 'a' _ 'c' _ '7' _ '8' _ ';', 5, 0, + 0x215e _ 0) +NAMED_CHARACTER_REFERENCE(1087, + /* f r */ 'a' _ 's' _ 'l' _ ';', 4, 0, 0x2044 _ 0) +NAMED_CHARACTER_REFERENCE(1088, + /* f r */ 'o' _ 'w' _ 'n' _ ';', 4, 0, 0x2322 _ 0) +NAMED_CHARACTER_REFERENCE(1089, + /* f s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbb) +NAMED_CHARACTER_REFERENCE(1090, /* g E */ ';', 1, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(1091, /* g E */ 'l' _ ';', 2, 0, 0x2a8c _ 0) +NAMED_CHARACTER_REFERENCE(1092, + /* g a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x01f5 _ 0) +NAMED_CHARACTER_REFERENCE(1093, + /* g a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x03b3 _ 0) +NAMED_CHARACTER_REFERENCE(1094, + /* g a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0, + 0x03dd _ 0) +NAMED_CHARACTER_REFERENCE(1095, /* g a */ 'p' _ ';', 2, 0, 0x2a86 _ 0) +NAMED_CHARACTER_REFERENCE(1096, + /* g b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, + 0x011f _ 0) +NAMED_CHARACTER_REFERENCE(1097, + /* g c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011d _ 0) +NAMED_CHARACTER_REFERENCE(1098, /* g c */ 'y' _ ';', 2, 0, 0x0433 _ 0) +NAMED_CHARACTER_REFERENCE(1099, /* g d */ 'o' _ 't' _ ';', 3, 0, 0x0121 _ 0) +NAMED_CHARACTER_REFERENCE(1100, /* g e */ ';', 1, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(1101, /* g e */ 'l' _ ';', 2, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE(1102, /* g e */ 'q' _ ';', 2, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(1103, /* g e */ 'q' _ 'q' _ ';', 3, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(1104, + /* g e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, + 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(1105, /* g e */ 's' _ ';', 2, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(1106, + /* g e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa9 _ 0) +NAMED_CHARACTER_REFERENCE(1107, + /* g e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2a80 _ 0) +NAMED_CHARACTER_REFERENCE(1108, + /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0, + 0x2a82 _ 0) +NAMED_CHARACTER_REFERENCE(1109, + /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 7, + 0, 0x2a84 _ 0) +NAMED_CHARACTER_REFERENCE(1110, + /* g e */ 's' _ 'l' _ ';', 3, 0, 0x22db _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1111, + /* g e */ 's' _ 'l' _ 'e' _ 's' _ ';', 5, 0, + 0x2a94 _ 0) +NAMED_CHARACTER_REFERENCE(1112, /* g f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd24) +NAMED_CHARACTER_REFERENCE(1113, /* g g */ ';', 1, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(1114, /* g g */ 'g' _ ';', 2, 0, 0x22d9 _ 0) +NAMED_CHARACTER_REFERENCE(1115, + /* g i */ 'm' _ 'e' _ 'l' _ ';', 4, 0, 0x2137 _ 0) +NAMED_CHARACTER_REFERENCE(1116, /* g j */ 'c' _ 'y' _ ';', 3, 0, 0x0453 _ 0) +NAMED_CHARACTER_REFERENCE(1117, /* g l */ ';', 1, 0, 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(1118, /* g l */ 'E' _ ';', 2, 0, 0x2a92 _ 0) +NAMED_CHARACTER_REFERENCE(1119, /* g l */ 'a' _ ';', 2, 0, 0x2aa5 _ 0) +NAMED_CHARACTER_REFERENCE(1120, /* g l */ 'j' _ ';', 2, 0, 0x2aa4 _ 0) +NAMED_CHARACTER_REFERENCE(1121, /* g n */ 'E' _ ';', 2, 0, 0x2269 _ 0) +NAMED_CHARACTER_REFERENCE(1122, /* g n */ 'a' _ 'p' _ ';', 3, 0, 0x2a8a _ 0) +NAMED_CHARACTER_REFERENCE(1123, + /* g n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, + 0, 0x2a8a _ 0) +NAMED_CHARACTER_REFERENCE(1124, /* g n */ 'e' _ ';', 2, 0, 0x2a88 _ 0) +NAMED_CHARACTER_REFERENCE(1125, /* g n */ 'e' _ 'q' _ ';', 3, 0, 0x2a88 _ 0) +NAMED_CHARACTER_REFERENCE(1126, + /* g n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2269 _ 0) +NAMED_CHARACTER_REFERENCE(1127, + /* g n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e7 _ 0) +NAMED_CHARACTER_REFERENCE(1128, + /* g o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd58) +NAMED_CHARACTER_REFERENCE(1129, + /* g r */ 'a' _ 'v' _ 'e' _ ';', 4, 0, 0x0060 _ 0) +NAMED_CHARACTER_REFERENCE(1130, /* g s */ 'c' _ 'r' _ ';', 3, 0, 0x210a _ 0) +NAMED_CHARACTER_REFERENCE(1131, /* g s */ 'i' _ 'm' _ ';', 3, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(1132, + /* g s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8e _ 0) +NAMED_CHARACTER_REFERENCE(1133, + /* g s */ 'i' _ 'm' _ 'l' _ ';', 4, 0, 0x2a90 _ 0) +NAMED_CHARACTER_REFERENCE(1134, /* g t */ 0, 0, 1, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(1135, /* g t */ ';', 1, 0, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(1136, /* g t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa7 _ 0) +NAMED_CHARACTER_REFERENCE(1137, + /* g t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a7a _ 0) +NAMED_CHARACTER_REFERENCE(1138, + /* g t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d7 _ 0) +NAMED_CHARACTER_REFERENCE(1139, + /* g t */ 'l' _ 'P' _ 'a' _ 'r' _ ';', 5, 0, + 0x2995 _ 0) +NAMED_CHARACTER_REFERENCE(1140, + /* g t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0, + 0x2a7c _ 0) +NAMED_CHARACTER_REFERENCE( + 1141, + /* g t */ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0, 0x2a86 _ 0) +NAMED_CHARACTER_REFERENCE(1142, + /* g t */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, + 0x2978 _ 0) +NAMED_CHARACTER_REFERENCE(1143, + /* g t */ 'r' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x22d7 _ 0) +NAMED_CHARACTER_REFERENCE( + 1144, + /* g t */ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE( + 1145, + /* g t */ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 9, 0, + 0x2a8c _ 0) +NAMED_CHARACTER_REFERENCE(1146, + /* g t */ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0, + 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(1147, + /* g t */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0, + 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE( + 1148, + /* g v */ 'e' _ 'r' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, + 0x2269 _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1149, + /* g v */ 'n' _ 'E' _ ';', 3, 0, 0x2269 _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1150, /* h A */ 'r' _ 'r' _ ';', 3, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(1151, + /* h a */ 'i' _ 'r' _ 's' _ 'p' _ ';', 5, 0, + 0x200a _ 0) +NAMED_CHARACTER_REFERENCE(1152, /* h a */ 'l' _ 'f' _ ';', 3, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1153, + /* h a */ 'm' _ 'i' _ 'l' _ 't' _ ';', 5, 0, + 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(1154, + /* h a */ 'r' _ 'd' _ 'c' _ 'y' _ ';', 5, 0, + 0x044a _ 0) +NAMED_CHARACTER_REFERENCE(1155, /* h a */ 'r' _ 'r' _ ';', 3, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE(1156, + /* h a */ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, + 0x2948 _ 0) +NAMED_CHARACTER_REFERENCE(1157, + /* h a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x21ad _ 0) +NAMED_CHARACTER_REFERENCE(1158, /* h b */ 'a' _ 'r' _ ';', 3, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1159, + /* h c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0125 _ 0) +NAMED_CHARACTER_REFERENCE(1160, + /* h e */ 'a' _ 'r' _ 't' _ 's' _ ';', 5, 0, + 0x2665 _ 0) +NAMED_CHARACTER_REFERENCE( + 1161, + /* h e */ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2665 _ 0) +NAMED_CHARACTER_REFERENCE(1162, + /* h e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0, + 0x2026 _ 0) +NAMED_CHARACTER_REFERENCE(1163, + /* h e */ 'r' _ 'c' _ 'o' _ 'n' _ ';', 5, 0, + 0x22b9 _ 0) +NAMED_CHARACTER_REFERENCE(1164, /* h f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd25) +NAMED_CHARACTER_REFERENCE(1165, + /* h k */ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, + 0, 0x2925 _ 0) +NAMED_CHARACTER_REFERENCE(1166, + /* h k */ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, + 0, 0x2926 _ 0) +NAMED_CHARACTER_REFERENCE(1167, + /* h o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ff _ 0) +NAMED_CHARACTER_REFERENCE(1168, + /* h o */ 'm' _ 't' _ 'h' _ 't' _ ';', 5, 0, + 0x223b _ 0) +NAMED_CHARACTER_REFERENCE( + 1169, + /* h o */ + 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, + 0, 0x21a9 _ 0) +NAMED_CHARACTER_REFERENCE( + 1170, + /* h o */ + 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x21aa _ 0) +NAMED_CHARACTER_REFERENCE(1171, + /* h o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd59) +NAMED_CHARACTER_REFERENCE(1172, + /* h o */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x2015 _ 0) +NAMED_CHARACTER_REFERENCE(1173, + /* h s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbd) +NAMED_CHARACTER_REFERENCE(1174, + /* h s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1175, + /* h s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0127 _ 0) +NAMED_CHARACTER_REFERENCE(1176, + /* h y */ 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0, + 0x2043 _ 0) +NAMED_CHARACTER_REFERENCE(1177, + /* h y */ 'p' _ 'h' _ 'e' _ 'n' _ ';', 5, 0, + 0x2010 _ 0) +NAMED_CHARACTER_REFERENCE(1178, + /* i a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00ed _ 0) +NAMED_CHARACTER_REFERENCE(1179, + /* i a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00ed _ 0) +NAMED_CHARACTER_REFERENCE(1180, /* i c */ ';', 1, 0, 0x2063 _ 0) +NAMED_CHARACTER_REFERENCE(1181, /* i c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ee _ 0) +NAMED_CHARACTER_REFERENCE(1182, + /* i c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ee _ 0) +NAMED_CHARACTER_REFERENCE(1183, /* i c */ 'y' _ ';', 2, 0, 0x0438 _ 0) +NAMED_CHARACTER_REFERENCE(1184, /* i e */ 'c' _ 'y' _ ';', 3, 0, 0x0435 _ 0) +NAMED_CHARACTER_REFERENCE(1185, /* i e */ 'x' _ 'c' _ 'l', 3, 0, 0x00a1 _ 0) +NAMED_CHARACTER_REFERENCE(1186, + /* i e */ 'x' _ 'c' _ 'l' _ ';', 4, 0, 0x00a1 _ 0) +NAMED_CHARACTER_REFERENCE(1187, /* i f */ 'f' _ ';', 2, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(1188, /* i f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd26) +NAMED_CHARACTER_REFERENCE(1189, + /* i g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00ec _ 0) +NAMED_CHARACTER_REFERENCE(1190, + /* i g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00ec _ 0) +NAMED_CHARACTER_REFERENCE(1191, /* i i */ ';', 1, 0, 0x2148 _ 0) +NAMED_CHARACTER_REFERENCE(1192, + /* i i */ 'i' _ 'i' _ 'n' _ 't' _ ';', 5, 0, + 0x2a0c _ 0) +NAMED_CHARACTER_REFERENCE(1193, + /* i i */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x222d _ 0) +NAMED_CHARACTER_REFERENCE(1194, + /* i i */ 'n' _ 'f' _ 'i' _ 'n' _ ';', 5, 0, + 0x29dc _ 0) +NAMED_CHARACTER_REFERENCE(1195, + /* i i */ 'o' _ 't' _ 'a' _ ';', 4, 0, 0x2129 _ 0) +NAMED_CHARACTER_REFERENCE(1196, + /* i j */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0133 _ 0) +NAMED_CHARACTER_REFERENCE(1197, + /* i m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012b _ 0) +NAMED_CHARACTER_REFERENCE(1198, + /* i m */ 'a' _ 'g' _ 'e' _ ';', 4, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(1199, + /* i m */ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, + 0, 0x2110 _ 0) +NAMED_CHARACTER_REFERENCE(1200, + /* i m */ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, + 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(1201, + /* i m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0131 _ 0) +NAMED_CHARACTER_REFERENCE(1202, /* i m */ 'o' _ 'f' _ ';', 3, 0, 0x22b7 _ 0) +NAMED_CHARACTER_REFERENCE(1203, + /* i m */ 'p' _ 'e' _ 'd' _ ';', 4, 0, 0x01b5 _ 0) +NAMED_CHARACTER_REFERENCE(1204, /* i n */ ';', 1, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1205, + /* i n */ 'c' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, + 0x2105 _ 0) +NAMED_CHARACTER_REFERENCE(1206, + /* i n */ 'f' _ 'i' _ 'n' _ ';', 4, 0, 0x221e _ 0) +NAMED_CHARACTER_REFERENCE(1207, + /* i n */ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 7, + 0, 0x29dd _ 0) +NAMED_CHARACTER_REFERENCE(1208, + /* i n */ 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x0131 _ 0) +NAMED_CHARACTER_REFERENCE(1209, /* i n */ 't' _ ';', 2, 0, 0x222b _ 0) +NAMED_CHARACTER_REFERENCE(1210, + /* i n */ 't' _ 'c' _ 'a' _ 'l' _ ';', 5, 0, + 0x22ba _ 0) +NAMED_CHARACTER_REFERENCE(1211, + /* i n */ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 7, + 0, 0x2124 _ 0) +NAMED_CHARACTER_REFERENCE(1212, + /* i n */ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 7, + 0, 0x22ba _ 0) +NAMED_CHARACTER_REFERENCE(1213, + /* i n */ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, + 0, 0x2a17 _ 0) +NAMED_CHARACTER_REFERENCE(1214, + /* i n */ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0, + 0x2a3c _ 0) +NAMED_CHARACTER_REFERENCE(1215, /* i o */ 'c' _ 'y' _ ';', 3, 0, 0x0451 _ 0) +NAMED_CHARACTER_REFERENCE(1216, + /* i o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012f _ 0) +NAMED_CHARACTER_REFERENCE(1217, + /* i o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5a) +NAMED_CHARACTER_REFERENCE(1218, /* i o */ 't' _ 'a' _ ';', 3, 0, 0x03b9 _ 0) +NAMED_CHARACTER_REFERENCE(1219, + /* i p */ 'r' _ 'o' _ 'd' _ ';', 4, 0, 0x2a3c _ 0) +NAMED_CHARACTER_REFERENCE(1220, + /* i q */ 'u' _ 'e' _ 's' _ 't', 4, 0, 0x00bf _ 0) +NAMED_CHARACTER_REFERENCE(1221, + /* i q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0, + 0x00bf _ 0) +NAMED_CHARACTER_REFERENCE(1222, + /* i s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbe) +NAMED_CHARACTER_REFERENCE(1223, /* i s */ 'i' _ 'n' _ ';', 3, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1224, + /* i s */ 'i' _ 'n' _ 'E' _ ';', 4, 0, 0x22f9 _ 0) +NAMED_CHARACTER_REFERENCE(1225, + /* i s */ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 6, 0, + 0x22f5 _ 0) +NAMED_CHARACTER_REFERENCE(1226, + /* i s */ 'i' _ 'n' _ 's' _ ';', 4, 0, 0x22f4 _ 0) +NAMED_CHARACTER_REFERENCE(1227, + /* i s */ 'i' _ 'n' _ 's' _ 'v' _ ';', 5, 0, + 0x22f3 _ 0) +NAMED_CHARACTER_REFERENCE(1228, + /* i s */ 'i' _ 'n' _ 'v' _ ';', 4, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1229, /* i t */ ';', 1, 0, 0x2062 _ 0) +NAMED_CHARACTER_REFERENCE(1230, + /* i t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x0129 _ 0) +NAMED_CHARACTER_REFERENCE(1231, + /* i u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0456 _ 0) +NAMED_CHARACTER_REFERENCE(1232, /* i u */ 'm' _ 'l', 2, 0, 0x00ef _ 0) +NAMED_CHARACTER_REFERENCE(1233, /* i u */ 'm' _ 'l' _ ';', 3, 0, 0x00ef _ 0) +NAMED_CHARACTER_REFERENCE(1234, + /* j c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0135 _ 0) +NAMED_CHARACTER_REFERENCE(1235, /* j c */ 'y' _ ';', 2, 0, 0x0439 _ 0) +NAMED_CHARACTER_REFERENCE(1236, /* j f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd27) +NAMED_CHARACTER_REFERENCE(1237, + /* j m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0237 _ 0) +NAMED_CHARACTER_REFERENCE(1238, + /* j o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5b) +NAMED_CHARACTER_REFERENCE(1239, + /* j s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbf) +NAMED_CHARACTER_REFERENCE(1240, + /* j s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0, + 0x0458 _ 0) +NAMED_CHARACTER_REFERENCE(1241, + /* j u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0454 _ 0) +NAMED_CHARACTER_REFERENCE(1242, + /* k a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x03ba _ 0) +NAMED_CHARACTER_REFERENCE(1243, + /* k a */ 'p' _ 'p' _ 'a' _ 'v' _ ';', 5, 0, + 0x03f0 _ 0) +NAMED_CHARACTER_REFERENCE(1244, + /* k c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0137 _ 0) +NAMED_CHARACTER_REFERENCE(1245, /* k c */ 'y' _ ';', 2, 0, 0x043a _ 0) +NAMED_CHARACTER_REFERENCE(1246, /* k f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd28) +NAMED_CHARACTER_REFERENCE(1247, + /* k g */ 'r' _ 'e' _ 'e' _ 'n' _ ';', 5, 0, + 0x0138 _ 0) +NAMED_CHARACTER_REFERENCE(1248, /* k h */ 'c' _ 'y' _ ';', 3, 0, 0x0445 _ 0) +NAMED_CHARACTER_REFERENCE(1249, /* k j */ 'c' _ 'y' _ ';', 3, 0, 0x045c _ 0) +NAMED_CHARACTER_REFERENCE(1250, + /* k o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5c) +NAMED_CHARACTER_REFERENCE(1251, + /* k s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc0) +NAMED_CHARACTER_REFERENCE(1252, + /* l A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21da _ 0) +NAMED_CHARACTER_REFERENCE(1253, /* l A */ 'r' _ 'r' _ ';', 3, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE(1254, + /* l A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, + 0x291b _ 0) +NAMED_CHARACTER_REFERENCE(1255, + /* l B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290e _ 0) +NAMED_CHARACTER_REFERENCE(1256, /* l E */ ';', 1, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(1257, /* l E */ 'g' _ ';', 2, 0, 0x2a8b _ 0) +NAMED_CHARACTER_REFERENCE(1258, /* l H */ 'a' _ 'r' _ ';', 3, 0, 0x2962 _ 0) +NAMED_CHARACTER_REFERENCE(1259, + /* l a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x013a _ 0) +NAMED_CHARACTER_REFERENCE(1260, + /* l a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, + 0, 0x29b4 _ 0) +NAMED_CHARACTER_REFERENCE(1261, + /* l a */ 'g' _ 'r' _ 'a' _ 'n' _ ';', 5, 0, + 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(1262, + /* l a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0, + 0x03bb _ 0) +NAMED_CHARACTER_REFERENCE(1263, /* l a */ 'n' _ 'g' _ ';', 3, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(1264, + /* l a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2991 _ 0) +NAMED_CHARACTER_REFERENCE(1265, + /* l a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0, + 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(1266, /* l a */ 'p' _ ';', 2, 0, 0x2a85 _ 0) +NAMED_CHARACTER_REFERENCE(1267, /* l a */ 'q' _ 'u' _ 'o', 3, 0, 0x00ab _ 0) +NAMED_CHARACTER_REFERENCE(1268, + /* l a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00ab _ 0) +NAMED_CHARACTER_REFERENCE(1269, /* l a */ 'r' _ 'r' _ ';', 3, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(1270, + /* l a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e4 _ 0) +NAMED_CHARACTER_REFERENCE(1271, + /* l a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0, + 0x291f _ 0) +NAMED_CHARACTER_REFERENCE(1272, + /* l a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0, + 0x291d _ 0) +NAMED_CHARACTER_REFERENCE(1273, + /* l a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, + 0x21a9 _ 0) +NAMED_CHARACTER_REFERENCE(1274, + /* l a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0, + 0x21ab _ 0) +NAMED_CHARACTER_REFERENCE(1275, + /* l a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0, + 0x2939 _ 0) +NAMED_CHARACTER_REFERENCE(1276, + /* l a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0, + 0x2973 _ 0) +NAMED_CHARACTER_REFERENCE(1277, + /* l a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, + 0x21a2 _ 0) +NAMED_CHARACTER_REFERENCE(1278, /* l a */ 't' _ ';', 2, 0, 0x2aab _ 0) +NAMED_CHARACTER_REFERENCE(1279, + /* l a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, + 0x2919 _ 0) +NAMED_CHARACTER_REFERENCE(1280, /* l a */ 't' _ 'e' _ ';', 3, 0, 0x2aad _ 0) +NAMED_CHARACTER_REFERENCE(1281, + /* l a */ 't' _ 'e' _ 's' _ ';', 4, 0, + 0x2aad _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1282, + /* l b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290c _ 0) +NAMED_CHARACTER_REFERENCE(1283, + /* l b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2772 _ 0) +NAMED_CHARACTER_REFERENCE(1284, + /* l b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0, + 0x007b _ 0) +NAMED_CHARACTER_REFERENCE(1285, + /* l b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0, + 0x005b _ 0) +NAMED_CHARACTER_REFERENCE(1286, + /* l b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298b _ 0) +NAMED_CHARACTER_REFERENCE(1287, + /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0, + 0x298f _ 0) +NAMED_CHARACTER_REFERENCE(1288, + /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0, + 0x298d _ 0) +NAMED_CHARACTER_REFERENCE(1289, + /* l c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x013e _ 0) +NAMED_CHARACTER_REFERENCE(1290, + /* l c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x013c _ 0) +NAMED_CHARACTER_REFERENCE(1291, + /* l c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2308 _ 0) +NAMED_CHARACTER_REFERENCE(1292, /* l c */ 'u' _ 'b' _ ';', 3, 0, 0x007b _ 0) +NAMED_CHARACTER_REFERENCE(1293, /* l c */ 'y' _ ';', 2, 0, 0x043b _ 0) +NAMED_CHARACTER_REFERENCE(1294, /* l d */ 'c' _ 'a' _ ';', 3, 0, 0x2936 _ 0) +NAMED_CHARACTER_REFERENCE(1295, + /* l d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201c _ 0) +NAMED_CHARACTER_REFERENCE(1296, + /* l d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, + 0x201e _ 0) +NAMED_CHARACTER_REFERENCE(1297, + /* l d */ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, + 0x2967 _ 0) +NAMED_CHARACTER_REFERENCE(1298, + /* l d */ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, + 0, 0x294b _ 0) +NAMED_CHARACTER_REFERENCE(1299, /* l d */ 's' _ 'h' _ ';', 3, 0, 0x21b2 _ 0) +NAMED_CHARACTER_REFERENCE(1300, /* l e */ ';', 1, 0, 0x2264 _ 0) +NAMED_CHARACTER_REFERENCE( + 1301, + /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE( + 1302, + /* l e */ + 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 12, + 0, 0x21a2 _ 0) +NAMED_CHARACTER_REFERENCE( + 1303, + /* l e */ + 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', + 14, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE( + 1304, + /* l e */ + 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 12, + 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE( + 1305, + /* l e */ + 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', + 13, 0, 0x21c7 _ 0) +NAMED_CHARACTER_REFERENCE( + 1306, + /* l e */ + 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE( + 1307, + /* l e */ + 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', + 14, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE( + 1308, + /* l e */ + 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', + 16, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE( + 1309, + /* l e */ + 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 18, 0, 0x21ad _ 0) +NAMED_CHARACTER_REFERENCE( + 1310, + /* l e */ + 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', + 13, 0, 0x22cb _ 0) +NAMED_CHARACTER_REFERENCE(1311, /* l e */ 'g' _ ';', 2, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE(1312, /* l e */ 'q' _ ';', 2, 0, 0x2264 _ 0) +NAMED_CHARACTER_REFERENCE(1313, /* l e */ 'q' _ 'q' _ ';', 3, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(1314, + /* l e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, + 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(1315, /* l e */ 's' _ ';', 2, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(1316, + /* l e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa8 _ 0) +NAMED_CHARACTER_REFERENCE(1317, + /* l e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2a7f _ 0) +NAMED_CHARACTER_REFERENCE(1318, + /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0, + 0x2a81 _ 0) +NAMED_CHARACTER_REFERENCE(1319, + /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 7, + 0, 0x2a83 _ 0) +NAMED_CHARACTER_REFERENCE(1320, + /* l e */ 's' _ 'g' _ ';', 3, 0, 0x22da _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1321, + /* l e */ 's' _ 'g' _ 'e' _ 's' _ ';', 5, 0, + 0x2a93 _ 0) +NAMED_CHARACTER_REFERENCE( + 1322, + /* l e */ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, + 0x2a85 _ 0) +NAMED_CHARACTER_REFERENCE(1323, + /* l e */ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0, + 0x22d6 _ 0) +NAMED_CHARACTER_REFERENCE( + 1324, + /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 8, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE( + 1325, + /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 9, 0, + 0x2a8b _ 0) +NAMED_CHARACTER_REFERENCE(1326, + /* l e */ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 6, 0, + 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(1327, + /* l e */ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0, + 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(1328, + /* l f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, + 0x297c _ 0) +NAMED_CHARACTER_REFERENCE(1329, + /* l f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0, + 0x230a _ 0) +NAMED_CHARACTER_REFERENCE(1330, /* l f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd29) +NAMED_CHARACTER_REFERENCE(1331, /* l g */ ';', 1, 0, 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(1332, /* l g */ 'E' _ ';', 2, 0, 0x2a91 _ 0) +NAMED_CHARACTER_REFERENCE(1333, + /* l h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE(1334, + /* l h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE(1335, + /* l h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0, + 0x296a _ 0) +NAMED_CHARACTER_REFERENCE(1336, + /* l h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2584 _ 0) +NAMED_CHARACTER_REFERENCE(1337, /* l j */ 'c' _ 'y' _ ';', 3, 0, 0x0459 _ 0) +NAMED_CHARACTER_REFERENCE(1338, /* l l */ ';', 1, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(1339, + /* l l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c7 _ 0) +NAMED_CHARACTER_REFERENCE(1340, + /* l l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, + 0, 0x231e _ 0) +NAMED_CHARACTER_REFERENCE(1341, + /* l l */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0, + 0x296b _ 0) +NAMED_CHARACTER_REFERENCE(1342, + /* l l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25fa _ 0) +NAMED_CHARACTER_REFERENCE(1343, + /* l m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x0140 _ 0) +NAMED_CHARACTER_REFERENCE(1344, + /* l m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0, + 0x23b0 _ 0) +NAMED_CHARACTER_REFERENCE( + 1345, + /* l m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0, + 0x23b0 _ 0) +NAMED_CHARACTER_REFERENCE(1346, /* l n */ 'E' _ ';', 2, 0, 0x2268 _ 0) +NAMED_CHARACTER_REFERENCE(1347, /* l n */ 'a' _ 'p' _ ';', 3, 0, 0x2a89 _ 0) +NAMED_CHARACTER_REFERENCE(1348, + /* l n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, + 0, 0x2a89 _ 0) +NAMED_CHARACTER_REFERENCE(1349, /* l n */ 'e' _ ';', 2, 0, 0x2a87 _ 0) +NAMED_CHARACTER_REFERENCE(1350, /* l n */ 'e' _ 'q' _ ';', 3, 0, 0x2a87 _ 0) +NAMED_CHARACTER_REFERENCE(1351, + /* l n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2268 _ 0) +NAMED_CHARACTER_REFERENCE(1352, + /* l n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e6 _ 0) +NAMED_CHARACTER_REFERENCE(1353, + /* l o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ec _ 0) +NAMED_CHARACTER_REFERENCE(1354, + /* l o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fd _ 0) +NAMED_CHARACTER_REFERENCE(1355, + /* l o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e6 _ 0) +NAMED_CHARACTER_REFERENCE( + 1356, + /* l o */ + 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, + 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE( + 1357, + /* l o */ + 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 17, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE( + 1358, + /* l o */ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 9, 0, + 0x27fc _ 0) +NAMED_CHARACTER_REFERENCE( + 1359, + /* l o */ + 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 13, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE( + 1360, + /* l o */ + 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, + 0, 0x21ab _ 0) +NAMED_CHARACTER_REFERENCE( + 1361, + /* l o */ + 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 13, 0, 0x21ac _ 0) +NAMED_CHARACTER_REFERENCE(1362, + /* l o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2985 _ 0) +NAMED_CHARACTER_REFERENCE(1363, + /* l o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5d) +NAMED_CHARACTER_REFERENCE(1364, + /* l o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, + 0x2a2d _ 0) +NAMED_CHARACTER_REFERENCE(1365, + /* l o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0, + 0x2a34 _ 0) +NAMED_CHARACTER_REFERENCE(1366, + /* l o */ 'w' _ 'a' _ 's' _ 't' _ ';', 5, 0, + 0x2217 _ 0) +NAMED_CHARACTER_REFERENCE(1367, + /* l o */ 'w' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x005f _ 0) +NAMED_CHARACTER_REFERENCE(1368, /* l o */ 'z' _ ';', 2, 0, 0x25ca _ 0) +NAMED_CHARACTER_REFERENCE(1369, + /* l o */ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 6, 0, + 0x25ca _ 0) +NAMED_CHARACTER_REFERENCE(1370, /* l o */ 'z' _ 'f' _ ';', 3, 0, 0x29eb _ 0) +NAMED_CHARACTER_REFERENCE(1371, /* l p */ 'a' _ 'r' _ ';', 3, 0, 0x0028 _ 0) +NAMED_CHARACTER_REFERENCE(1372, + /* l p */ 'a' _ 'r' _ 'l' _ 't' _ ';', 5, 0, + 0x2993 _ 0) +NAMED_CHARACTER_REFERENCE(1373, + /* l r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE(1374, + /* l r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, + 0, 0x231f _ 0) +NAMED_CHARACTER_REFERENCE(1375, + /* l r */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE(1376, + /* l r */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0, + 0x296d _ 0) +NAMED_CHARACTER_REFERENCE(1377, /* l r */ 'm' _ ';', 2, 0, 0x200e _ 0) +NAMED_CHARACTER_REFERENCE(1378, + /* l r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22bf _ 0) +NAMED_CHARACTER_REFERENCE(1379, + /* l s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0, + 0x2039 _ 0) +NAMED_CHARACTER_REFERENCE(1380, + /* l s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc1) +NAMED_CHARACTER_REFERENCE(1381, /* l s */ 'h' _ ';', 2, 0, 0x21b0 _ 0) +NAMED_CHARACTER_REFERENCE(1382, /* l s */ 'i' _ 'm' _ ';', 3, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(1383, + /* l s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8d _ 0) +NAMED_CHARACTER_REFERENCE(1384, + /* l s */ 'i' _ 'm' _ 'g' _ ';', 4, 0, 0x2a8f _ 0) +NAMED_CHARACTER_REFERENCE(1385, /* l s */ 'q' _ 'b' _ ';', 3, 0, 0x005b _ 0) +NAMED_CHARACTER_REFERENCE(1386, + /* l s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2018 _ 0) +NAMED_CHARACTER_REFERENCE(1387, + /* l s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, + 0x201a _ 0) +NAMED_CHARACTER_REFERENCE(1388, + /* l s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0142 _ 0) +NAMED_CHARACTER_REFERENCE(1389, /* l t */ 0, 0, 1, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(1390, /* l t */ ';', 1, 0, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(1391, /* l t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa6 _ 0) +NAMED_CHARACTER_REFERENCE(1392, + /* l t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a79 _ 0) +NAMED_CHARACTER_REFERENCE(1393, + /* l t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d6 _ 0) +NAMED_CHARACTER_REFERENCE(1394, + /* l t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0, + 0x22cb _ 0) +NAMED_CHARACTER_REFERENCE(1395, + /* l t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, + 0x22c9 _ 0) +NAMED_CHARACTER_REFERENCE(1396, + /* l t */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, + 0x2976 _ 0) +NAMED_CHARACTER_REFERENCE(1397, + /* l t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0, + 0x2a7b _ 0) +NAMED_CHARACTER_REFERENCE(1398, + /* l t */ 'r' _ 'P' _ 'a' _ 'r' _ ';', 5, 0, + 0x2996 _ 0) +NAMED_CHARACTER_REFERENCE(1399, /* l t */ 'r' _ 'i' _ ';', 3, 0, 0x25c3 _ 0) +NAMED_CHARACTER_REFERENCE(1400, + /* l t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE(1401, + /* l t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25c2 _ 0) +NAMED_CHARACTER_REFERENCE(1402, + /* l u */ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, + 0, 0x294a _ 0) +NAMED_CHARACTER_REFERENCE(1403, + /* l u */ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, + 0x2966 _ 0) +NAMED_CHARACTER_REFERENCE( + 1404, + /* l v */ 'e' _ 'r' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, + 0x2268 _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1405, + /* l v */ 'n' _ 'E' _ ';', 3, 0, 0x2268 _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1406, + /* m D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x223a _ 0) +NAMED_CHARACTER_REFERENCE(1407, /* m a */ 'c' _ 'r', 2, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1408, /* m a */ 'c' _ 'r' _ ';', 3, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1409, /* m a */ 'l' _ 'e' _ ';', 3, 0, 0x2642 _ 0) +NAMED_CHARACTER_REFERENCE(1410, /* m a */ 'l' _ 't' _ ';', 3, 0, 0x2720 _ 0) +NAMED_CHARACTER_REFERENCE(1411, + /* m a */ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 6, 0, + 0x2720 _ 0) +NAMED_CHARACTER_REFERENCE(1412, /* m a */ 'p' _ ';', 2, 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE(1413, + /* m a */ 'p' _ 's' _ 't' _ 'o' _ ';', 5, 0, + 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE( + 1414, + /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 9, 0, + 0x21a7 _ 0) +NAMED_CHARACTER_REFERENCE( + 1415, + /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 9, 0, + 0x21a4 _ 0) +NAMED_CHARACTER_REFERENCE(1416, + /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 7, + 0, 0x21a5 _ 0) +NAMED_CHARACTER_REFERENCE(1417, + /* m a */ 'r' _ 'k' _ 'e' _ 'r' _ ';', 5, 0, + 0x25ae _ 0) +NAMED_CHARACTER_REFERENCE(1418, + /* m c */ 'o' _ 'm' _ 'm' _ 'a' _ ';', 5, 0, + 0x2a29 _ 0) +NAMED_CHARACTER_REFERENCE(1419, /* m c */ 'y' _ ';', 2, 0, 0x043c _ 0) +NAMED_CHARACTER_REFERENCE(1420, + /* m d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2014 _ 0) +NAMED_CHARACTER_REFERENCE( + 1421, + /* m e */ + 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, + 0, 0x2221 _ 0) +NAMED_CHARACTER_REFERENCE(1422, /* m f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2a) +NAMED_CHARACTER_REFERENCE(1423, /* m h */ 'o' _ ';', 2, 0, 0x2127 _ 0) +NAMED_CHARACTER_REFERENCE(1424, /* m i */ 'c' _ 'r' _ 'o', 3, 0, 0x00b5 _ 0) +NAMED_CHARACTER_REFERENCE(1425, + /* m i */ 'c' _ 'r' _ 'o' _ ';', 4, 0, 0x00b5 _ 0) +NAMED_CHARACTER_REFERENCE(1426, /* m i */ 'd' _ ';', 2, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1427, + /* m i */ 'd' _ 'a' _ 's' _ 't' _ ';', 5, 0, + 0x002a _ 0) +NAMED_CHARACTER_REFERENCE(1428, + /* m i */ 'd' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, + 0x2af0 _ 0) +NAMED_CHARACTER_REFERENCE(1429, + /* m i */ 'd' _ 'd' _ 'o' _ 't', 4, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(1430, + /* m i */ 'd' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(1431, + /* m i */ 'n' _ 'u' _ 's' _ ';', 4, 0, 0x2212 _ 0) +NAMED_CHARACTER_REFERENCE(1432, + /* m i */ 'n' _ 'u' _ 's' _ 'b' _ ';', 5, 0, + 0x229f _ 0) +NAMED_CHARACTER_REFERENCE(1433, + /* m i */ 'n' _ 'u' _ 's' _ 'd' _ ';', 5, 0, + 0x2238 _ 0) +NAMED_CHARACTER_REFERENCE(1434, + /* m i */ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 6, 0, + 0x2a2a _ 0) +NAMED_CHARACTER_REFERENCE(1435, /* m l */ 'c' _ 'p' _ ';', 3, 0, 0x2adb _ 0) +NAMED_CHARACTER_REFERENCE(1436, /* m l */ 'd' _ 'r' _ ';', 3, 0, 0x2026 _ 0) +NAMED_CHARACTER_REFERENCE(1437, + /* m n */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, + 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(1438, + /* m o */ 'd' _ 'e' _ 'l' _ 's' _ ';', 5, 0, + 0x22a7 _ 0) +NAMED_CHARACTER_REFERENCE(1439, + /* m o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5e) +NAMED_CHARACTER_REFERENCE(1440, /* m p */ ';', 1, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(1441, + /* m s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc2) +NAMED_CHARACTER_REFERENCE(1442, + /* m s */ 't' _ 'p' _ 'o' _ 's' _ ';', 5, 0, + 0x223e _ 0) +NAMED_CHARACTER_REFERENCE(1443, /* m u */ ';', 1, 0, 0x03bc _ 0) +NAMED_CHARACTER_REFERENCE(1444, + /* m u */ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 7, + 0, 0x22b8 _ 0) +NAMED_CHARACTER_REFERENCE(1445, + /* m u */ 'm' _ 'a' _ 'p' _ ';', 4, 0, 0x22b8 _ 0) +NAMED_CHARACTER_REFERENCE(1446, /* n G */ 'g' _ ';', 2, 0, 0x22d9 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1447, /* n G */ 't' _ ';', 2, 0, 0x226b _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1448, + /* n G */ 't' _ 'v' _ ';', 3, 0, 0x226b _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 1449, + /* n L */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, + 0x21cd _ 0) +NAMED_CHARACTER_REFERENCE( + 1450, + /* n L */ + 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x21ce _ 0) +NAMED_CHARACTER_REFERENCE(1451, /* n L */ 'l' _ ';', 2, 0, 0x22d8 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1452, /* n L */ 't' _ ';', 2, 0, 0x226a _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1453, + /* n L */ 't' _ 'v' _ ';', 3, 0, 0x226a _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 1454, + /* n R */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, + 0x21cf _ 0) +NAMED_CHARACTER_REFERENCE(1455, + /* n V */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x22af _ 0) +NAMED_CHARACTER_REFERENCE(1456, + /* n V */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x22ae _ 0) +NAMED_CHARACTER_REFERENCE(1457, + /* n a */ 'b' _ 'l' _ 'a' _ ';', 4, 0, 0x2207 _ 0) +NAMED_CHARACTER_REFERENCE(1458, + /* n a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0144 _ 0) +NAMED_CHARACTER_REFERENCE(1459, + /* n a */ 'n' _ 'g' _ ';', 3, 0, 0x2220 _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1460, /* n a */ 'p' _ ';', 2, 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(1461, + /* n a */ 'p' _ 'E' _ ';', 3, 0, 0x2a70 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1462, + /* n a */ 'p' _ 'i' _ 'd' _ ';', 4, 0, + 0x224b _ 0x0338) +NAMED_CHARACTER_REFERENCE(1463, + /* n a */ 'p' _ 'o' _ 's' _ ';', 4, 0, 0x0149 _ 0) +NAMED_CHARACTER_REFERENCE(1464, + /* n a */ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 6, 0, + 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(1465, + /* n a */ 't' _ 'u' _ 'r' _ ';', 4, 0, 0x266e _ 0) +NAMED_CHARACTER_REFERENCE(1466, + /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 6, 0, + 0x266e _ 0) +NAMED_CHARACTER_REFERENCE(1467, + /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 7, + 0, 0x2115 _ 0) +NAMED_CHARACTER_REFERENCE(1468, /* n b */ 's' _ 'p', 2, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(1469, /* n b */ 's' _ 'p' _ ';', 3, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(1470, + /* n b */ 'u' _ 'm' _ 'p' _ ';', 4, 0, + 0x224e _ 0x0338) +NAMED_CHARACTER_REFERENCE(1471, + /* n b */ 'u' _ 'm' _ 'p' _ 'e' _ ';', 5, 0, + 0x224f _ 0x0338) +NAMED_CHARACTER_REFERENCE(1472, /* n c */ 'a' _ 'p' _ ';', 3, 0, 0x2a43 _ 0) +NAMED_CHARACTER_REFERENCE(1473, + /* n c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0148 _ 0) +NAMED_CHARACTER_REFERENCE(1474, + /* n c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0146 _ 0) +NAMED_CHARACTER_REFERENCE(1475, + /* n c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x2247 _ 0) +NAMED_CHARACTER_REFERENCE(1476, + /* n c */ 'o' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 7, + 0, 0x2a6d _ 0x0338) +NAMED_CHARACTER_REFERENCE(1477, /* n c */ 'u' _ 'p' _ ';', 3, 0, 0x2a42 _ 0) +NAMED_CHARACTER_REFERENCE(1478, /* n c */ 'y' _ ';', 2, 0, 0x043d _ 0) +NAMED_CHARACTER_REFERENCE(1479, + /* n d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2013 _ 0) +NAMED_CHARACTER_REFERENCE(1480, /* n e */ ';', 1, 0, 0x2260 _ 0) +NAMED_CHARACTER_REFERENCE(1481, + /* n e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d7 _ 0) +NAMED_CHARACTER_REFERENCE(1482, + /* n e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, + 0x2924 _ 0) +NAMED_CHARACTER_REFERENCE(1483, + /* n e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(1484, + /* n e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(1485, + /* n e */ 'd' _ 'o' _ 't' _ ';', 4, 0, + 0x2250 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1486, + /* n e */ 'q' _ 'u' _ 'i' _ 'v' _ ';', 5, 0, + 0x2262 _ 0) +NAMED_CHARACTER_REFERENCE(1487, + /* n e */ 's' _ 'e' _ 'a' _ 'r' _ ';', 5, 0, + 0x2928 _ 0) +NAMED_CHARACTER_REFERENCE(1488, + /* n e */ 's' _ 'i' _ 'm' _ ';', 4, 0, + 0x2242 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1489, + /* n e */ 'x' _ 'i' _ 's' _ 't' _ ';', 5, 0, + 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(1490, + /* n e */ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 6, 0, + 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(1491, /* n f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2b) +NAMED_CHARACTER_REFERENCE(1492, /* n g */ 'E' _ ';', 2, 0, 0x2267 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1493, /* n g */ 'e' _ ';', 2, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(1494, /* n g */ 'e' _ 'q' _ ';', 3, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(1495, + /* n g */ 'e' _ 'q' _ 'q' _ ';', 4, 0, + 0x2267 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 1496, + /* n g */ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 8, 0, + 0x2a7e _ 0x0338) +NAMED_CHARACTER_REFERENCE(1497, + /* n g */ 'e' _ 's' _ ';', 3, 0, 0x2a7e _ 0x0338) +NAMED_CHARACTER_REFERENCE(1498, + /* n g */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2275 _ 0) +NAMED_CHARACTER_REFERENCE(1499, /* n g */ 't' _ ';', 2, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(1500, /* n g */ 't' _ 'r' _ ';', 3, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(1501, + /* n h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21ce _ 0) +NAMED_CHARACTER_REFERENCE(1502, + /* n h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ae _ 0) +NAMED_CHARACTER_REFERENCE(1503, + /* n h */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2af2 _ 0) +NAMED_CHARACTER_REFERENCE(1504, /* n i */ ';', 1, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(1505, /* n i */ 's' _ ';', 2, 0, 0x22fc _ 0) +NAMED_CHARACTER_REFERENCE(1506, /* n i */ 's' _ 'd' _ ';', 3, 0, 0x22fa _ 0) +NAMED_CHARACTER_REFERENCE(1507, /* n i */ 'v' _ ';', 2, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(1508, /* n j */ 'c' _ 'y' _ ';', 3, 0, 0x045a _ 0) +NAMED_CHARACTER_REFERENCE(1509, + /* n l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cd _ 0) +NAMED_CHARACTER_REFERENCE(1510, /* n l */ 'E' _ ';', 2, 0, 0x2266 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1511, + /* n l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219a _ 0) +NAMED_CHARACTER_REFERENCE(1512, /* n l */ 'd' _ 'r' _ ';', 3, 0, 0x2025 _ 0) +NAMED_CHARACTER_REFERENCE(1513, /* n l */ 'e' _ ';', 2, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE( + 1514, + /* n l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, + 0x219a _ 0) +NAMED_CHARACTER_REFERENCE( + 1515, + /* n l */ + 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x21ae _ 0) +NAMED_CHARACTER_REFERENCE(1516, /* n l */ 'e' _ 'q' _ ';', 3, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE(1517, + /* n l */ 'e' _ 'q' _ 'q' _ ';', 4, 0, + 0x2266 _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 1518, + /* n l */ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 8, 0, + 0x2a7d _ 0x0338) +NAMED_CHARACTER_REFERENCE(1519, + /* n l */ 'e' _ 's' _ ';', 3, 0, 0x2a7d _ 0x0338) +NAMED_CHARACTER_REFERENCE(1520, + /* n l */ 'e' _ 's' _ 's' _ ';', 4, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(1521, + /* n l */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2274 _ 0) +NAMED_CHARACTER_REFERENCE(1522, /* n l */ 't' _ ';', 2, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(1523, + /* n l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE(1524, + /* n l */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0, + 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(1525, /* n m */ 'i' _ 'd' _ ';', 3, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1526, + /* n o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5f) +NAMED_CHARACTER_REFERENCE(1527, /* n o */ 't', 1, 0, 0x00ac _ 0) +NAMED_CHARACTER_REFERENCE(1528, /* n o */ 't' _ ';', 2, 0, 0x00ac _ 0) +NAMED_CHARACTER_REFERENCE(1529, + /* n o */ 't' _ 'i' _ 'n' _ ';', 4, 0, 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(1530, + /* n o */ 't' _ 'i' _ 'n' _ 'E' _ ';', 5, 0, + 0x22f9 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1531, + /* n o */ 't' _ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 7, + 0, 0x22f5 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1532, + /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 6, 0, + 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(1533, + /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 6, 0, + 0x22f7 _ 0) +NAMED_CHARACTER_REFERENCE(1534, + /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 6, 0, + 0x22f6 _ 0) +NAMED_CHARACTER_REFERENCE(1535, + /* n o */ 't' _ 'n' _ 'i' _ ';', 4, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(1536, + /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 6, 0, + 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(1537, + /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 6, 0, + 0x22fe _ 0) +NAMED_CHARACTER_REFERENCE(1538, + /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 6, 0, + 0x22fd _ 0) +NAMED_CHARACTER_REFERENCE(1539, /* n p */ 'a' _ 'r' _ ';', 3, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE( + 1540, + /* n p */ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 8, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1541, + /* n p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0, + 0x2afd _ 0x20e5) +NAMED_CHARACTER_REFERENCE(1542, + /* n p */ 'a' _ 'r' _ 't' _ ';', 4, 0, + 0x2202 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1543, + /* n p */ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 6, 0, + 0x2a14 _ 0) +NAMED_CHARACTER_REFERENCE(1544, /* n p */ 'r' _ ';', 2, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(1545, + /* n p */ 'r' _ 'c' _ 'u' _ 'e' _ ';', 5, 0, + 0x22e0 _ 0) +NAMED_CHARACTER_REFERENCE(1546, + /* n p */ 'r' _ 'e' _ ';', 3, 0, 0x2aaf _ 0x0338) +NAMED_CHARACTER_REFERENCE(1547, + /* n p */ 'r' _ 'e' _ 'c' _ ';', 4, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(1548, + /* n p */ 'r' _ 'e' _ 'c' _ 'e' _ 'q' _ ';', 6, 0, + 0x2aaf _ 0x0338) +NAMED_CHARACTER_REFERENCE(1549, + /* n r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cf _ 0) +NAMED_CHARACTER_REFERENCE(1550, + /* n r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219b _ 0) +NAMED_CHARACTER_REFERENCE(1551, + /* n r */ 'a' _ 'r' _ 'r' _ 'c' _ ';', 5, 0, + 0x2933 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1552, + /* n r */ 'a' _ 'r' _ 'r' _ 'w' _ ';', 5, 0, + 0x219d _ 0x0338) +NAMED_CHARACTER_REFERENCE( + 1553, + /* n r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, + 0x219b _ 0) +NAMED_CHARACTER_REFERENCE(1554, + /* n r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE(1555, + /* n r */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0, + 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(1556, /* n s */ 'c' _ ';', 2, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(1557, + /* n s */ 'c' _ 'c' _ 'u' _ 'e' _ ';', 5, 0, + 0x22e1 _ 0) +NAMED_CHARACTER_REFERENCE(1558, + /* n s */ 'c' _ 'e' _ ';', 3, 0, 0x2ab0 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1559, + /* n s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc3) +NAMED_CHARACTER_REFERENCE( + 1560, + /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 8, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE( + 1561, + /* n s */ + 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', + 13, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1562, /* n s */ 'i' _ 'm' _ ';', 3, 0, 0x2241 _ 0) +NAMED_CHARACTER_REFERENCE(1563, + /* n s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(1564, + /* n s */ 'i' _ 'm' _ 'e' _ 'q' _ ';', 5, 0, + 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(1565, + /* n s */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1566, + /* n s */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1567, + /* n s */ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0, + 0x22e2 _ 0) +NAMED_CHARACTER_REFERENCE(1568, + /* n s */ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0, + 0x22e3 _ 0) +NAMED_CHARACTER_REFERENCE(1569, /* n s */ 'u' _ 'b' _ ';', 3, 0, 0x2284 _ 0) +NAMED_CHARACTER_REFERENCE(1570, + /* n s */ 'u' _ 'b' _ 'E' _ ';', 4, 0, + 0x2ac5 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1571, + /* n s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE(1572, + /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 6, 0, + 0x2282 _ 0x20d2) +NAMED_CHARACTER_REFERENCE( + 1573, + /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE( + 1574, + /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, + 0x2ac5 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1575, + /* n s */ 'u' _ 'c' _ 'c' _ ';', 4, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(1576, + /* n s */ 'u' _ 'c' _ 'c' _ 'e' _ 'q' _ ';', 6, 0, + 0x2ab0 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1577, /* n s */ 'u' _ 'p' _ ';', 3, 0, 0x2285 _ 0) +NAMED_CHARACTER_REFERENCE(1578, + /* n s */ 'u' _ 'p' _ 'E' _ ';', 4, 0, + 0x2ac6 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1579, + /* n s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(1580, + /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 6, 0, + 0x2283 _ 0x20d2) +NAMED_CHARACTER_REFERENCE( + 1581, + /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE( + 1582, + /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, + 0x2ac6 _ 0x0338) +NAMED_CHARACTER_REFERENCE(1583, /* n t */ 'g' _ 'l' _ ';', 3, 0, 0x2279 _ 0) +NAMED_CHARACTER_REFERENCE(1584, + /* n t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f1 _ 0) +NAMED_CHARACTER_REFERENCE(1585, + /* n t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x00f1 _ 0) +NAMED_CHARACTER_REFERENCE(1586, /* n t */ 'l' _ 'g' _ ';', 3, 0, 0x2278 _ 0) +NAMED_CHARACTER_REFERENCE( + 1587, + /* n t */ + 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, + 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE( + 1588, + /* n t */ + 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', + 14, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE( + 1589, + /* n t */ + 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 13, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE( + 1590, + /* n t */ + 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', + 15, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(1591, /* n u */ ';', 1, 0, 0x03bd _ 0) +NAMED_CHARACTER_REFERENCE(1592, /* n u */ 'm' _ ';', 2, 0, 0x0023 _ 0) +NAMED_CHARACTER_REFERENCE(1593, + /* n u */ 'm' _ 'e' _ 'r' _ 'o' _ ';', 5, 0, + 0x2116 _ 0) +NAMED_CHARACTER_REFERENCE(1594, + /* n u */ 'm' _ 's' _ 'p' _ ';', 4, 0, 0x2007 _ 0) +NAMED_CHARACTER_REFERENCE(1595, + /* n v */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x22ad _ 0) +NAMED_CHARACTER_REFERENCE(1596, + /* n v */ 'H' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, + 0x2904 _ 0) +NAMED_CHARACTER_REFERENCE(1597, + /* n v */ 'a' _ 'p' _ ';', 3, 0, 0x224d _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1598, + /* n v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x22ac _ 0) +NAMED_CHARACTER_REFERENCE(1599, + /* n v */ 'g' _ 'e' _ ';', 3, 0, 0x2265 _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1600, + /* n v */ 'g' _ 't' _ ';', 3, 0, 0x003e _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1601, + /* n v */ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0, + 0x29de _ 0) +NAMED_CHARACTER_REFERENCE(1602, + /* n v */ 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0, + 0x2902 _ 0) +NAMED_CHARACTER_REFERENCE(1603, + /* n v */ 'l' _ 'e' _ ';', 3, 0, 0x2264 _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1604, + /* n v */ 'l' _ 't' _ ';', 3, 0, 0x003c _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1605, + /* n v */ 'l' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 6, 0, + 0x22b4 _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1606, + /* n v */ 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0, + 0x2903 _ 0) +NAMED_CHARACTER_REFERENCE(1607, + /* n v */ 'r' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 6, 0, + 0x22b5 _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1608, + /* n v */ 's' _ 'i' _ 'm' _ ';', 4, 0, + 0x223c _ 0x20d2) +NAMED_CHARACTER_REFERENCE(1609, + /* n w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d6 _ 0) +NAMED_CHARACTER_REFERENCE(1610, + /* n w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, + 0x2923 _ 0) +NAMED_CHARACTER_REFERENCE(1611, + /* n w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(1612, + /* n w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(1613, + /* n w */ 'n' _ 'e' _ 'a' _ 'r' _ ';', 5, 0, + 0x2927 _ 0) +NAMED_CHARACTER_REFERENCE(1614, /* o S */ ';', 1, 0, 0x24c8 _ 0) +NAMED_CHARACTER_REFERENCE(1615, + /* o a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00f3 _ 0) +NAMED_CHARACTER_REFERENCE(1616, + /* o a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00f3 _ 0) +NAMED_CHARACTER_REFERENCE(1617, /* o a */ 's' _ 't' _ ';', 3, 0, 0x229b _ 0) +NAMED_CHARACTER_REFERENCE(1618, /* o c */ 'i' _ 'r' _ ';', 3, 0, 0x229a _ 0) +NAMED_CHARACTER_REFERENCE(1619, /* o c */ 'i' _ 'r' _ 'c', 3, 0, 0x00f4 _ 0) +NAMED_CHARACTER_REFERENCE(1620, + /* o c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00f4 _ 0) +NAMED_CHARACTER_REFERENCE(1621, /* o c */ 'y' _ ';', 2, 0, 0x043e _ 0) +NAMED_CHARACTER_REFERENCE(1622, + /* o d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x229d _ 0) +NAMED_CHARACTER_REFERENCE(1623, + /* o d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, + 0x0151 _ 0) +NAMED_CHARACTER_REFERENCE(1624, /* o d */ 'i' _ 'v' _ ';', 3, 0, 0x2a38 _ 0) +NAMED_CHARACTER_REFERENCE(1625, /* o d */ 'o' _ 't' _ ';', 3, 0, 0x2299 _ 0) +NAMED_CHARACTER_REFERENCE(1626, + /* o d */ 's' _ 'o' _ 'l' _ 'd' _ ';', 5, 0, + 0x29bc _ 0) +NAMED_CHARACTER_REFERENCE(1627, + /* o e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0153 _ 0) +NAMED_CHARACTER_REFERENCE(1628, + /* o f */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29bf _ 0) +NAMED_CHARACTER_REFERENCE(1629, /* o f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2c) +NAMED_CHARACTER_REFERENCE(1630, /* o g */ 'o' _ 'n' _ ';', 3, 0, 0x02db _ 0) +NAMED_CHARACTER_REFERENCE(1631, + /* o g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f2 _ 0) +NAMED_CHARACTER_REFERENCE(1632, + /* o g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00f2 _ 0) +NAMED_CHARACTER_REFERENCE(1633, /* o g */ 't' _ ';', 2, 0, 0x29c1 _ 0) +NAMED_CHARACTER_REFERENCE(1634, + /* o h */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x29b5 _ 0) +NAMED_CHARACTER_REFERENCE(1635, /* o h */ 'm' _ ';', 2, 0, 0x03a9 _ 0) +NAMED_CHARACTER_REFERENCE(1636, /* o i */ 'n' _ 't' _ ';', 3, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(1637, + /* o l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ba _ 0) +NAMED_CHARACTER_REFERENCE(1638, + /* o l */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29be _ 0) +NAMED_CHARACTER_REFERENCE(1639, + /* o l */ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0, + 0x29bb _ 0) +NAMED_CHARACTER_REFERENCE(1640, + /* o l */ 'i' _ 'n' _ 'e' _ ';', 4, 0, 0x203e _ 0) +NAMED_CHARACTER_REFERENCE(1641, /* o l */ 't' _ ';', 2, 0, 0x29c0 _ 0) +NAMED_CHARACTER_REFERENCE(1642, + /* o m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014d _ 0) +NAMED_CHARACTER_REFERENCE(1643, + /* o m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03c9 _ 0) +NAMED_CHARACTER_REFERENCE(1644, + /* o m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0, + 0x03bf _ 0) +NAMED_CHARACTER_REFERENCE(1645, /* o m */ 'i' _ 'd' _ ';', 3, 0, 0x29b6 _ 0) +NAMED_CHARACTER_REFERENCE(1646, + /* o m */ 'i' _ 'n' _ 'u' _ 's' _ ';', 5, 0, + 0x2296 _ 0) +NAMED_CHARACTER_REFERENCE(1647, + /* o o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd60) +NAMED_CHARACTER_REFERENCE(1648, /* o p */ 'a' _ 'r' _ ';', 3, 0, 0x29b7 _ 0) +NAMED_CHARACTER_REFERENCE(1649, + /* o p */ 'e' _ 'r' _ 'p' _ ';', 4, 0, 0x29b9 _ 0) +NAMED_CHARACTER_REFERENCE(1650, + /* o p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2295 _ 0) +NAMED_CHARACTER_REFERENCE(1651, /* o r */ ';', 1, 0, 0x2228 _ 0) +NAMED_CHARACTER_REFERENCE(1652, + /* o r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21bb _ 0) +NAMED_CHARACTER_REFERENCE(1653, /* o r */ 'd' _ ';', 2, 0, 0x2a5d _ 0) +NAMED_CHARACTER_REFERENCE(1654, + /* o r */ 'd' _ 'e' _ 'r' _ ';', 4, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1655, + /* o r */ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 6, 0, + 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1656, /* o r */ 'd' _ 'f', 2, 0, 0x00aa _ 0) +NAMED_CHARACTER_REFERENCE(1657, /* o r */ 'd' _ 'f' _ ';', 3, 0, 0x00aa _ 0) +NAMED_CHARACTER_REFERENCE(1658, /* o r */ 'd' _ 'm', 2, 0, 0x00ba _ 0) +NAMED_CHARACTER_REFERENCE(1659, /* o r */ 'd' _ 'm' _ ';', 3, 0, 0x00ba _ 0) +NAMED_CHARACTER_REFERENCE(1660, + /* o r */ 'i' _ 'g' _ 'o' _ 'f' _ ';', 5, 0, + 0x22b6 _ 0) +NAMED_CHARACTER_REFERENCE(1661, /* o r */ 'o' _ 'r' _ ';', 3, 0, 0x2a56 _ 0) +NAMED_CHARACTER_REFERENCE(1662, + /* o r */ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 6, 0, + 0x2a57 _ 0) +NAMED_CHARACTER_REFERENCE(1663, /* o r */ 'v' _ ';', 2, 0, 0x2a5b _ 0) +NAMED_CHARACTER_REFERENCE(1664, /* o s */ 'c' _ 'r' _ ';', 3, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1665, + /* o s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00f8 _ 0) +NAMED_CHARACTER_REFERENCE(1666, + /* o s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, + 0x00f8 _ 0) +NAMED_CHARACTER_REFERENCE(1667, /* o s */ 'o' _ 'l' _ ';', 3, 0, 0x2298 _ 0) +NAMED_CHARACTER_REFERENCE(1668, + /* o t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f5 _ 0) +NAMED_CHARACTER_REFERENCE(1669, + /* o t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x00f5 _ 0) +NAMED_CHARACTER_REFERENCE(1670, + /* o t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, + 0x2297 _ 0) +NAMED_CHARACTER_REFERENCE(1671, + /* o t */ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 7, + 0, 0x2a36 _ 0) +NAMED_CHARACTER_REFERENCE(1672, /* o u */ 'm' _ 'l', 2, 0, 0x00f6 _ 0) +NAMED_CHARACTER_REFERENCE(1673, /* o u */ 'm' _ 'l' _ ';', 3, 0, 0x00f6 _ 0) +NAMED_CHARACTER_REFERENCE(1674, + /* o v */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x233d _ 0) +NAMED_CHARACTER_REFERENCE(1675, /* p a */ 'r' _ ';', 2, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1676, /* p a */ 'r' _ 'a', 2, 0, 0x00b6 _ 0) +NAMED_CHARACTER_REFERENCE(1677, /* p a */ 'r' _ 'a' _ ';', 3, 0, 0x00b6 _ 0) +NAMED_CHARACTER_REFERENCE(1678, + /* p a */ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 7, + 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1679, + /* p a */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0, + 0x2af3 _ 0) +NAMED_CHARACTER_REFERENCE(1680, + /* p a */ 'r' _ 's' _ 'l' _ ';', 4, 0, 0x2afd _ 0) +NAMED_CHARACTER_REFERENCE(1681, /* p a */ 'r' _ 't' _ ';', 3, 0, 0x2202 _ 0) +NAMED_CHARACTER_REFERENCE(1682, /* p c */ 'y' _ ';', 2, 0, 0x043f _ 0) +NAMED_CHARACTER_REFERENCE(1683, + /* p e */ 'r' _ 'c' _ 'n' _ 't' _ ';', 5, 0, + 0x0025 _ 0) +NAMED_CHARACTER_REFERENCE(1684, + /* p e */ 'r' _ 'i' _ 'o' _ 'd' _ ';', 5, 0, + 0x002e _ 0) +NAMED_CHARACTER_REFERENCE(1685, + /* p e */ 'r' _ 'm' _ 'i' _ 'l' _ ';', 5, 0, + 0x2030 _ 0) +NAMED_CHARACTER_REFERENCE(1686, /* p e */ 'r' _ 'p' _ ';', 3, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(1687, + /* p e */ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 6, 0, + 0x2031 _ 0) +NAMED_CHARACTER_REFERENCE(1688, /* p f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2d) +NAMED_CHARACTER_REFERENCE(1689, /* p h */ 'i' _ ';', 2, 0, 0x03c6 _ 0) +NAMED_CHARACTER_REFERENCE(1690, /* p h */ 'i' _ 'v' _ ';', 3, 0, 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(1691, + /* p h */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0, + 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(1692, + /* p h */ 'o' _ 'n' _ 'e' _ ';', 4, 0, 0x260e _ 0) +NAMED_CHARACTER_REFERENCE(1693, /* p i */ ';', 1, 0, 0x03c0 _ 0) +NAMED_CHARACTER_REFERENCE( + 1694, + /* p i */ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0, 0x22d4 _ 0) +NAMED_CHARACTER_REFERENCE(1695, /* p i */ 'v' _ ';', 2, 0, 0x03d6 _ 0) +NAMED_CHARACTER_REFERENCE(1696, + /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ ';', 5, 0, + 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1697, + /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 6, 0, + 0x210e _ 0) +NAMED_CHARACTER_REFERENCE(1698, + /* p l */ 'a' _ 'n' _ 'k' _ 'v' _ ';', 5, 0, + 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1699, /* p l */ 'u' _ 's' _ ';', 3, 0, 0x002b _ 0) +NAMED_CHARACTER_REFERENCE(1700, + /* p l */ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 7, + 0, 0x2a23 _ 0) +NAMED_CHARACTER_REFERENCE(1701, + /* p l */ 'u' _ 's' _ 'b' _ ';', 4, 0, 0x229e _ 0) +NAMED_CHARACTER_REFERENCE(1702, + /* p l */ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, + 0x2a22 _ 0) +NAMED_CHARACTER_REFERENCE(1703, + /* p l */ 'u' _ 's' _ 'd' _ 'o' _ ';', 5, 0, + 0x2214 _ 0) +NAMED_CHARACTER_REFERENCE(1704, + /* p l */ 'u' _ 's' _ 'd' _ 'u' _ ';', 5, 0, + 0x2a25 _ 0) +NAMED_CHARACTER_REFERENCE(1705, + /* p l */ 'u' _ 's' _ 'e' _ ';', 4, 0, 0x2a72 _ 0) +NAMED_CHARACTER_REFERENCE(1706, + /* p l */ 'u' _ 's' _ 'm' _ 'n', 4, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1707, + /* p l */ 'u' _ 's' _ 'm' _ 'n' _ ';', 5, 0, + 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1708, + /* p l */ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0, + 0x2a26 _ 0) +NAMED_CHARACTER_REFERENCE(1709, + /* p l */ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 6, 0, + 0x2a27 _ 0) +NAMED_CHARACTER_REFERENCE(1710, /* p m */ ';', 1, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1711, + /* p o */ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, + 0, 0x2a15 _ 0) +NAMED_CHARACTER_REFERENCE(1712, + /* p o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd61) +NAMED_CHARACTER_REFERENCE(1713, /* p o */ 'u' _ 'n' _ 'd', 3, 0, 0x00a3 _ 0) +NAMED_CHARACTER_REFERENCE(1714, + /* p o */ 'u' _ 'n' _ 'd' _ ';', 4, 0, 0x00a3 _ 0) +NAMED_CHARACTER_REFERENCE(1715, /* p r */ ';', 1, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE(1716, /* p r */ 'E' _ ';', 2, 0, 0x2ab3 _ 0) +NAMED_CHARACTER_REFERENCE(1717, /* p r */ 'a' _ 'p' _ ';', 3, 0, 0x2ab7 _ 0) +NAMED_CHARACTER_REFERENCE(1718, + /* p r */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(1719, /* p r */ 'e' _ ';', 2, 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE(1720, /* p r */ 'e' _ 'c' _ ';', 3, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE( + 1721, + /* p r */ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, + 0x2ab7 _ 0) +NAMED_CHARACTER_REFERENCE( + 1722, + /* p r */ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0, + 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(1723, + /* p r */ 'e' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, + 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE( + 1724, + /* p r */ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, + 0x2ab9 _ 0) +NAMED_CHARACTER_REFERENCE(1725, + /* p r */ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, + 0, 0x2ab5 _ 0) +NAMED_CHARACTER_REFERENCE(1726, + /* p r */ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, + 0, 0x22e8 _ 0) +NAMED_CHARACTER_REFERENCE(1727, + /* p r */ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0, + 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(1728, + /* p r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2032 _ 0) +NAMED_CHARACTER_REFERENCE(1729, + /* p r */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, + 0x2119 _ 0) +NAMED_CHARACTER_REFERENCE(1730, /* p r */ 'n' _ 'E' _ ';', 3, 0, 0x2ab5 _ 0) +NAMED_CHARACTER_REFERENCE(1731, + /* p r */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2ab9 _ 0) +NAMED_CHARACTER_REFERENCE(1732, + /* p r */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0, + 0x22e8 _ 0) +NAMED_CHARACTER_REFERENCE(1733, /* p r */ 'o' _ 'd' _ ';', 3, 0, 0x220f _ 0) +NAMED_CHARACTER_REFERENCE(1734, + /* p r */ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 7, + 0, 0x232e _ 0) +NAMED_CHARACTER_REFERENCE(1735, + /* p r */ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, + 0, 0x2312 _ 0) +NAMED_CHARACTER_REFERENCE(1736, + /* p r */ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 7, + 0, 0x2313 _ 0) +NAMED_CHARACTER_REFERENCE(1737, /* p r */ 'o' _ 'p' _ ';', 3, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(1738, + /* p r */ 'o' _ 'p' _ 't' _ 'o' _ ';', 5, 0, + 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(1739, + /* p r */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(1740, + /* p r */ 'u' _ 'r' _ 'e' _ 'l' _ ';', 5, 0, + 0x22b0 _ 0) +NAMED_CHARACTER_REFERENCE(1741, + /* p s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc5) +NAMED_CHARACTER_REFERENCE(1742, /* p s */ 'i' _ ';', 2, 0, 0x03c8 _ 0) +NAMED_CHARACTER_REFERENCE(1743, + /* p u */ 'n' _ 'c' _ 's' _ 'p' _ ';', 5, 0, + 0x2008 _ 0) +NAMED_CHARACTER_REFERENCE(1744, /* q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2e) +NAMED_CHARACTER_REFERENCE(1745, /* q i */ 'n' _ 't' _ ';', 3, 0, 0x2a0c _ 0) +NAMED_CHARACTER_REFERENCE(1746, + /* q o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd62) +NAMED_CHARACTER_REFERENCE(1747, + /* q p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, + 0x2057 _ 0) +NAMED_CHARACTER_REFERENCE(1748, + /* q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc6) +NAMED_CHARACTER_REFERENCE( + 1749, + /* q u */ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 10, 0, + 0x210d _ 0) +NAMED_CHARACTER_REFERENCE(1750, + /* q u */ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 6, 0, + 0x2a16 _ 0) +NAMED_CHARACTER_REFERENCE(1751, + /* q u */ 'e' _ 's' _ 't' _ ';', 4, 0, 0x003f _ 0) +NAMED_CHARACTER_REFERENCE(1752, + /* q u */ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 6, 0, + 0x225f _ 0) +NAMED_CHARACTER_REFERENCE(1753, /* q u */ 'o' _ 't', 2, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(1754, /* q u */ 'o' _ 't' _ ';', 3, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(1755, + /* r A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21db _ 0) +NAMED_CHARACTER_REFERENCE(1756, /* r A */ 'r' _ 'r' _ ';', 3, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(1757, + /* r A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, + 0x291c _ 0) +NAMED_CHARACTER_REFERENCE(1758, + /* r B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290f _ 0) +NAMED_CHARACTER_REFERENCE(1759, /* r H */ 'a' _ 'r' _ ';', 3, 0, 0x2964 _ 0) +NAMED_CHARACTER_REFERENCE(1760, + /* r a */ 'c' _ 'e' _ ';', 3, 0, 0x223d _ 0x0331) +NAMED_CHARACTER_REFERENCE(1761, + /* r a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x0155 _ 0) +NAMED_CHARACTER_REFERENCE(1762, + /* r a */ 'd' _ 'i' _ 'c' _ ';', 4, 0, 0x221a _ 0) +NAMED_CHARACTER_REFERENCE(1763, + /* r a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, + 0, 0x29b3 _ 0) +NAMED_CHARACTER_REFERENCE(1764, /* r a */ 'n' _ 'g' _ ';', 3, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(1765, + /* r a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2992 _ 0) +NAMED_CHARACTER_REFERENCE(1766, + /* r a */ 'n' _ 'g' _ 'e' _ ';', 4, 0, 0x29a5 _ 0) +NAMED_CHARACTER_REFERENCE(1767, + /* r a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0, + 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(1768, /* r a */ 'q' _ 'u' _ 'o', 3, 0, 0x00bb _ 0) +NAMED_CHARACTER_REFERENCE(1769, + /* r a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00bb _ 0) +NAMED_CHARACTER_REFERENCE(1770, /* r a */ 'r' _ 'r' _ ';', 3, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1771, + /* r a */ 'r' _ 'r' _ 'a' _ 'p' _ ';', 5, 0, + 0x2975 _ 0) +NAMED_CHARACTER_REFERENCE(1772, + /* r a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e5 _ 0) +NAMED_CHARACTER_REFERENCE(1773, + /* r a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0, + 0x2920 _ 0) +NAMED_CHARACTER_REFERENCE(1774, + /* r a */ 'r' _ 'r' _ 'c' _ ';', 4, 0, 0x2933 _ 0) +NAMED_CHARACTER_REFERENCE(1775, + /* r a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0, + 0x291e _ 0) +NAMED_CHARACTER_REFERENCE(1776, + /* r a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, + 0x21aa _ 0) +NAMED_CHARACTER_REFERENCE(1777, + /* r a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0, + 0x21ac _ 0) +NAMED_CHARACTER_REFERENCE(1778, + /* r a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0, + 0x2945 _ 0) +NAMED_CHARACTER_REFERENCE(1779, + /* r a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0, + 0x2974 _ 0) +NAMED_CHARACTER_REFERENCE(1780, + /* r a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, + 0x21a3 _ 0) +NAMED_CHARACTER_REFERENCE(1781, + /* r a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x219d _ 0) +NAMED_CHARACTER_REFERENCE(1782, + /* r a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, + 0x291a _ 0) +NAMED_CHARACTER_REFERENCE(1783, + /* r a */ 't' _ 'i' _ 'o' _ ';', 4, 0, 0x2236 _ 0) +NAMED_CHARACTER_REFERENCE( + 1784, + /* r a */ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ 's' _ ';', 8, 0, 0x211a _ 0) +NAMED_CHARACTER_REFERENCE(1785, + /* r b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290d _ 0) +NAMED_CHARACTER_REFERENCE(1786, + /* r b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2773 _ 0) +NAMED_CHARACTER_REFERENCE(1787, + /* r b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0, + 0x007d _ 0) +NAMED_CHARACTER_REFERENCE(1788, + /* r b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0, + 0x005d _ 0) +NAMED_CHARACTER_REFERENCE(1789, + /* r b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298c _ 0) +NAMED_CHARACTER_REFERENCE(1790, + /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0, + 0x298e _ 0) +NAMED_CHARACTER_REFERENCE(1791, + /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0, + 0x2990 _ 0) +NAMED_CHARACTER_REFERENCE(1792, + /* r c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0159 _ 0) +NAMED_CHARACTER_REFERENCE(1793, + /* r c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0157 _ 0) +NAMED_CHARACTER_REFERENCE(1794, + /* r c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2309 _ 0) +NAMED_CHARACTER_REFERENCE(1795, /* r c */ 'u' _ 'b' _ ';', 3, 0, 0x007d _ 0) +NAMED_CHARACTER_REFERENCE(1796, /* r c */ 'y' _ ';', 2, 0, 0x0440 _ 0) +NAMED_CHARACTER_REFERENCE(1797, /* r d */ 'c' _ 'a' _ ';', 3, 0, 0x2937 _ 0) +NAMED_CHARACTER_REFERENCE(1798, + /* r d */ 'l' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, + 0x2969 _ 0) +NAMED_CHARACTER_REFERENCE(1799, + /* r d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(1800, + /* r d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, + 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(1801, /* r d */ 's' _ 'h' _ ';', 3, 0, 0x21b3 _ 0) +NAMED_CHARACTER_REFERENCE(1802, /* r e */ 'a' _ 'l' _ ';', 3, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(1803, + /* r e */ 'a' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0, + 0x211b _ 0) +NAMED_CHARACTER_REFERENCE(1804, + /* r e */ 'a' _ 'l' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, + 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(1805, + /* r e */ 'a' _ 'l' _ 's' _ ';', 4, 0, 0x211d _ 0) +NAMED_CHARACTER_REFERENCE(1806, /* r e */ 'c' _ 't' _ ';', 3, 0, 0x25ad _ 0) +NAMED_CHARACTER_REFERENCE(1807, /* r e */ 'g', 1, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(1808, /* r e */ 'g' _ ';', 2, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(1809, + /* r f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, + 0x297d _ 0) +NAMED_CHARACTER_REFERENCE(1810, + /* r f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0, + 0x230b _ 0) +NAMED_CHARACTER_REFERENCE(1811, /* r f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2f) +NAMED_CHARACTER_REFERENCE(1812, + /* r h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE(1813, + /* r h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE(1814, + /* r h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0, + 0x296c _ 0) +NAMED_CHARACTER_REFERENCE(1815, /* r h */ 'o' _ ';', 2, 0, 0x03c1 _ 0) +NAMED_CHARACTER_REFERENCE(1816, /* r h */ 'o' _ 'v' _ ';', 3, 0, 0x03f1 _ 0) +NAMED_CHARACTER_REFERENCE( + 1817, + /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, + 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE( + 1818, + /* r i */ + 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', + 13, 0, 0x21a3 _ 0) +NAMED_CHARACTER_REFERENCE( + 1819, + /* r i */ + 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', + 15, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE( + 1820, + /* r i */ + 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', + 13, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE( + 1821, + /* r i */ + 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', + 14, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE( + 1822, + /* r i */ + 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', + 16, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE( + 1823, + /* r i */ + 'g' _ 'h' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', + 15, 0, 0x21c9 _ 0) +NAMED_CHARACTER_REFERENCE( + 1824, + /* r i */ + 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 14, 0, 0x219d _ 0) +NAMED_CHARACTER_REFERENCE( + 1825, + /* r i */ + 'g' _ 'h' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', + 14, 0, 0x22cc _ 0) +NAMED_CHARACTER_REFERENCE(1826, /* r i */ 'n' _ 'g' _ ';', 3, 0, 0x02da _ 0) +NAMED_CHARACTER_REFERENCE( + 1827, + /* r i */ 's' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', + 11, 0, 0x2253 _ 0) +NAMED_CHARACTER_REFERENCE(1828, + /* r l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE(1829, + /* r l */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(1830, /* r l */ 'm' _ ';', 2, 0, 0x200f _ 0) +NAMED_CHARACTER_REFERENCE(1831, + /* r m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0, + 0x23b1 _ 0) +NAMED_CHARACTER_REFERENCE( + 1832, + /* r m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0, + 0x23b1 _ 0) +NAMED_CHARACTER_REFERENCE(1833, + /* r n */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2aee _ 0) +NAMED_CHARACTER_REFERENCE(1834, + /* r o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ed _ 0) +NAMED_CHARACTER_REFERENCE(1835, + /* r o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fe _ 0) +NAMED_CHARACTER_REFERENCE(1836, + /* r o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e7 _ 0) +NAMED_CHARACTER_REFERENCE(1837, + /* r o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2986 _ 0) +NAMED_CHARACTER_REFERENCE(1838, + /* r o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd63) +NAMED_CHARACTER_REFERENCE(1839, + /* r o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, + 0x2a2e _ 0) +NAMED_CHARACTER_REFERENCE(1840, + /* r o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0, + 0x2a35 _ 0) +NAMED_CHARACTER_REFERENCE(1841, /* r p */ 'a' _ 'r' _ ';', 3, 0, 0x0029 _ 0) +NAMED_CHARACTER_REFERENCE(1842, + /* r p */ 'a' _ 'r' _ 'g' _ 't' _ ';', 5, 0, + 0x2994 _ 0) +NAMED_CHARACTER_REFERENCE(1843, + /* r p */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, + 0, 0x2a12 _ 0) +NAMED_CHARACTER_REFERENCE(1844, + /* r r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c9 _ 0) +NAMED_CHARACTER_REFERENCE(1845, + /* r s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0, + 0x203a _ 0) +NAMED_CHARACTER_REFERENCE(1846, + /* r s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc7) +NAMED_CHARACTER_REFERENCE(1847, /* r s */ 'h' _ ';', 2, 0, 0x21b1 _ 0) +NAMED_CHARACTER_REFERENCE(1848, /* r s */ 'q' _ 'b' _ ';', 3, 0, 0x005d _ 0) +NAMED_CHARACTER_REFERENCE(1849, + /* r s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(1850, + /* r s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, + 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(1851, + /* r t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0, + 0x22cc _ 0) +NAMED_CHARACTER_REFERENCE(1852, + /* r t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, + 0x22ca _ 0) +NAMED_CHARACTER_REFERENCE(1853, /* r t */ 'r' _ 'i' _ ';', 3, 0, 0x25b9 _ 0) +NAMED_CHARACTER_REFERENCE(1854, + /* r t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(1855, + /* r t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b8 _ 0) +NAMED_CHARACTER_REFERENCE(1856, + /* r t */ 'r' _ 'i' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 7, + 0, 0x29ce _ 0) +NAMED_CHARACTER_REFERENCE(1857, + /* r u */ 'l' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, + 0x2968 _ 0) +NAMED_CHARACTER_REFERENCE(1858, /* r x */ ';', 1, 0, 0x211e _ 0) +NAMED_CHARACTER_REFERENCE(1859, + /* s a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x015b _ 0) +NAMED_CHARACTER_REFERENCE(1860, + /* s b */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201a _ 0) +NAMED_CHARACTER_REFERENCE(1861, /* s c */ ';', 1, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE(1862, /* s c */ 'E' _ ';', 2, 0, 0x2ab4 _ 0) +NAMED_CHARACTER_REFERENCE(1863, /* s c */ 'a' _ 'p' _ ';', 3, 0, 0x2ab8 _ 0) +NAMED_CHARACTER_REFERENCE(1864, + /* s c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0161 _ 0) +NAMED_CHARACTER_REFERENCE(1865, + /* s c */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(1866, /* s c */ 'e' _ ';', 2, 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE(1867, + /* s c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x015f _ 0) +NAMED_CHARACTER_REFERENCE(1868, + /* s c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015d _ 0) +NAMED_CHARACTER_REFERENCE(1869, /* s c */ 'n' _ 'E' _ ';', 3, 0, 0x2ab6 _ 0) +NAMED_CHARACTER_REFERENCE(1870, + /* s c */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2aba _ 0) +NAMED_CHARACTER_REFERENCE(1871, + /* s c */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0, + 0x22e9 _ 0) +NAMED_CHARACTER_REFERENCE(1872, + /* s c */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, + 0, 0x2a13 _ 0) +NAMED_CHARACTER_REFERENCE(1873, + /* s c */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(1874, /* s c */ 'y' _ ';', 2, 0, 0x0441 _ 0) +NAMED_CHARACTER_REFERENCE(1875, /* s d */ 'o' _ 't' _ ';', 3, 0, 0x22c5 _ 0) +NAMED_CHARACTER_REFERENCE(1876, + /* s d */ 'o' _ 't' _ 'b' _ ';', 4, 0, 0x22a1 _ 0) +NAMED_CHARACTER_REFERENCE(1877, + /* s d */ 'o' _ 't' _ 'e' _ ';', 4, 0, 0x2a66 _ 0) +NAMED_CHARACTER_REFERENCE(1878, + /* s e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d8 _ 0) +NAMED_CHARACTER_REFERENCE(1879, + /* s e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, + 0x2925 _ 0) +NAMED_CHARACTER_REFERENCE(1880, + /* s e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(1881, + /* s e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(1882, /* s e */ 'c' _ 't', 2, 0, 0x00a7 _ 0) +NAMED_CHARACTER_REFERENCE(1883, /* s e */ 'c' _ 't' _ ';', 3, 0, 0x00a7 _ 0) +NAMED_CHARACTER_REFERENCE(1884, /* s e */ 'm' _ 'i' _ ';', 3, 0, 0x003b _ 0) +NAMED_CHARACTER_REFERENCE(1885, + /* s e */ 's' _ 'w' _ 'a' _ 'r' _ ';', 5, 0, + 0x2929 _ 0) +NAMED_CHARACTER_REFERENCE(1886, + /* s e */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, + 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1887, + /* s e */ 't' _ 'm' _ 'n' _ ';', 4, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1888, /* s e */ 'x' _ 't' _ ';', 3, 0, 0x2736 _ 0) +NAMED_CHARACTER_REFERENCE(1889, /* s f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd30) +NAMED_CHARACTER_REFERENCE(1890, + /* s f */ 'r' _ 'o' _ 'w' _ 'n' _ ';', 5, 0, + 0x2322 _ 0) +NAMED_CHARACTER_REFERENCE(1891, + /* s h */ 'a' _ 'r' _ 'p' _ ';', 4, 0, 0x266f _ 0) +NAMED_CHARACTER_REFERENCE(1892, + /* s h */ 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0, + 0x0449 _ 0) +NAMED_CHARACTER_REFERENCE(1893, /* s h */ 'c' _ 'y' _ ';', 3, 0, 0x0448 _ 0) +NAMED_CHARACTER_REFERENCE(1894, + /* s h */ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 7, + 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE( + 1895, + /* s h */ + 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 12, + 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1896, /* s h */ 'y', 1, 0, 0x00ad _ 0) +NAMED_CHARACTER_REFERENCE(1897, /* s h */ 'y' _ ';', 2, 0, 0x00ad _ 0) +NAMED_CHARACTER_REFERENCE(1898, + /* s i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03c3 _ 0) +NAMED_CHARACTER_REFERENCE(1899, + /* s i */ 'g' _ 'm' _ 'a' _ 'f' _ ';', 5, 0, + 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(1900, + /* s i */ 'g' _ 'm' _ 'a' _ 'v' _ ';', 5, 0, + 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(1901, /* s i */ 'm' _ ';', 2, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(1902, + /* s i */ 'm' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2a6a _ 0) +NAMED_CHARACTER_REFERENCE(1903, /* s i */ 'm' _ 'e' _ ';', 3, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(1904, + /* s i */ 'm' _ 'e' _ 'q' _ ';', 4, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(1905, /* s i */ 'm' _ 'g' _ ';', 3, 0, 0x2a9e _ 0) +NAMED_CHARACTER_REFERENCE(1906, + /* s i */ 'm' _ 'g' _ 'E' _ ';', 4, 0, 0x2aa0 _ 0) +NAMED_CHARACTER_REFERENCE(1907, /* s i */ 'm' _ 'l' _ ';', 3, 0, 0x2a9d _ 0) +NAMED_CHARACTER_REFERENCE(1908, + /* s i */ 'm' _ 'l' _ 'E' _ ';', 4, 0, 0x2a9f _ 0) +NAMED_CHARACTER_REFERENCE(1909, + /* s i */ 'm' _ 'n' _ 'e' _ ';', 4, 0, 0x2246 _ 0) +NAMED_CHARACTER_REFERENCE(1910, + /* s i */ 'm' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, + 0x2a24 _ 0) +NAMED_CHARACTER_REFERENCE(1911, + /* s i */ 'm' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, + 0x2972 _ 0) +NAMED_CHARACTER_REFERENCE(1912, + /* s l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE( + 1913, + /* s m */ + 'a' _ 'l' _ 'l' _ 's' _ 'e' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 12, + 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1914, + /* s m */ 'a' _ 's' _ 'h' _ 'p' _ ';', 5, 0, + 0x2a33 _ 0) +NAMED_CHARACTER_REFERENCE(1915, + /* s m */ 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, + 0, 0x29e4 _ 0) +NAMED_CHARACTER_REFERENCE(1916, /* s m */ 'i' _ 'd' _ ';', 3, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1917, + /* s m */ 'i' _ 'l' _ 'e' _ ';', 4, 0, 0x2323 _ 0) +NAMED_CHARACTER_REFERENCE(1918, /* s m */ 't' _ ';', 2, 0, 0x2aaa _ 0) +NAMED_CHARACTER_REFERENCE(1919, /* s m */ 't' _ 'e' _ ';', 3, 0, 0x2aac _ 0) +NAMED_CHARACTER_REFERENCE(1920, + /* s m */ 't' _ 'e' _ 's' _ ';', 4, 0, + 0x2aac _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1921, + /* s o */ 'f' _ 't' _ 'c' _ 'y' _ ';', 5, 0, + 0x044c _ 0) +NAMED_CHARACTER_REFERENCE(1922, /* s o */ 'l' _ ';', 2, 0, 0x002f _ 0) +NAMED_CHARACTER_REFERENCE(1923, /* s o */ 'l' _ 'b' _ ';', 3, 0, 0x29c4 _ 0) +NAMED_CHARACTER_REFERENCE(1924, + /* s o */ 'l' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x233f _ 0) +NAMED_CHARACTER_REFERENCE(1925, + /* s o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd64) +NAMED_CHARACTER_REFERENCE(1926, + /* s p */ 'a' _ 'd' _ 'e' _ 's' _ ';', 5, 0, + 0x2660 _ 0) +NAMED_CHARACTER_REFERENCE( + 1927, + /* s p */ 'a' _ 'd' _ 'e' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2660 _ 0) +NAMED_CHARACTER_REFERENCE(1928, /* s p */ 'a' _ 'r' _ ';', 3, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1929, + /* s q */ 'c' _ 'a' _ 'p' _ ';', 4, 0, 0x2293 _ 0) +NAMED_CHARACTER_REFERENCE(1930, + /* s q */ 'c' _ 'a' _ 'p' _ 's' _ ';', 5, 0, + 0x2293 _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1931, + /* s q */ 'c' _ 'u' _ 'p' _ ';', 4, 0, 0x2294 _ 0) +NAMED_CHARACTER_REFERENCE(1932, + /* s q */ 'c' _ 'u' _ 'p' _ 's' _ ';', 5, 0, + 0x2294 _ 0xfe00) +NAMED_CHARACTER_REFERENCE(1933, + /* s q */ 's' _ 'u' _ 'b' _ ';', 4, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE(1934, + /* s q */ 's' _ 'u' _ 'b' _ 'e' _ ';', 5, 0, + 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(1935, + /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 7, + 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE( + 1936, + /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0, + 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(1937, + /* s q */ 's' _ 'u' _ 'p' _ ';', 4, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE(1938, + /* s q */ 's' _ 'u' _ 'p' _ 'e' _ ';', 5, 0, + 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(1939, + /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7, + 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE( + 1940, + /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0, + 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(1941, /* s q */ 'u' _ ';', 2, 0, 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(1942, + /* s q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, + 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(1943, + /* s q */ 'u' _ 'a' _ 'r' _ 'f' _ ';', 5, 0, + 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(1944, /* s q */ 'u' _ 'f' _ ';', 3, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(1945, + /* s r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1946, + /* s s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc8) +NAMED_CHARACTER_REFERENCE(1947, + /* s s */ 'e' _ 't' _ 'm' _ 'n' _ ';', 5, 0, + 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1948, + /* s s */ 'm' _ 'i' _ 'l' _ 'e' _ ';', 5, 0, + 0x2323 _ 0) +NAMED_CHARACTER_REFERENCE(1949, + /* s s */ 't' _ 'a' _ 'r' _ 'f' _ ';', 5, 0, + 0x22c6 _ 0) +NAMED_CHARACTER_REFERENCE(1950, /* s t */ 'a' _ 'r' _ ';', 3, 0, 0x2606 _ 0) +NAMED_CHARACTER_REFERENCE(1951, + /* s t */ 'a' _ 'r' _ 'f' _ ';', 4, 0, 0x2605 _ 0) +NAMED_CHARACTER_REFERENCE( + 1952, + /* s t */ + 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', + 14, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE( + 1953, + /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'p' _ 'h' _ 'i' _ ';', 10, 0, + 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(1954, + /* s t */ 'r' _ 'n' _ 's' _ ';', 4, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1955, /* s u */ 'b' _ ';', 2, 0, 0x2282 _ 0) +NAMED_CHARACTER_REFERENCE(1956, /* s u */ 'b' _ 'E' _ ';', 3, 0, 0x2ac5 _ 0) +NAMED_CHARACTER_REFERENCE(1957, + /* s u */ 'b' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2abd _ 0) +NAMED_CHARACTER_REFERENCE(1958, /* s u */ 'b' _ 'e' _ ';', 3, 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(1959, + /* s u */ 'b' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0, + 0x2ac3 _ 0) +NAMED_CHARACTER_REFERENCE(1960, + /* s u */ 'b' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0, + 0x2ac1 _ 0) +NAMED_CHARACTER_REFERENCE(1961, + /* s u */ 'b' _ 'n' _ 'E' _ ';', 4, 0, 0x2acb _ 0) +NAMED_CHARACTER_REFERENCE(1962, + /* s u */ 'b' _ 'n' _ 'e' _ ';', 4, 0, 0x228a _ 0) +NAMED_CHARACTER_REFERENCE(1963, + /* s u */ 'b' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, + 0x2abf _ 0) +NAMED_CHARACTER_REFERENCE(1964, + /* s u */ 'b' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, + 0x2979 _ 0) +NAMED_CHARACTER_REFERENCE(1965, + /* s u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0, + 0x2282 _ 0) +NAMED_CHARACTER_REFERENCE(1966, + /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, + 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE( + 1967, + /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac5 _ 0) +NAMED_CHARACTER_REFERENCE( + 1968, + /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228a _ 0) +NAMED_CHARACTER_REFERENCE( + 1969, + /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, + 0x2acb _ 0) +NAMED_CHARACTER_REFERENCE(1970, + /* s u */ 'b' _ 's' _ 'i' _ 'm' _ ';', 5, 0, + 0x2ac7 _ 0) +NAMED_CHARACTER_REFERENCE(1971, + /* s u */ 'b' _ 's' _ 'u' _ 'b' _ ';', 5, 0, + 0x2ad5 _ 0) +NAMED_CHARACTER_REFERENCE(1972, + /* s u */ 'b' _ 's' _ 'u' _ 'p' _ ';', 5, 0, + 0x2ad3 _ 0) +NAMED_CHARACTER_REFERENCE(1973, /* s u */ 'c' _ 'c' _ ';', 3, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE( + 1974, + /* s u */ 'c' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, + 0x2ab8 _ 0) +NAMED_CHARACTER_REFERENCE( + 1975, + /* s u */ 'c' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0, + 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(1976, + /* s u */ 'c' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, + 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE( + 1977, + /* s u */ 'c' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, + 0x2aba _ 0) +NAMED_CHARACTER_REFERENCE(1978, + /* s u */ 'c' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, + 0, 0x2ab6 _ 0) +NAMED_CHARACTER_REFERENCE(1979, + /* s u */ 'c' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, + 0, 0x22e9 _ 0) +NAMED_CHARACTER_REFERENCE(1980, + /* s u */ 'c' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0, + 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(1981, /* s u */ 'm' _ ';', 2, 0, 0x2211 _ 0) +NAMED_CHARACTER_REFERENCE(1982, /* s u */ 'n' _ 'g' _ ';', 3, 0, 0x266a _ 0) +NAMED_CHARACTER_REFERENCE(1983, /* s u */ 'p' _ '1', 2, 0, 0x00b9 _ 0) +NAMED_CHARACTER_REFERENCE(1984, /* s u */ 'p' _ '1' _ ';', 3, 0, 0x00b9 _ 0) +NAMED_CHARACTER_REFERENCE(1985, /* s u */ 'p' _ '2', 2, 0, 0x00b2 _ 0) +NAMED_CHARACTER_REFERENCE(1986, /* s u */ 'p' _ '2' _ ';', 3, 0, 0x00b2 _ 0) +NAMED_CHARACTER_REFERENCE(1987, /* s u */ 'p' _ '3', 2, 0, 0x00b3 _ 0) +NAMED_CHARACTER_REFERENCE(1988, /* s u */ 'p' _ '3' _ ';', 3, 0, 0x00b3 _ 0) +NAMED_CHARACTER_REFERENCE(1989, /* s u */ 'p' _ ';', 2, 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(1990, /* s u */ 'p' _ 'E' _ ';', 3, 0, 0x2ac6 _ 0) +NAMED_CHARACTER_REFERENCE(1991, + /* s u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x2abe _ 0) +NAMED_CHARACTER_REFERENCE(1992, + /* s u */ 'p' _ 'd' _ 's' _ 'u' _ 'b' _ ';', 6, 0, + 0x2ad8 _ 0) +NAMED_CHARACTER_REFERENCE(1993, /* s u */ 'p' _ 'e' _ ';', 3, 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(1994, + /* s u */ 'p' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0, + 0x2ac4 _ 0) +NAMED_CHARACTER_REFERENCE(1995, + /* s u */ 'p' _ 'h' _ 's' _ 'o' _ 'l' _ ';', 6, 0, + 0x27c9 _ 0) +NAMED_CHARACTER_REFERENCE(1996, + /* s u */ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 6, 0, + 0x2ad7 _ 0) +NAMED_CHARACTER_REFERENCE(1997, + /* s u */ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, + 0x297b _ 0) +NAMED_CHARACTER_REFERENCE(1998, + /* s u */ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0, + 0x2ac2 _ 0) +NAMED_CHARACTER_REFERENCE(1999, + /* s u */ 'p' _ 'n' _ 'E' _ ';', 4, 0, 0x2acc _ 0) +NAMED_CHARACTER_REFERENCE(2000, + /* s u */ 'p' _ 'n' _ 'e' _ ';', 4, 0, 0x228b _ 0) +NAMED_CHARACTER_REFERENCE(2001, + /* s u */ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, + 0x2ac0 _ 0) +NAMED_CHARACTER_REFERENCE(2002, + /* s u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0, + 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(2003, + /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, + 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE( + 2004, + /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac6 _ 0) +NAMED_CHARACTER_REFERENCE( + 2005, + /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228b _ 0) +NAMED_CHARACTER_REFERENCE( + 2006, + /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, + 0x2acc _ 0) +NAMED_CHARACTER_REFERENCE(2007, + /* s u */ 'p' _ 's' _ 'i' _ 'm' _ ';', 5, 0, + 0x2ac8 _ 0) +NAMED_CHARACTER_REFERENCE(2008, + /* s u */ 'p' _ 's' _ 'u' _ 'b' _ ';', 5, 0, + 0x2ad4 _ 0) +NAMED_CHARACTER_REFERENCE(2009, + /* s u */ 'p' _ 's' _ 'u' _ 'p' _ ';', 5, 0, + 0x2ad6 _ 0) +NAMED_CHARACTER_REFERENCE(2010, + /* s w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d9 _ 0) +NAMED_CHARACTER_REFERENCE(2011, + /* s w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, + 0x2926 _ 0) +NAMED_CHARACTER_REFERENCE(2012, + /* s w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(2013, + /* s w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(2014, + /* s w */ 'n' _ 'w' _ 'a' _ 'r' _ ';', 5, 0, + 0x292a _ 0) +NAMED_CHARACTER_REFERENCE(2015, /* s z */ 'l' _ 'i' _ 'g', 3, 0, 0x00df _ 0) +NAMED_CHARACTER_REFERENCE(2016, + /* s z */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00df _ 0) +NAMED_CHARACTER_REFERENCE(2017, + /* t a */ 'r' _ 'g' _ 'e' _ 't' _ ';', 5, 0, + 0x2316 _ 0) +NAMED_CHARACTER_REFERENCE(2018, /* t a */ 'u' _ ';', 2, 0, 0x03c4 _ 0) +NAMED_CHARACTER_REFERENCE(2019, /* t b */ 'r' _ 'k' _ ';', 3, 0, 0x23b4 _ 0) +NAMED_CHARACTER_REFERENCE(2020, + /* t c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x0165 _ 0) +NAMED_CHARACTER_REFERENCE(2021, + /* t c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, + 0x0163 _ 0) +NAMED_CHARACTER_REFERENCE(2022, /* t c */ 'y' _ ';', 2, 0, 0x0442 _ 0) +NAMED_CHARACTER_REFERENCE(2023, /* t d */ 'o' _ 't' _ ';', 3, 0, 0x20db _ 0) +NAMED_CHARACTER_REFERENCE(2024, + /* t e */ 'l' _ 'r' _ 'e' _ 'c' _ ';', 5, 0, + 0x2315 _ 0) +NAMED_CHARACTER_REFERENCE(2025, /* t f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd31) +NAMED_CHARACTER_REFERENCE(2026, + /* t h */ 'e' _ 'r' _ 'e' _ '4' _ ';', 5, 0, + 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE( + 2027, + /* t h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(2028, + /* t h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x03b8 _ 0) +NAMED_CHARACTER_REFERENCE(2029, + /* t h */ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 7, + 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE(2030, + /* t h */ 'e' _ 't' _ 'a' _ 'v' _ ';', 5, 0, + 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE( + 2031, + /* t h */ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, + 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(2032, + /* t h */ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7, + 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(2033, + /* t h */ 'i' _ 'n' _ 's' _ 'p' _ ';', 5, 0, + 0x2009 _ 0) +NAMED_CHARACTER_REFERENCE(2034, + /* t h */ 'k' _ 'a' _ 'p' _ ';', 4, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(2035, + /* t h */ 'k' _ 's' _ 'i' _ 'm' _ ';', 5, 0, + 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(2036, /* t h */ 'o' _ 'r' _ 'n', 3, 0, 0x00fe _ 0) +NAMED_CHARACTER_REFERENCE(2037, + /* t h */ 'o' _ 'r' _ 'n' _ ';', 4, 0, 0x00fe _ 0) +NAMED_CHARACTER_REFERENCE(2038, + /* t i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x02dc _ 0) +NAMED_CHARACTER_REFERENCE(2039, /* t i */ 'm' _ 'e' _ 's', 3, 0, 0x00d7 _ 0) +NAMED_CHARACTER_REFERENCE(2040, + /* t i */ 'm' _ 'e' _ 's' _ ';', 4, 0, 0x00d7 _ 0) +NAMED_CHARACTER_REFERENCE(2041, + /* t i */ 'm' _ 'e' _ 's' _ 'b' _ ';', 5, 0, + 0x22a0 _ 0) +NAMED_CHARACTER_REFERENCE(2042, + /* t i */ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 7, + 0, 0x2a31 _ 0) +NAMED_CHARACTER_REFERENCE(2043, + /* t i */ 'm' _ 'e' _ 's' _ 'd' _ ';', 5, 0, + 0x2a30 _ 0) +NAMED_CHARACTER_REFERENCE(2044, /* t i */ 'n' _ 't' _ ';', 3, 0, 0x222d _ 0) +NAMED_CHARACTER_REFERENCE(2045, /* t o */ 'e' _ 'a' _ ';', 3, 0, 0x2928 _ 0) +NAMED_CHARACTER_REFERENCE(2046, /* t o */ 'p' _ ';', 2, 0, 0x22a4 _ 0) +NAMED_CHARACTER_REFERENCE(2047, + /* t o */ 'p' _ 'b' _ 'o' _ 't' _ ';', 5, 0, + 0x2336 _ 0) +NAMED_CHARACTER_REFERENCE(2048, + /* t o */ 'p' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, + 0x2af1 _ 0) +NAMED_CHARACTER_REFERENCE(2049, + /* t o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd65) +NAMED_CHARACTER_REFERENCE(2050, + /* t o */ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 6, 0, + 0x2ada _ 0) +NAMED_CHARACTER_REFERENCE(2051, /* t o */ 's' _ 'a' _ ';', 3, 0, 0x2929 _ 0) +NAMED_CHARACTER_REFERENCE(2052, + /* t p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, + 0x2034 _ 0) +NAMED_CHARACTER_REFERENCE(2053, + /* t r */ 'a' _ 'd' _ 'e' _ ';', 4, 0, 0x2122 _ 0) +NAMED_CHARACTER_REFERENCE(2054, + /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7, + 0, 0x25b5 _ 0) +NAMED_CHARACTER_REFERENCE( + 2055, + /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', + 11, 0, 0x25bf _ 0) +NAMED_CHARACTER_REFERENCE( + 2056, + /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', + 11, 0, 0x25c3 _ 0) +NAMED_CHARACTER_REFERENCE( + 2057, + /* t r */ + 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', + 13, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE( + 2058, + /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 8, 0, 0x225c _ 0) +NAMED_CHARACTER_REFERENCE( + 2059, + /* t r */ + 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 12, + 0, 0x25b9 _ 0) +NAMED_CHARACTER_REFERENCE( + 2060, + /* t r */ + 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', + 14, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(2061, + /* t r */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, + 0x25ec _ 0) +NAMED_CHARACTER_REFERENCE(2062, /* t r */ 'i' _ 'e' _ ';', 3, 0, 0x225c _ 0) +NAMED_CHARACTER_REFERENCE(2063, + /* t r */ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, + 0, 0x2a3a _ 0) +NAMED_CHARACTER_REFERENCE(2064, + /* t r */ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, + 0x2a39 _ 0) +NAMED_CHARACTER_REFERENCE(2065, + /* t r */ 'i' _ 's' _ 'b' _ ';', 4, 0, 0x29cd _ 0) +NAMED_CHARACTER_REFERENCE(2066, + /* t r */ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 6, 0, + 0x2a3b _ 0) +NAMED_CHARACTER_REFERENCE(2067, + /* t r */ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 7, + 0, 0x23e2 _ 0) +NAMED_CHARACTER_REFERENCE(2068, + /* t s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc9) +NAMED_CHARACTER_REFERENCE(2069, /* t s */ 'c' _ 'y' _ ';', 3, 0, 0x0446 _ 0) +NAMED_CHARACTER_REFERENCE(2070, + /* t s */ 'h' _ 'c' _ 'y' _ ';', 4, 0, 0x045b _ 0) +NAMED_CHARACTER_REFERENCE(2071, + /* t s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, + 0x0167 _ 0) +NAMED_CHARACTER_REFERENCE(2072, + /* t w */ 'i' _ 'x' _ 't' _ ';', 4, 0, 0x226c _ 0) +NAMED_CHARACTER_REFERENCE( + 2073, + /* t w */ + 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 15, 0, 0x219e _ 0) +NAMED_CHARACTER_REFERENCE( + 2074, + /* t w */ + 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', + 16, 0, 0x21a0 _ 0) +NAMED_CHARACTER_REFERENCE(2075, /* u A */ 'r' _ 'r' _ ';', 3, 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE(2076, /* u H */ 'a' _ 'r' _ ';', 3, 0, 0x2963 _ 0) +NAMED_CHARACTER_REFERENCE(2077, + /* u a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fa _ 0) +NAMED_CHARACTER_REFERENCE(2078, + /* u a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00fa _ 0) +NAMED_CHARACTER_REFERENCE(2079, /* u a */ 'r' _ 'r' _ ';', 3, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(2080, + /* u b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x045e _ 0) +NAMED_CHARACTER_REFERENCE(2081, + /* u b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, + 0x016d _ 0) +NAMED_CHARACTER_REFERENCE(2082, /* u c */ 'i' _ 'r' _ 'c', 3, 0, 0x00fb _ 0) +NAMED_CHARACTER_REFERENCE(2083, + /* u c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00fb _ 0) +NAMED_CHARACTER_REFERENCE(2084, /* u c */ 'y' _ ';', 2, 0, 0x0443 _ 0) +NAMED_CHARACTER_REFERENCE(2085, + /* u d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c5 _ 0) +NAMED_CHARACTER_REFERENCE(2086, + /* u d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, + 0x0171 _ 0) +NAMED_CHARACTER_REFERENCE(2087, + /* u d */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296e _ 0) +NAMED_CHARACTER_REFERENCE(2088, + /* u f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, + 0x297e _ 0) +NAMED_CHARACTER_REFERENCE(2089, /* u f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd32) +NAMED_CHARACTER_REFERENCE(2090, + /* u g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f9 _ 0) +NAMED_CHARACTER_REFERENCE(2091, + /* u g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, + 0x00f9 _ 0) +NAMED_CHARACTER_REFERENCE(2092, + /* u h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE(2093, + /* u h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(2094, + /* u h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2580 _ 0) +NAMED_CHARACTER_REFERENCE(2095, + /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, + 0x231c _ 0) +NAMED_CHARACTER_REFERENCE(2096, + /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, + 0, 0x231c _ 0) +NAMED_CHARACTER_REFERENCE(2097, + /* u l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, + 0x230f _ 0) +NAMED_CHARACTER_REFERENCE(2098, + /* u l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f8 _ 0) +NAMED_CHARACTER_REFERENCE(2099, + /* u m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016b _ 0) +NAMED_CHARACTER_REFERENCE(2100, /* u m */ 'l', 1, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(2101, /* u m */ 'l' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(2102, + /* u o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0173 _ 0) +NAMED_CHARACTER_REFERENCE(2103, + /* u o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd66) +NAMED_CHARACTER_REFERENCE(2104, + /* u p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, + 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE( + 2105, + /* u p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, + 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE( + 2106, + /* u p */ + 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, + 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE( + 2107, + /* u p */ + 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 13, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(2108, + /* u p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x228e _ 0) +NAMED_CHARACTER_REFERENCE(2109, /* u p */ 's' _ 'i' _ ';', 3, 0, 0x03c5 _ 0) +NAMED_CHARACTER_REFERENCE(2110, + /* u p */ 's' _ 'i' _ 'h' _ ';', 4, 0, 0x03d2 _ 0) +NAMED_CHARACTER_REFERENCE(2111, + /* u p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, + 0x03c5 _ 0) +NAMED_CHARACTER_REFERENCE( + 2112, + /* u p */ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 9, 0, + 0x21c8 _ 0) +NAMED_CHARACTER_REFERENCE(2113, + /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, + 0x231d _ 0) +NAMED_CHARACTER_REFERENCE(2114, + /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, + 0, 0x231d _ 0) +NAMED_CHARACTER_REFERENCE(2115, + /* u r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, + 0x230e _ 0) +NAMED_CHARACTER_REFERENCE(2116, + /* u r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016f _ 0) +NAMED_CHARACTER_REFERENCE(2117, + /* u r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f9 _ 0) +NAMED_CHARACTER_REFERENCE(2118, + /* u s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcca) +NAMED_CHARACTER_REFERENCE(2119, + /* u t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f0 _ 0) +NAMED_CHARACTER_REFERENCE(2120, + /* u t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, + 0x0169 _ 0) +NAMED_CHARACTER_REFERENCE(2121, /* u t */ 'r' _ 'i' _ ';', 3, 0, 0x25b5 _ 0) +NAMED_CHARACTER_REFERENCE(2122, + /* u t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b4 _ 0) +NAMED_CHARACTER_REFERENCE(2123, + /* u u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c8 _ 0) +NAMED_CHARACTER_REFERENCE(2124, /* u u */ 'm' _ 'l', 2, 0, 0x00fc _ 0) +NAMED_CHARACTER_REFERENCE(2125, /* u u */ 'm' _ 'l' _ ';', 3, 0, 0x00fc _ 0) +NAMED_CHARACTER_REFERENCE(2126, + /* u w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0, + 0x29a7 _ 0) +NAMED_CHARACTER_REFERENCE(2127, /* v A */ 'r' _ 'r' _ ';', 3, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE(2128, /* v B */ 'a' _ 'r' _ ';', 3, 0, 0x2ae8 _ 0) +NAMED_CHARACTER_REFERENCE(2129, + /* v B */ 'a' _ 'r' _ 'v' _ ';', 4, 0, 0x2ae9 _ 0) +NAMED_CHARACTER_REFERENCE(2130, + /* v D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a8 _ 0) +NAMED_CHARACTER_REFERENCE(2131, + /* v a */ 'n' _ 'g' _ 'r' _ 't' _ ';', 5, 0, + 0x299c _ 0) +NAMED_CHARACTER_REFERENCE( + 2132, + /* v a */ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 9, 0, + 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(2133, + /* v a */ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 7, + 0, 0x03f0 _ 0) +NAMED_CHARACTER_REFERENCE( + 2134, + /* v a */ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 9, 0, + 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(2135, + /* v a */ 'r' _ 'p' _ 'h' _ 'i' _ ';', 5, 0, + 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(2136, + /* v a */ 'r' _ 'p' _ 'i' _ ';', 4, 0, 0x03d6 _ 0) +NAMED_CHARACTER_REFERENCE( + 2137, + /* v a */ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 8, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(2138, /* v a */ 'r' _ 'r' _ ';', 3, 0, 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE(2139, + /* v a */ 'r' _ 'r' _ 'h' _ 'o' _ ';', 5, 0, + 0x03f1 _ 0) +NAMED_CHARACTER_REFERENCE(2140, + /* v a */ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 7, + 0, 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE( + 2141, + /* v a */ 'r' _ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', + 11, 0, 0x228a _ 0xfe00) +NAMED_CHARACTER_REFERENCE( + 2142, + /* v a */ + 'r' _ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 12, + 0, 0x2acb _ 0xfe00) +NAMED_CHARACTER_REFERENCE( + 2143, + /* v a */ 'r' _ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', + 11, 0, 0x228b _ 0xfe00) +NAMED_CHARACTER_REFERENCE( + 2144, + /* v a */ + 'r' _ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 12, + 0, 0x2acc _ 0xfe00) +NAMED_CHARACTER_REFERENCE(2145, + /* v a */ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 7, + 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE( + 2146, + /* v a */ + 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', + 14, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE( + 2147, + /* v a */ + 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', + 15, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(2148, /* v c */ 'y' _ ';', 2, 0, 0x0432 _ 0) +NAMED_CHARACTER_REFERENCE(2149, + /* v d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a2 _ 0) +NAMED_CHARACTER_REFERENCE(2150, /* v e */ 'e' _ ';', 2, 0, 0x2228 _ 0) +NAMED_CHARACTER_REFERENCE(2151, + /* v e */ 'e' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x22bb _ 0) +NAMED_CHARACTER_REFERENCE(2152, + /* v e */ 'e' _ 'e' _ 'q' _ ';', 4, 0, 0x225a _ 0) +NAMED_CHARACTER_REFERENCE(2153, + /* v e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0, + 0x22ee _ 0) +NAMED_CHARACTER_REFERENCE(2154, + /* v e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(2155, /* v e */ 'r' _ 't' _ ';', 3, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(2156, /* v f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd33) +NAMED_CHARACTER_REFERENCE(2157, + /* v l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE(2158, + /* v n */ 's' _ 'u' _ 'b' _ ';', 4, 0, + 0x2282 _ 0x20d2) +NAMED_CHARACTER_REFERENCE(2159, + /* v n */ 's' _ 'u' _ 'p' _ ';', 4, 0, + 0x2283 _ 0x20d2) +NAMED_CHARACTER_REFERENCE(2160, + /* v o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd67) +NAMED_CHARACTER_REFERENCE(2161, + /* v p */ 'r' _ 'o' _ 'p' _ ';', 4, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(2162, + /* v r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(2163, + /* v s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccb) +NAMED_CHARACTER_REFERENCE(2164, + /* v s */ 'u' _ 'b' _ 'n' _ 'E' _ ';', 5, 0, + 0x2acb _ 0xfe00) +NAMED_CHARACTER_REFERENCE(2165, + /* v s */ 'u' _ 'b' _ 'n' _ 'e' _ ';', 5, 0, + 0x228a _ 0xfe00) +NAMED_CHARACTER_REFERENCE(2166, + /* v s */ 'u' _ 'p' _ 'n' _ 'E' _ ';', 5, 0, + 0x2acc _ 0xfe00) +NAMED_CHARACTER_REFERENCE(2167, + /* v s */ 'u' _ 'p' _ 'n' _ 'e' _ ';', 5, 0, + 0x228b _ 0xfe00) +NAMED_CHARACTER_REFERENCE(2168, + /* v z */ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 6, 0, + 0x299a _ 0) +NAMED_CHARACTER_REFERENCE(2169, + /* w c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0175 _ 0) +NAMED_CHARACTER_REFERENCE(2170, + /* w e */ 'd' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, + 0x2a5f _ 0) +NAMED_CHARACTER_REFERENCE(2171, + /* w e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x2227 _ 0) +NAMED_CHARACTER_REFERENCE(2172, + /* w e */ 'd' _ 'g' _ 'e' _ 'q' _ ';', 5, 0, + 0x2259 _ 0) +NAMED_CHARACTER_REFERENCE(2173, + /* w e */ 'i' _ 'e' _ 'r' _ 'p' _ ';', 5, 0, + 0x2118 _ 0) +NAMED_CHARACTER_REFERENCE(2174, /* w f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd34) +NAMED_CHARACTER_REFERENCE(2175, + /* w o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd68) +NAMED_CHARACTER_REFERENCE(2176, /* w p */ ';', 1, 0, 0x2118 _ 0) +NAMED_CHARACTER_REFERENCE(2177, /* w r */ ';', 1, 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(2178, + /* w r */ 'e' _ 'a' _ 't' _ 'h' _ ';', 5, 0, + 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(2179, + /* w s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccc) +NAMED_CHARACTER_REFERENCE(2180, /* x c */ 'a' _ 'p' _ ';', 3, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(2181, + /* x c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x25ef _ 0) +NAMED_CHARACTER_REFERENCE(2182, /* x c */ 'u' _ 'p' _ ';', 3, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(2183, + /* x d */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25bd _ 0) +NAMED_CHARACTER_REFERENCE(2184, /* x f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd35) +NAMED_CHARACTER_REFERENCE(2185, + /* x h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE(2186, + /* x h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE(2187, /* x i */ ';', 1, 0, 0x03be _ 0) +NAMED_CHARACTER_REFERENCE(2188, + /* x l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE(2189, + /* x l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE(2190, /* x m */ 'a' _ 'p' _ ';', 3, 0, 0x27fc _ 0) +NAMED_CHARACTER_REFERENCE(2191, /* x n */ 'i' _ 's' _ ';', 3, 0, 0x22fb _ 0) +NAMED_CHARACTER_REFERENCE(2192, + /* x o */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2a00 _ 0) +NAMED_CHARACTER_REFERENCE(2193, + /* x o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd69) +NAMED_CHARACTER_REFERENCE(2194, + /* x o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, + 0x2a01 _ 0) +NAMED_CHARACTER_REFERENCE(2195, + /* x o */ 't' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, + 0x2a02 _ 0) +NAMED_CHARACTER_REFERENCE(2196, + /* x r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(2197, + /* x r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE(2198, + /* x s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccd) +NAMED_CHARACTER_REFERENCE(2199, + /* x s */ 'q' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, + 0x2a06 _ 0) +NAMED_CHARACTER_REFERENCE(2200, + /* x u */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, + 0x2a04 _ 0) +NAMED_CHARACTER_REFERENCE(2201, + /* x u */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25b3 _ 0) +NAMED_CHARACTER_REFERENCE(2202, /* x v */ 'e' _ 'e' _ ';', 3, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(2203, + /* x w */ 'e' _ 'd' _ 'g' _ 'e' _ ';', 5, 0, + 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(2204, + /* y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fd _ 0) +NAMED_CHARACTER_REFERENCE(2205, + /* y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x00fd _ 0) +NAMED_CHARACTER_REFERENCE(2206, /* y a */ 'c' _ 'y' _ ';', 3, 0, 0x044f _ 0) +NAMED_CHARACTER_REFERENCE(2207, + /* y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0177 _ 0) +NAMED_CHARACTER_REFERENCE(2208, /* y c */ 'y' _ ';', 2, 0, 0x044b _ 0) +NAMED_CHARACTER_REFERENCE(2209, /* y e */ 'n', 1, 0, 0x00a5 _ 0) +NAMED_CHARACTER_REFERENCE(2210, /* y e */ 'n' _ ';', 2, 0, 0x00a5 _ 0) +NAMED_CHARACTER_REFERENCE(2211, /* y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd36) +NAMED_CHARACTER_REFERENCE(2212, /* y i */ 'c' _ 'y' _ ';', 3, 0, 0x0457 _ 0) +NAMED_CHARACTER_REFERENCE(2213, + /* y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6a) +NAMED_CHARACTER_REFERENCE(2214, + /* y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcce) +NAMED_CHARACTER_REFERENCE(2215, /* y u */ 'c' _ 'y' _ ';', 3, 0, 0x044e _ 0) +NAMED_CHARACTER_REFERENCE(2216, /* y u */ 'm' _ 'l', 2, 0, 0x00ff _ 0) +NAMED_CHARACTER_REFERENCE(2217, /* y u */ 'm' _ 'l' _ ';', 3, 0, 0x00ff _ 0) +NAMED_CHARACTER_REFERENCE(2218, + /* z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, + 0x017a _ 0) +NAMED_CHARACTER_REFERENCE(2219, + /* z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, + 0x017e _ 0) +NAMED_CHARACTER_REFERENCE(2220, /* z c */ 'y' _ ';', 2, 0, 0x0437 _ 0) +NAMED_CHARACTER_REFERENCE(2221, /* z d */ 'o' _ 't' _ ';', 3, 0, 0x017c _ 0) +NAMED_CHARACTER_REFERENCE(2222, + /* z e */ 'e' _ 't' _ 'r' _ 'f' _ ';', 5, 0, + 0x2128 _ 0) +NAMED_CHARACTER_REFERENCE(2223, /* z e */ 't' _ 'a' _ ';', 3, 0, 0x03b6 _ 0) +NAMED_CHARACTER_REFERENCE(2224, /* z f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd37) +NAMED_CHARACTER_REFERENCE(2225, /* z h */ 'c' _ 'y' _ ';', 3, 0, 0x0436 _ 0) +NAMED_CHARACTER_REFERENCE(2226, + /* z i */ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, + 0x21dd _ 0) +NAMED_CHARACTER_REFERENCE(2227, + /* z o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6b) +NAMED_CHARACTER_REFERENCE(2228, + /* z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccf) +NAMED_CHARACTER_REFERENCE(2229, /* z w */ 'j' _ ';', 2, 0, 0x200d _ 0) +NAMED_CHARACTER_REFERENCE(2230, /* z w */ 'n' _ 'j' _ ';', 3, 0, 0x200c _ 0) + +#undef _ diff --git a/parser/html/nsHtml5OplessBuilder.cpp b/parser/html/nsHtml5OplessBuilder.cpp new file mode 100644 index 0000000000..60bbe72928 --- /dev/null +++ b/parser/html/nsHtml5OplessBuilder.cpp @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#include "nsHtml5OplessBuilder.h" + +#include "mozilla/css/Loader.h" +#include "mozilla/dom/ScriptLoader.h" +#include "nsIDocShell.h" + +nsHtml5OplessBuilder::nsHtml5OplessBuilder() : nsHtml5DocumentBuilder(true) {} + +nsHtml5OplessBuilder::~nsHtml5OplessBuilder() {} + +void nsHtml5OplessBuilder::Start() { + BeginFlush(); + BeginDocUpdate(); +} + +void nsHtml5OplessBuilder::Finish() { + EndDocUpdate(); + EndFlush(); + DropParserAndPerfHint(); + mScriptLoader = nullptr; + mDocument = nullptr; + mNodeInfoManager = nullptr; + mCSSLoader = nullptr; + mDocumentURI = nullptr; + mDocShell = nullptr; + mOwnedElements.Clear(); +} + +void nsHtml5OplessBuilder::SetParser(nsParserBase* aParser) { + mParser = aParser; +} diff --git a/parser/html/nsHtml5OplessBuilder.h b/parser/html/nsHtml5OplessBuilder.h new file mode 100644 index 0000000000..4fa4f4e735 --- /dev/null +++ b/parser/html/nsHtml5OplessBuilder.h @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#ifndef nsHtml5OplessBuilder_h +#define nsHtml5OplessBuilder_h + +#include "nsHtml5DocumentBuilder.h" + +class nsParserBase; + +/** + * This class implements a minimal subclass of nsHtml5DocumentBuilder that + * works when tree operation queues that are part of the off-the-main-thread + * parsing machinery are not used and, therefore, nsHtml5TreeOpExecutor is + * not used. + * + * This class is mostly responsible for wrapping tree building in an update + * batch and resetting various fields in nsContentSink upon finishing. + */ +class nsHtml5OplessBuilder : public nsHtml5DocumentBuilder { + public: + nsHtml5OplessBuilder(); + ~nsHtml5OplessBuilder(); + void Start(); + void Finish(); + void SetParser(nsParserBase* aParser); +}; + +#endif // nsHtml5OplessBuilder_h diff --git a/parser/html/nsHtml5OwningUTF16Buffer.cpp b/parser/html/nsHtml5OwningUTF16Buffer.cpp new file mode 100644 index 0000000000..eec07a29ac --- /dev/null +++ b/parser/html/nsHtml5OwningUTF16Buffer.cpp @@ -0,0 +1,57 @@ +/* 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/. */ + +#include "nsHtml5OwningUTF16Buffer.h" + +#include "mozilla/Span.h" + +using namespace mozilla; + +nsHtml5OwningUTF16Buffer::nsHtml5OwningUTF16Buffer(char16_t* aBuffer) + : nsHtml5UTF16Buffer(aBuffer, 0), next(nullptr), key(nullptr) {} + +nsHtml5OwningUTF16Buffer::nsHtml5OwningUTF16Buffer(void* aKey) + : nsHtml5UTF16Buffer(nullptr, 0), next(nullptr), key(aKey) {} + +nsHtml5OwningUTF16Buffer::~nsHtml5OwningUTF16Buffer() { + DeleteBuffer(); + + // This is to avoid dtor recursion on 'next', bug 706932. + RefPtr<nsHtml5OwningUTF16Buffer> tail; + tail.swap(next); + while (tail && tail->mRefCnt == 1) { + RefPtr<nsHtml5OwningUTF16Buffer> tmp; + tmp.swap(tail->next); + tail.swap(tmp); + } +} + +// static +already_AddRefed<nsHtml5OwningUTF16Buffer> +nsHtml5OwningUTF16Buffer::FalliblyCreate(int32_t aLength) { + char16_t* newBuf = new (mozilla::fallible) char16_t[aLength]; + if (!newBuf) { + return nullptr; + } + RefPtr<nsHtml5OwningUTF16Buffer> newObj = + new (mozilla::fallible) nsHtml5OwningUTF16Buffer(newBuf); + if (!newObj) { + delete[] newBuf; + return nullptr; + } + return newObj.forget(); +} + +void nsHtml5OwningUTF16Buffer::Swap(nsHtml5OwningUTF16Buffer* aOther) { + nsHtml5UTF16Buffer::Swap(aOther); +} + +Span<char16_t> nsHtml5OwningUTF16Buffer::TailAsSpan(int32_t aBufferSize) { + MOZ_ASSERT(aBufferSize >= getEnd()); + return {getBuffer() + getEnd(), static_cast<size_t>(aBufferSize - getEnd())}; +} + +void nsHtml5OwningUTF16Buffer::AdvanceEnd(int32_t aNumberOfCodeUnits) { + setEnd(getEnd() + aNumberOfCodeUnits); +} diff --git a/parser/html/nsHtml5OwningUTF16Buffer.h b/parser/html/nsHtml5OwningUTF16Buffer.h new file mode 100644 index 0000000000..2cc94583e7 --- /dev/null +++ b/parser/html/nsHtml5OwningUTF16Buffer.h @@ -0,0 +1,64 @@ +/* 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/. */ + +#ifndef nsHtml5OwningUTF16Buffer_h +#define nsHtml5OwningUTF16Buffer_h + +#include "nsHtml5UTF16Buffer.h" +#include "mozilla/Span.h" + +class nsHtml5OwningUTF16Buffer : public nsHtml5UTF16Buffer { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHtml5OwningUTF16Buffer) + + private: + /** + * Passes a buffer and its length to the superclass constructor. + */ + explicit nsHtml5OwningUTF16Buffer(char16_t* aBuffer); + + public: + /** + * Constructor for a parser key placeholder. (No actual buffer.) + * @param aKey a parser key + */ + explicit nsHtml5OwningUTF16Buffer(void* aKey); + + protected: + /** + * Takes care of releasing the owned buffer. + */ + ~nsHtml5OwningUTF16Buffer(); + + public: + /** + * The next buffer in a queue. + */ + RefPtr<nsHtml5OwningUTF16Buffer> next; + + /** + * A parser key. + */ + void* key; + + static already_AddRefed<nsHtml5OwningUTF16Buffer> FalliblyCreate( + int32_t aLength); + + /** + * Swap start, end and buffer fields with another object. + */ + void Swap(nsHtml5OwningUTF16Buffer* aOther); + + /** + * Return a span from `end` to `aBufferSize`. + */ + mozilla::Span<char16_t> TailAsSpan(int32_t aBufferSize); + + /** + * Add the argument to `end`. + */ + void AdvanceEnd(int32_t aNumberOfCodeUnits); +}; + +#endif // nsHtml5OwningUTF16Buffer_h diff --git a/parser/html/nsHtml5Parser.cpp b/parser/html/nsHtml5Parser.cpp new file mode 100644 index 0000000000..f1916ca2d4 --- /dev/null +++ b/parser/html/nsHtml5Parser.cpp @@ -0,0 +1,695 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=2 et tw=80: */ +/* 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/. */ + +#include "nsHtml5Parser.h" + +#include "mozilla/AutoRestore.h" +#include "mozilla/UniquePtr.h" +#include "nsCRT.h" +#include "nsContentUtils.h" // for kLoadAsData +#include "nsHtml5AtomTable.h" +#include "nsHtml5DependentUTF16Buffer.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsNetUtil.h" + +NS_INTERFACE_TABLE_HEAD(nsHtml5Parser) + NS_INTERFACE_TABLE(nsHtml5Parser, nsIParser, nsISupportsWeakReference) + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHtml5Parser) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5Parser) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5Parser) + +NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5Parser) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5Parser) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExecutor) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetStreamParser()) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5Parser) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mExecutor) + NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE + tmp->DropStreamParser(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +nsHtml5Parser::nsHtml5Parser() + : mLastWasCR(false), + mDocWriteSpeculativeLastWasCR(false), + mBlocked(0), + mDocWriteSpeculatorActive(false), + mScriptNestingLevel(0), + mDocumentClosed(false), + mInDocumentWrite(false), + mInsertionPointPermanentlyUndefined(false), + mFirstBuffer(new nsHtml5OwningUTF16Buffer((void*)nullptr)), + mLastBuffer(mFirstBuffer), + mExecutor(new nsHtml5TreeOpExecutor()), + mTreeBuilder(new nsHtml5TreeBuilder(mExecutor, nullptr, false)), + mTokenizer(new nsHtml5Tokenizer(mTreeBuilder.get(), false)), + mRootContextLineNumber(1), + mReturnToStreamParserPermitted(false) { + mTokenizer->setInterner(&mAtomTable); +} + +nsHtml5Parser::~nsHtml5Parser() { + mTokenizer->end(); + if (mDocWriteSpeculativeTokenizer) { + mDocWriteSpeculativeTokenizer->end(); + } +} + +NS_IMETHODIMP_(void) +nsHtml5Parser::SetContentSink(nsIContentSink* aSink) { + NS_ASSERTION(aSink == static_cast<nsIContentSink*>(mExecutor), + "Attempt to set a foreign sink."); +} + +NS_IMETHODIMP_(nsIContentSink*) +nsHtml5Parser::GetContentSink() { + return static_cast<nsIContentSink*>(mExecutor); +} + +NS_IMETHODIMP_(void) +nsHtml5Parser::GetCommand(nsCString& aCommand) { + aCommand.AssignLiteral("view"); +} + +NS_IMETHODIMP_(void) +nsHtml5Parser::SetCommand(const char* aCommand) { + NS_ASSERTION(!strcmp(aCommand, "view") || !strcmp(aCommand, "view-source") || + !strcmp(aCommand, "external-resource") || + !strcmp(aCommand, "import") || + !strcmp(aCommand, kLoadAsData), + "Unsupported parser command"); +} + +NS_IMETHODIMP_(void) +nsHtml5Parser::SetCommand(eParserCommands aParserCommand) { + NS_ASSERTION(aParserCommand == eViewNormal, + "Parser command was not eViewNormal."); +} + +void nsHtml5Parser::SetDocumentCharset(NotNull<const Encoding*> aEncoding, + int32_t aCharsetSource, + bool aForceAutoDetection) { + MOZ_ASSERT(!mExecutor->HasStarted(), "Document charset set too late."); + MOZ_ASSERT(GetStreamParser(), "Setting charset on a script-only parser."); + GetStreamParser()->SetDocumentCharset( + aEncoding, (nsCharsetSource)aCharsetSource, aForceAutoDetection); + mExecutor->SetDocumentCharsetAndSource(aEncoding, + (nsCharsetSource)aCharsetSource); +} + +nsresult nsHtml5Parser::GetChannel(nsIChannel** aChannel) { + if (GetStreamParser()) { + return GetStreamParser()->GetChannel(aChannel); + } else { + return NS_ERROR_NOT_AVAILABLE; + } +} + +nsIStreamListener* nsHtml5Parser::GetStreamListener() { + return mStreamListener; +} + +NS_IMETHODIMP +nsHtml5Parser::ContinueInterruptedParsing() { + MOZ_ASSERT_UNREACHABLE("Don't call. For interface compat only."); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP_(void) +nsHtml5Parser::BlockParser() { mBlocked++; } + +NS_IMETHODIMP_(void) +nsHtml5Parser::UnblockParser() { + MOZ_DIAGNOSTIC_ASSERT(mBlocked > 0); + if (MOZ_LIKELY(mBlocked > 0)) { + mBlocked--; + } + if (MOZ_LIKELY(mBlocked == 0) && mExecutor) { + mExecutor->ContinueInterruptedParsingAsync(); + } +} + +NS_IMETHODIMP_(void) +nsHtml5Parser::ContinueInterruptedParsingAsync() { + if (mExecutor) { + mExecutor->ContinueInterruptedParsingAsync(); + } +} + +NS_IMETHODIMP_(bool) +nsHtml5Parser::IsParserEnabled() { return !mBlocked; } + +NS_IMETHODIMP_(bool) +nsHtml5Parser::IsComplete() { return mExecutor->IsComplete(); } + +NS_IMETHODIMP +nsHtml5Parser::Parse(nsIURI* aURL) { + /* + * Do NOT cause WillBuildModel to be called synchronously from here! + * The document won't be ready for it until OnStartRequest! + */ + MOZ_ASSERT(!mExecutor->HasStarted(), + "Tried to start parse without initializing the parser."); + MOZ_ASSERT(GetStreamParser(), + "Can't call this Parse() variant on script-created parser"); + + GetStreamParser()->SetViewSourceTitle(aURL); // In case we're viewing source + mExecutor->SetStreamParser(GetStreamParser()); + mExecutor->SetParser(this); + return NS_OK; +} + +nsresult nsHtml5Parser::Parse(const nsAString& aSourceBuffer, void* aKey, + bool aLastCall) { + nsresult rv; + if (NS_FAILED(rv = mExecutor->IsBroken())) { + return rv; + } + if (aSourceBuffer.Length() > INT32_MAX) { + return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + + // Maintain a reference to ourselves so we don't go away + // till we're completely done. The old parser grips itself in this method. + nsCOMPtr<nsIParser> kungFuDeathGrip(this); + + // Gripping the other objects just in case, since the other old grip + // required grips to these, too. + RefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(GetStreamParser()); + mozilla::Unused << streamKungFuDeathGrip; // Not used within function + RefPtr<nsHtml5TreeOpExecutor> executor(mExecutor); + + MOZ_RELEASE_ASSERT(executor->HasStarted()); + + // Return early if the parser has processed EOF + if (executor->IsComplete()) { + return NS_OK; + } + + if (aLastCall && aSourceBuffer.IsEmpty() && !aKey) { + // document.close() + NS_ASSERTION(!GetStreamParser(), + "Had stream parser but got document.close()."); + if (mDocumentClosed) { + // already closed + return NS_OK; + } + mDocumentClosed = true; + if (!mBlocked && !mInDocumentWrite) { + return ParseUntilBlocked(); + } + return NS_OK; + } + + // If we got this far, we are dealing with a document.write or + // document.writeln call--not document.close(). + + MOZ_RELEASE_ASSERT( + IsInsertionPointDefined(), + "Doc.write reached parser with undefined insertion point."); + + MOZ_RELEASE_ASSERT(!(GetStreamParser() && !aKey), + "Got a null key in a non-script-created parser"); + + // XXX is this optimization bogus? + if (aSourceBuffer.IsEmpty()) { + return NS_OK; + } + + // This guard is here to prevent document.close from tokenizing synchronously + // while a document.write (that wrote the script that called document.close!) + // is still on the call stack. + mozilla::AutoRestore<bool> guard(mInDocumentWrite); + mInDocumentWrite = true; + + // The script is identified by aKey. If there's nothing in the buffer + // chain for that key, we'll insert at the head of the queue. + // When the script leaves something in the queue, a zero-length + // key-holder "buffer" is inserted in the queue. If the same script + // leaves something in the chain again, it will be inserted immediately + // before the old key holder belonging to the same script. + // + // We don't do the actual data insertion yet in the hope that the data gets + // tokenized and there no data or less data to copy to the heap after + // tokenization. Also, this way, we avoid inserting one empty data buffer + // per document.write, which matters for performance when the parser isn't + // blocked and a badly-authored script calls document.write() once per + // input character. (As seen in a benchmark!) + // + // The insertion into the input stream happens conceptually before anything + // gets tokenized. To make sure multi-level document.write works right, + // it's necessary to establish the location of our parser key up front + // in case this is the first write with this key. + // + // In a document.open() case, the first write level has a null key, so that + // case is handled separately, because normal buffers containing data + // have null keys. + + // These don't need to be owning references, because they always point to + // the buffer queue and buffers can't be removed from the buffer queue + // before document.write() returns. The buffer queue clean-up happens the + // next time ParseUntilBlocked() is called. + // However, they are made owning just in case the reasoning above is flawed + // and a flaw would lead to worse problems with plain pointers. If this + // turns out to be a perf problem, it's worthwhile to consider making + // prevSearchbuf a plain pointer again. + RefPtr<nsHtml5OwningUTF16Buffer> prevSearchBuf; + RefPtr<nsHtml5OwningUTF16Buffer> firstLevelMarker; + + if (aKey) { + if (mFirstBuffer == mLastBuffer) { + nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey); + keyHolder->next = mLastBuffer; + mFirstBuffer = keyHolder; + } else if (mFirstBuffer->key != aKey) { + prevSearchBuf = mFirstBuffer; + for (;;) { + if (prevSearchBuf->next == mLastBuffer) { + // key was not found + nsHtml5OwningUTF16Buffer* keyHolder = + new nsHtml5OwningUTF16Buffer(aKey); + keyHolder->next = mFirstBuffer; + mFirstBuffer = keyHolder; + prevSearchBuf = nullptr; + break; + } + if (prevSearchBuf->next->key == aKey) { + // found a key holder + break; + } + prevSearchBuf = prevSearchBuf->next; + } + } // else mFirstBuffer is the keyholder + + // prevSearchBuf is the previous buffer before the keyholder or null if + // there isn't one. + } else { + // We have a first-level write in the document.open() case. We insert before + // mLastBuffer, effectively, by making mLastBuffer be a new sentinel object + // and redesignating the previous mLastBuffer as our firstLevelMarker. We + // need to put a marker there, because otherwise additional document.writes + // from nested event loops would insert in the wrong place. Sigh. + mLastBuffer->next = new nsHtml5OwningUTF16Buffer((void*)nullptr); + firstLevelMarker = mLastBuffer; + mLastBuffer = mLastBuffer->next; + } + + nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer); + + while (!mBlocked && stackBuffer.hasMore()) { + stackBuffer.adjust(mLastWasCR); + mLastWasCR = false; + if (stackBuffer.hasMore()) { + int32_t lineNumberSave; + bool inRootContext = (!GetStreamParser() && !aKey); + if (inRootContext) { + mTokenizer->setLineNumber(mRootContextLineNumber); + } else { + // we aren't the root context, so save the line number on the + // *stack* so that we can restore it. + lineNumberSave = mTokenizer->getLineNumber(); + } + + if (!mTokenizer->EnsureBufferSpace(stackBuffer.getLength())) { + return executor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer); + if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) { + return executor->MarkAsBroken(rv); + } + + if (inRootContext) { + mRootContextLineNumber = mTokenizer->getLineNumber(); + } else { + mTokenizer->setLineNumber(lineNumberSave); + } + + if (mTreeBuilder->HasScript()) { + auto r = mTreeBuilder->Flush(); // Move ops to the executor + if (r.isErr()) { + return executor->MarkAsBroken(r.unwrapErr()); + } + rv = executor->FlushDocumentWrite(); // run the ops + NS_ENSURE_SUCCESS(rv, rv); + // Flushing tree ops can cause all sorts of things. + // Return early if the parser got terminated. + if (executor->IsComplete()) { + return NS_OK; + } + } + // Ignore suspension requests + } + } + + RefPtr<nsHtml5OwningUTF16Buffer> heapBuffer; + if (stackBuffer.hasMore()) { + // The buffer wasn't tokenized to completion. Create a copy of the tail + // on the heap. + heapBuffer = stackBuffer.FalliblyCopyAsOwningBuffer(); + if (!heapBuffer) { + // Allocation failed. The parser is now broken. + return executor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + } + + if (heapBuffer) { + // We have something to insert before the keyholder holding in the non-null + // aKey case and we have something to swap into firstLevelMarker in the + // null aKey case. + if (aKey) { + NS_ASSERTION(mFirstBuffer != mLastBuffer, "Where's the keyholder?"); + // the key holder is still somewhere further down the list from + // prevSearchBuf (which may be null) + if (mFirstBuffer->key == aKey) { + NS_ASSERTION( + !prevSearchBuf, + "Non-null prevSearchBuf when mFirstBuffer is the key holder?"); + heapBuffer->next = mFirstBuffer; + mFirstBuffer = heapBuffer; + } else { + if (!prevSearchBuf) { + prevSearchBuf = mFirstBuffer; + } + // We created a key holder earlier, so we will find it without walking + // past the end of the list. + while (prevSearchBuf->next->key != aKey) { + prevSearchBuf = prevSearchBuf->next; + } + heapBuffer->next = prevSearchBuf->next; + prevSearchBuf->next = heapBuffer; + } + } else { + NS_ASSERTION(firstLevelMarker, "How come we don't have a marker."); + firstLevelMarker->Swap(heapBuffer); + } + } + + if (!mBlocked) { // buffer was tokenized to completion + NS_ASSERTION(!stackBuffer.hasMore(), + "Buffer wasn't tokenized to completion?"); + // Scripting semantics require a forced tree builder flush here + auto r = mTreeBuilder->Flush(); // Move ops to the executor + if (r.isErr()) { + return executor->MarkAsBroken(r.unwrapErr()); + } + rv = executor->FlushDocumentWrite(); // run the ops + NS_ENSURE_SUCCESS(rv, rv); + } else if (stackBuffer.hasMore()) { + // The buffer wasn't tokenized to completion. Tokenize the untokenized + // content in order to preload stuff. This content will be retokenized + // later for normal parsing. + if (!mDocWriteSpeculatorActive) { + mDocWriteSpeculatorActive = true; + if (!mDocWriteSpeculativeTreeBuilder) { + // Lazily initialize if uninitialized + mDocWriteSpeculativeTreeBuilder = + mozilla::MakeUnique<nsHtml5TreeBuilder>(nullptr, + executor->GetStage(), true); + mDocWriteSpeculativeTreeBuilder->setScriptingEnabled( + mTreeBuilder->isScriptingEnabled()); + mDocWriteSpeculativeTokenizer = mozilla::MakeUnique<nsHtml5Tokenizer>( + mDocWriteSpeculativeTreeBuilder.get(), false); + mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable); + mDocWriteSpeculativeTokenizer->start(); + } + mDocWriteSpeculativeTokenizer->resetToDataState(); + mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder.get()); + mDocWriteSpeculativeLastWasCR = false; + } + + // Note that with multilevel document.write if we didn't just activate the + // speculator, it's possible that the speculator is now in the wrong state. + // That's OK for the sake of simplicity. The worst that can happen is + // that the speculative loads aren't exactly right. The content will be + // reparsed anyway for non-preload purposes. + + // The buffer position for subsequent non-speculative parsing now lives + // in heapBuffer, so it's ok to let the buffer position of stackBuffer + // to be overwritten and not restored below. + while (stackBuffer.hasMore()) { + stackBuffer.adjust(mDocWriteSpeculativeLastWasCR); + if (stackBuffer.hasMore()) { + if (!mDocWriteSpeculativeTokenizer->EnsureBufferSpace( + stackBuffer.getLength())) { + return executor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + mDocWriteSpeculativeLastWasCR = + mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer); + nsresult rv; + if (NS_FAILED((rv = mDocWriteSpeculativeTreeBuilder->IsBroken()))) { + return executor->MarkAsBroken(rv); + } + } + } + + auto r = mDocWriteSpeculativeTreeBuilder->Flush(); + if (r.isErr()) { + return executor->MarkAsBroken(r.unwrapErr()); + } + mDocWriteSpeculativeTreeBuilder->DropHandles(); + executor->FlushSpeculativeLoads(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsHtml5Parser::Terminate() { + // Prevent a second call to DidBuildModel via document.close() + mDocumentClosed = true; + // We should only call DidBuildModel once, so don't do anything if this is + // the second time that Terminate has been called. + if (mExecutor->IsComplete()) { + return NS_OK; + } + // XXX - [ until we figure out a way to break parser-sink circularity ] + // Hack - Hold a reference until we are completely done... + nsCOMPtr<nsIParser> kungFuDeathGrip(this); + RefPtr<nsHtml5StreamParser> streamParser(GetStreamParser()); + RefPtr<nsHtml5TreeOpExecutor> executor(mExecutor); + if (streamParser) { + streamParser->Terminate(); + } + return executor->DidBuildModel(true); +} + +bool nsHtml5Parser::IsInsertionPointDefined() { + return !mExecutor->IsFlushing() && !mInsertionPointPermanentlyUndefined && + (!GetStreamParser() || mScriptNestingLevel != 0); +} + +void nsHtml5Parser::IncrementScriptNestingLevel() { ++mScriptNestingLevel; } + +void nsHtml5Parser::DecrementScriptNestingLevel() { --mScriptNestingLevel; } + +bool nsHtml5Parser::HasNonzeroScriptNestingLevel() const { + return mScriptNestingLevel != 0; +} + +void nsHtml5Parser::MarkAsNotScriptCreated(const char* aCommand) { + MOZ_ASSERT(!mStreamListener, "Must not call this twice."); + eParserMode mode = NORMAL; + if (!nsCRT::strcmp(aCommand, "view-source")) { + mode = VIEW_SOURCE_HTML; + } else if (!nsCRT::strcmp(aCommand, "view-source-xml")) { + mode = VIEW_SOURCE_XML; + } else if (!nsCRT::strcmp(aCommand, "view-source-plain")) { + mode = VIEW_SOURCE_PLAIN; + } else if (!nsCRT::strcmp(aCommand, "plain-text")) { + mode = PLAIN_TEXT; + } else if (!nsCRT::strcmp(aCommand, kLoadAsData)) { + mode = LOAD_AS_DATA; + } +#ifdef DEBUG + else { + NS_ASSERTION(!nsCRT::strcmp(aCommand, "view") || + !nsCRT::strcmp(aCommand, "external-resource") || + !nsCRT::strcmp(aCommand, "import"), + "Unsupported parser command!"); + } +#endif + mStreamListener = + new nsHtml5StreamListener(new nsHtml5StreamParser(mExecutor, this, mode)); +} + +bool nsHtml5Parser::IsScriptCreated() { return !GetStreamParser(); } + +/* End nsIParser */ + +// not from interface +nsresult nsHtml5Parser::ParseUntilBlocked() { + nsresult rv = mExecutor->IsBroken(); + NS_ENSURE_SUCCESS(rv, rv); + if (mBlocked || mInsertionPointPermanentlyUndefined || + mExecutor->IsComplete()) { + return NS_OK; + } + NS_ASSERTION(mExecutor->HasStarted(), "Bad life cycle."); + NS_ASSERTION(!mInDocumentWrite, + "ParseUntilBlocked entered while in doc.write!"); + + mDocWriteSpeculatorActive = false; + + for (;;) { + if (!mFirstBuffer->hasMore()) { + if (mFirstBuffer == mLastBuffer) { + if (mExecutor->IsComplete()) { + // something like cache manisfests stopped the parse in mid-flight + return NS_OK; + } + if (mDocumentClosed) { + PermanentlyUndefineInsertionPoint(); + nsresult rv; + MOZ_RELEASE_ASSERT( + !GetStreamParser(), + "This should only happen with script-created parser."); + if (NS_SUCCEEDED((rv = mExecutor->IsBroken()))) { + mTokenizer->eof(); + if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) { + mExecutor->MarkAsBroken(rv); + } else { + mTreeBuilder->StreamEnded(); + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return mExecutor->MarkAsBroken(r.unwrapErr()); + } + mExecutor->FlushDocumentWrite(); + // The below call does memory cleanup, so call it even if the + // parser has been marked as broken. + mTokenizer->end(); + return rv; + } + // never release the last buffer. + NS_ASSERTION(!mLastBuffer->getStart() && !mLastBuffer->getEnd(), + "Sentinel buffer had its indeces changed."); + if (GetStreamParser()) { + if (mReturnToStreamParserPermitted && + !mExecutor->IsScriptExecuting()) { + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return mExecutor->MarkAsBroken(r.unwrapErr()); + } + mReturnToStreamParserPermitted = false; + GetStreamParser()->ContinueAfterScriptsOrEncodingCommitment( + mTokenizer.get(), mTreeBuilder.get(), mLastWasCR); + } + } else { + // Script-created parser + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return mExecutor->MarkAsBroken(r.unwrapErr()); + } + // No need to flush the executor, because the executor is already + // in a flush + NS_ASSERTION(mExecutor->IsInFlushLoop(), + "How did we come here without being in the flush loop?"); + } + return NS_OK; // no more data for now but expecting more + } + mFirstBuffer = mFirstBuffer->next; + continue; + } + + if (mBlocked || mExecutor->IsComplete()) { + return NS_OK; + } + + // now we have a non-empty buffer + mFirstBuffer->adjust(mLastWasCR); + mLastWasCR = false; + if (mFirstBuffer->hasMore()) { + bool inRootContext = (!GetStreamParser() && !mFirstBuffer->key); + if (inRootContext) { + mTokenizer->setLineNumber(mRootContextLineNumber); + } + if (!mTokenizer->EnsureBufferSpace(mFirstBuffer->getLength())) { + return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer); + nsresult rv; + if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) { + return mExecutor->MarkAsBroken(rv); + } + if (inRootContext) { + mRootContextLineNumber = mTokenizer->getLineNumber(); + } + if (mTreeBuilder->HasScript()) { + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return mExecutor->MarkAsBroken(r.unwrapErr()); + } + rv = mExecutor->FlushDocumentWrite(); + NS_ENSURE_SUCCESS(rv, rv); + } + if (mBlocked) { + return NS_OK; + } + } + } +} + +nsresult nsHtml5Parser::StartExecutor() { + MOZ_ASSERT(!GetStreamParser(), + "Had stream parser but document.write started life cycle."); + // This is part of the setup document.open() does. + RefPtr<nsHtml5TreeOpExecutor> executor(mExecutor); + executor->SetParser(this); + mTreeBuilder->setScriptingEnabled(executor->IsScriptEnabled()); + + mTreeBuilder->setIsSrcdocDocument(false); + + mTokenizer->start(); + executor->Start(); + + /* + * We know we're in document.open(), so our document must already + * have a script global andthe WillBuildModel call is safe. + */ + return executor->WillBuildModel(); +} + +nsresult nsHtml5Parser::Initialize(mozilla::dom::Document* aDoc, nsIURI* aURI, + nsISupports* aContainer, + nsIChannel* aChannel) { + return mExecutor->Init(aDoc, aURI, aContainer, aChannel); +} + +void nsHtml5Parser::StartTokenizer(bool aScriptingEnabled) { + bool isSrcdoc = false; + nsCOMPtr<nsIChannel> channel; + nsresult rv = GetChannel(getter_AddRefs(channel)); + if (NS_SUCCEEDED(rv)) { + isSrcdoc = NS_IsSrcdocChannel(channel); + } + mTreeBuilder->setIsSrcdocDocument(isSrcdoc); + + mTreeBuilder->SetPreventScriptExecution(!aScriptingEnabled); + mTreeBuilder->setScriptingEnabled(aScriptingEnabled); + mTokenizer->start(); +} + +void nsHtml5Parser::InitializeDocWriteParserState( + nsAHtml5TreeBuilderState* aState, int32_t aLine) { + mTokenizer->resetToDataState(); + mTokenizer->setLineNumber(aLine); + mTreeBuilder->loadState(aState); + mLastWasCR = false; + mReturnToStreamParserPermitted = true; +} + +void nsHtml5Parser::ContinueAfterFailedCharsetSwitch() { + MOZ_ASSERT( + GetStreamParser(), + "Tried to continue after failed charset switch without a stream parser"); + GetStreamParser()->ContinueAfterFailedCharsetSwitch(); +} diff --git a/parser/html/nsHtml5Parser.h b/parser/html/nsHtml5Parser.h new file mode 100644 index 0000000000..593d52bc42 --- /dev/null +++ b/parser/html/nsHtml5Parser.h @@ -0,0 +1,337 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef NS_HTML5_PARSER +#define NS_HTML5_PARSER + +#include "mozilla/UniquePtr.h" +#include "nsIParser.h" +#include "nsDeque.h" +#include "nsIContentSink.h" +#include "nsIRequest.h" +#include "nsIChannel.h" +#include "nsCOMArray.h" +#include "nsContentSink.h" +#include "nsCycleCollectionParticipant.h" +#include "nsHtml5OwningUTF16Buffer.h" +#include "nsHtml5TreeOpExecutor.h" +#include "nsHtml5StreamParser.h" +#include "nsHtml5AtomTable.h" +#include "nsWeakReference.h" +#include "nsHtml5StreamListener.h" +#include "nsCharsetSource.h" + +class nsHtml5Parser final : public nsIParser, public nsSupportsWeakReference { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHtml5Parser, nsIParser) + + nsHtml5Parser(); + + /* Start nsIParser */ + /** + * No-op for backwards compat. + */ + NS_IMETHOD_(void) SetContentSink(nsIContentSink* aSink) override; + + /** + * Returns the tree op executor for backwards compat. + */ + NS_IMETHOD_(nsIContentSink*) GetContentSink() override; + + /** + * Always returns "view" for backwards compat. + */ + NS_IMETHOD_(void) GetCommand(nsCString& aCommand) override; + + /** + * No-op for backwards compat. + */ + NS_IMETHOD_(void) SetCommand(const char* aCommand) override; + + /** + * No-op for backwards compat. + */ + NS_IMETHOD_(void) SetCommand(eParserCommands aParserCommand) override; + + /** + * Call this method once you've created a parser, and want to instruct it + * about what charset to load + * + * @param aEncoding the charset of a document + * @param aCharsetSource the source of the charset + */ + virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding, + int32_t aSource, + bool aForceAutoDetection) override; + + /** + * Get the channel associated with this parser + * @param aChannel out param that will contain the result + * @return NS_OK if successful or NS_NOT_AVAILABLE if not + */ + nsresult GetChannel(nsIChannel** aChannel); + + /** + * Get the stream parser for this parser + */ + virtual nsIStreamListener* GetStreamListener() override; + + /** + * Don't call. For interface compat only. + */ + NS_IMETHOD ContinueInterruptedParsing() override; + + /** + * Blocks the parser. + */ + NS_IMETHOD_(void) BlockParser() override; + + /** + * Unblocks the parser. + */ + NS_IMETHOD_(void) UnblockParser() override; + + /** + * Asynchronously continues parsing. + */ + NS_IMETHOD_(void) ContinueInterruptedParsingAsync() override; + + /** + * Query whether the parser is enabled (i.e. not blocked) or not. + */ + NS_IMETHOD_(bool) IsParserEnabled() override; + + /** + * Query whether the parser thinks it's done with parsing. + */ + NS_IMETHOD_(bool) IsComplete() override; + + /** + * Set up request observer. + * + * @param aURL used for View Source title + */ + NS_IMETHOD Parse(nsIURI* aURL) override; + + /** + * document.write and document.close + * + * @param aSourceBuffer the argument of document.write (empty for .close()) + * @param aKey a key unique to the script element that caused this call + * @param aLastCall true if .close() false if .write() + */ + nsresult Parse(const nsAString& aSourceBuffer, void* aKey, bool aLastCall); + + /** + * Stops the parser prematurely + */ + NS_IMETHOD Terminate() override; + + /** + * True if the insertion point (per HTML5) is defined. + */ + virtual bool IsInsertionPointDefined() override; + + /** + * Call immediately before starting to evaluate a parser-inserted script or + * in general when the spec says to increment the script nesting level. + */ + void IncrementScriptNestingLevel() final; + + /** + * Call immediately after having evaluated a parser-inserted script or + * generally want to restore to the state before the last + * IncrementScriptNestingLevel call. + */ + void DecrementScriptNestingLevel() final; + + /** + * True if this is an HTML5 parser whose script nesting level (in + * the sense of + * <https://html.spec.whatwg.org/multipage/parsing.html#script-nesting-level>) + * is nonzero. + */ + bool HasNonzeroScriptNestingLevel() const final; + + /** + * Marks the HTML5 parser as not a script-created parser: Prepares the + * parser to be able to read a stream. + * + * @param aCommand the parser command (Yeah, this is bad API design. Let's + * make this better when retiring nsIParser) + */ + void MarkAsNotScriptCreated(const char* aCommand); + + /** + * True if this is a script-created HTML5 parser. + */ + virtual bool IsScriptCreated() override; + + /* End nsIParser */ + + // Not from an external interface + // Non-inherited methods + + public: + /** + * Initializes the parser to load from a channel. + */ + virtual nsresult Initialize(mozilla::dom::Document* aDoc, nsIURI* aURI, + nsISupports* aContainer, nsIChannel* aChannel); + + inline nsHtml5Tokenizer* GetTokenizer() { return mTokenizer.get(); } + + void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, + int32_t aLine); + + void DropStreamParser() { + if (GetStreamParser()) { + GetStreamParser()->DropTimer(); + mStreamListener->DropDelegate(); + mStreamListener = nullptr; + } + } + + void StartTokenizer(bool aScriptingEnabled); + + void ContinueAfterFailedCharsetSwitch(); + + nsHtml5StreamParser* GetStreamParser() { + if (!mStreamListener) { + return nullptr; + } + return mStreamListener->GetDelegate(); + } + + void PermanentlyUndefineInsertionPoint() { + mInsertionPointPermanentlyUndefined = true; + } + + /** + * Parse until pending data is exhausted or a script blocks the parser + */ + nsresult ParseUntilBlocked(); + + /** + * Start our executor. This is meant to be used from document.open() _only_ + * and does some work similar to what nsHtml5StreamParser::OnStartRequest does + * for normal parses. + */ + nsresult StartExecutor(); + + private: + virtual ~nsHtml5Parser(); + + // State variables + + /** + * Whether the last character tokenized was a carriage return (for CRLF) + */ + bool mLastWasCR; + + /** + * Whether the last character tokenized was a carriage return (for CRLF) + * when preparsing document.write. + */ + bool mDocWriteSpeculativeLastWasCR; + + /** + * The parser is blocking on the load of an external script from a web + * page, or any number of extension content scripts. + */ + uint32_t mBlocked; + + /** + * Whether the document.write() speculator is already active. + */ + bool mDocWriteSpeculatorActive; + + /** + * The number of IncrementScriptNestingLevel calls we've seen without a + * matching DecrementScriptNestingLevel. + */ + int32_t mScriptNestingLevel; + + /** + * True if document.close() has been called. + */ + bool mDocumentClosed; + + bool mInDocumentWrite; + + /** + * This is set when the tokenizer has seen EOF. The purpose is to + * keep the insertion point undefined between the time the + * parser has reached the point where it can't accept more input + * and the time the document's mParser is set to nullptr. + * Scripts can run during this time period due to an update + * batch ending and due to various end-of-parse events firing. + * (Setting mParser on the document to nullptr at the point + * where this flag gets set to true would break things that for + * legacy reasons assume that mParser on the document stays + * non-null though the end-of-parse events.) + */ + bool mInsertionPointPermanentlyUndefined; + + // Portable parser objects + /** + * The first buffer in the pending UTF-16 buffer queue + */ + RefPtr<nsHtml5OwningUTF16Buffer> mFirstBuffer; + + /** + * The last buffer in the pending UTF-16 buffer queue. Always points + * to a sentinel object with nullptr as its parser key. + */ + nsHtml5OwningUTF16Buffer* mLastBuffer; // weak ref; + + /** + * The tree operation executor + */ + RefPtr<nsHtml5TreeOpExecutor> mExecutor; + + /** + * The HTML5 tree builder + */ + const mozilla::UniquePtr<nsHtml5TreeBuilder> mTreeBuilder; + + /** + * The HTML5 tokenizer + */ + const mozilla::UniquePtr<nsHtml5Tokenizer> mTokenizer; + + /** + * Another HTML5 tree builder for preloading document.written content. + */ + mozilla::UniquePtr<nsHtml5TreeBuilder> mDocWriteSpeculativeTreeBuilder; + + /** + * Another HTML5 tokenizer for preloading document.written content. + */ + mozilla::UniquePtr<nsHtml5Tokenizer> mDocWriteSpeculativeTokenizer; + + /** + * The stream listener holding the stream parser. + */ + RefPtr<nsHtml5StreamListener> mStreamListener; + + /** + * + */ + int32_t mRootContextLineNumber; + + /** + * Whether it's OK to transfer parsing back to the stream parser + */ + bool mReturnToStreamParserPermitted; + + /** + * The scoped atom table + */ + nsHtml5AtomTable mAtomTable; +}; +#endif diff --git a/parser/html/nsHtml5PlainTextUtils.cpp b/parser/html/nsHtml5PlainTextUtils.cpp new file mode 100644 index 0000000000..17bf83c6ca --- /dev/null +++ b/parser/html/nsHtml5PlainTextUtils.cpp @@ -0,0 +1,33 @@ +/* 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/. */ + +#include "nsHtml5PlainTextUtils.h" +#include "nsHtml5AttributeName.h" +#include "nsHtml5Portability.h" +#include "nsHtml5String.h" +#include "nsGkAtoms.h" +#include "mozilla/StaticPrefs_plain_text.h" + +// static +nsHtml5HtmlAttributes* nsHtml5PlainTextUtils::NewLinkAttributes() { + nsHtml5HtmlAttributes* linkAttrs = new nsHtml5HtmlAttributes(0); + nsHtml5String rel = nsHtml5Portability::newStringFromLiteral("stylesheet"); + linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_REL, rel, -1); + nsHtml5String href = nsHtml5Portability::newStringFromLiteral( + "resource://content-accessible/plaintext.css"); + linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_HREF, href, -1); + return linkAttrs; +} + +// static +nsHtml5HtmlAttributes* nsHtml5PlainTextUtils::NewBodyAttributes() { + if (mozilla::StaticPrefs::plain_text_wrap_long_lines()) { + return nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES; + } + nsHtml5HtmlAttributes* bodyAttrs = new nsHtml5HtmlAttributes(0); + RefPtr<nsAtom> nowrap = nsGkAtoms::nowrap; + bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_CLASS, + nsHtml5String::FromAtom(nowrap.forget()), -1); + return bodyAttrs; +} diff --git a/parser/html/nsHtml5PlainTextUtils.h b/parser/html/nsHtml5PlainTextUtils.h new file mode 100644 index 0000000000..a56a8fc81a --- /dev/null +++ b/parser/html/nsHtml5PlainTextUtils.h @@ -0,0 +1,16 @@ +/* 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/. */ + +#ifndef nsHtml5PlainTextUtils_h +#define nsHtml5PlainTextUtils_h + +#include "nsHtml5HtmlAttributes.h" + +class nsHtml5PlainTextUtils { + public: + static nsHtml5HtmlAttributes* NewLinkAttributes(); + static nsHtml5HtmlAttributes* NewBodyAttributes(); +}; + +#endif // nsHtml5PlainTextUtils_h diff --git a/parser/html/nsHtml5Portability.cpp b/parser/html/nsHtml5Portability.cpp new file mode 100644 index 0000000000..e947c9e257 --- /dev/null +++ b/parser/html/nsHtml5Portability.cpp @@ -0,0 +1,109 @@ +/* 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/. */ + +#include "nsHtml5Portability.h" +#include "jArray.h" +#include "nsAtom.h" +#include "nsHtml5TreeBuilder.h" +#include "nsString.h" +#include "mozilla/CheckedInt.h" + +int32_t nsHtml5Portability::checkedAdd(int32_t a, int32_t b) { + mozilla::CheckedInt<int32_t> sum(a); + sum += b; + MOZ_RELEASE_ASSERT(sum.isValid(), + "HTML input too large for signed 32-bit integer."); + return sum.value(); +} + +nsAtom* nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf, + int32_t length, + nsHtml5AtomTable* interner) { + NS_ASSERTION(interner, "Didn't get an atom service."); + return interner->GetAtom(nsDependentSubstring(buf, buf + length)); +} + +static bool ContainsWhiteSpace(mozilla::Span<char16_t> aSpan) { + for (char16_t c : aSpan) { + if (nsContentUtils::IsHTMLWhitespace(c)) { + return true; + } + } + return false; +} + +nsHtml5String nsHtml5Portability::newStringFromBuffer( + char16_t* buf, int32_t offset, int32_t length, + nsHtml5TreeBuilder* treeBuilder, bool maybeAtomize) { + if (!length) { + return nsHtml5String::EmptyString(); + } + if (maybeAtomize && + !ContainsWhiteSpace(mozilla::Span(buf + offset, length))) { + return nsHtml5String::FromAtom( + NS_AtomizeMainThread(nsDependentSubstring(buf + offset, length))); + } + return nsHtml5String::FromBuffer(buf + offset, length, treeBuilder); +} + +nsHtml5String nsHtml5Portability::newEmptyString() { + return nsHtml5String::EmptyString(); +} + +nsHtml5String nsHtml5Portability::newStringFromLiteral(const char* literal) { + return nsHtml5String::FromLiteral(literal); +} + +nsHtml5String nsHtml5Portability::newStringFromString(nsHtml5String string) { + return string.Clone(); +} + +jArray<char16_t, int32_t> nsHtml5Portability::newCharArrayFromLocal( + nsAtom* local) { + nsAutoString temp; + local->ToString(temp); + int32_t len = temp.Length(); + jArray<char16_t, int32_t> arr = jArray<char16_t, int32_t>::newJArray(len); + memcpy(arr, temp.BeginReading(), len * sizeof(char16_t)); + return arr; +} + +jArray<char16_t, int32_t> nsHtml5Portability::newCharArrayFromString( + nsHtml5String string) { + MOZ_RELEASE_ASSERT(string); + uint32_t len = string.Length(); + MOZ_RELEASE_ASSERT(len < INT32_MAX); + jArray<char16_t, int32_t> arr = jArray<char16_t, int32_t>::newJArray(len); + string.CopyToBuffer(arr); + return arr; +} + +bool nsHtml5Portability::localEqualsBuffer(nsAtom* local, char16_t* buf, + int32_t length) { + return local->Equals(buf, length); +} + +bool nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + const char* lowerCaseLiteral, nsHtml5String string) { + return string.LowerCaseStartsWithASCII(lowerCaseLiteral); +} + +bool nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + const char* lowerCaseLiteral, nsHtml5String string) { + return string.LowerCaseEqualsASCII(lowerCaseLiteral); +} + +bool nsHtml5Portability::literalEqualsString(const char* literal, + nsHtml5String string) { + return string.EqualsASCII(literal); +} + +bool nsHtml5Portability::stringEqualsString(nsHtml5String one, + nsHtml5String other) { + return one.Equals(other); +} + +void nsHtml5Portability::initializeStatics() {} + +void nsHtml5Portability::releaseStatics() {} diff --git a/parser/html/nsHtml5Portability.h b/parser/html/nsHtml5Portability.h new file mode 100644 index 0000000000..18d2bd6b7e --- /dev/null +++ b/parser/html/nsHtml5Portability.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008-2015 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit Portability.java instead and regenerate. + */ + +#ifndef nsHtml5Portability_h +#define nsHtml5Portability_h + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5ContentCreatorFunction.h" + +class nsHtml5StreamParser; + +class nsHtml5AttributeName; +class nsHtml5ElementName; +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5UTF16Buffer; +class nsHtml5StateSnapshot; + +class nsHtml5Portability { + public: + static int32_t checkedAdd(int32_t a, int32_t b); + static nsAtom* newLocalNameFromBuffer(char16_t* buf, int32_t length, + nsHtml5AtomTable* interner); + static nsHtml5String newStringFromBuffer(char16_t* buf, int32_t offset, + int32_t length, + nsHtml5TreeBuilder* treeBuilder, + bool maybeAtomize); + static nsHtml5String newEmptyString(); + static nsHtml5String newStringFromLiteral(const char* literal); + static nsHtml5String newStringFromString(nsHtml5String string); + static jArray<char16_t, int32_t> newCharArrayFromLocal(nsAtom* local); + static jArray<char16_t, int32_t> newCharArrayFromString(nsHtml5String string); + static bool localEqualsBuffer(nsAtom* local, char16_t* buf, int32_t length); + static bool lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + const char* lowerCaseLiteral, nsHtml5String string); + static bool lowerCaseLiteralEqualsIgnoreAsciiCaseString( + const char* lowerCaseLiteral, nsHtml5String string); + static bool literalEqualsString(const char* literal, nsHtml5String string); + static bool stringEqualsString(nsHtml5String one, nsHtml5String other); + static void initializeStatics(); + static void releaseStatics(); +}; + +#endif diff --git a/parser/html/nsHtml5SVGLoadDispatcher.cpp b/parser/html/nsHtml5SVGLoadDispatcher.cpp new file mode 100644 index 0000000000..cbd711a98f --- /dev/null +++ b/parser/html/nsHtml5SVGLoadDispatcher.cpp @@ -0,0 +1,35 @@ +/* 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/. */ + +#include "nsHtml5SVGLoadDispatcher.h" +#include "mozilla/BasicEvents.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/DocumentInlines.h" +#include "nsPresContext.h" + +using namespace mozilla; + +nsHtml5SVGLoadDispatcher::nsHtml5SVGLoadDispatcher(nsIContent* aElement) + : Runnable("nsHtml5SVGLoadDispatcher"), + mElement(aElement), + mDocument(mElement->OwnerDoc()) { + mDocument->BlockOnload(); +} + +// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230, bug 1535398) +MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP nsHtml5SVGLoadDispatcher::Run() { + WidgetEvent event(true, eSVGLoad); + event.mFlags.mBubbles = false; + // Do we care about forcing presshell creation if it hasn't happened yet? + // That is, should this code flush or something? Does it really matter? + // For that matter, do we really want to try getting the prescontext? + // Does this event ever want one? + RefPtr<nsPresContext> ctx = mElement->OwnerDoc()->GetPresContext(); + EventDispatcher::Dispatch(mElement, ctx, &event); + // Unblocking onload on the same document that it was blocked even if + // the element has moved between docs since blocking. + mDocument->UnblockOnload(false); + return NS_OK; +} diff --git a/parser/html/nsHtml5SVGLoadDispatcher.h b/parser/html/nsHtml5SVGLoadDispatcher.h new file mode 100644 index 0000000000..9079e5f430 --- /dev/null +++ b/parser/html/nsHtml5SVGLoadDispatcher.h @@ -0,0 +1,21 @@ +/* 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/. */ + +#ifndef nsHtml5SVGLoadDispatcher_h +#define nsHtml5SVGLoadDispatcher_h + +#include "nsThreadUtils.h" +#include "nsIContent.h" + +class nsHtml5SVGLoadDispatcher : public mozilla::Runnable { + private: + const nsCOMPtr<nsIContent> mElement; + const RefPtr<mozilla::dom::Document> mDocument; + + public: + explicit nsHtml5SVGLoadDispatcher(nsIContent* aElement); + NS_IMETHOD Run() override; +}; + +#endif // nsHtml5SVGLoadDispatcher_h diff --git a/parser/html/nsHtml5Speculation.cpp b/parser/html/nsHtml5Speculation.cpp new file mode 100644 index 0000000000..0cf7816ff6 --- /dev/null +++ b/parser/html/nsHtml5Speculation.cpp @@ -0,0 +1,32 @@ +/* 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/. */ + +#include "nsHtml5Speculation.h" + +using namespace mozilla; + +nsHtml5Speculation::nsHtml5Speculation(nsHtml5OwningUTF16Buffer* aBuffer, + int32_t aStart, int32_t aStartLineNumber, + int32_t aStartColumnNumber, + nsAHtml5TreeBuilderState* aSnapshot) + : mBuffer(aBuffer), + mStart(aStart), + mStartLineNumber(aStartLineNumber), + mStartColumnNumber(aStartColumnNumber), + mSnapshot(aSnapshot) { + MOZ_COUNT_CTOR(nsHtml5Speculation); +} + +nsHtml5Speculation::~nsHtml5Speculation() { + MOZ_COUNT_DTOR(nsHtml5Speculation); +} + +[[nodiscard]] bool nsHtml5Speculation::MoveOpsFrom( + nsTArray<nsHtml5TreeOperation>& aOpQueue) { + return !!mOpQueue.AppendElements(std::move(aOpQueue), mozilla::fallible_t()); +} + +[[nodiscard]] bool nsHtml5Speculation::FlushToSink(nsAHtml5TreeOpSink* aSink) { + return aSink->MoveOpsFrom(mOpQueue); +} diff --git a/parser/html/nsHtml5Speculation.h b/parser/html/nsHtml5Speculation.h new file mode 100644 index 0000000000..9bd04a7c19 --- /dev/null +++ b/parser/html/nsHtml5Speculation.h @@ -0,0 +1,69 @@ +/* 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/. */ + +#ifndef nsHtml5Speculation_h +#define nsHtml5Speculation_h + +#include "nsHtml5OwningUTF16Buffer.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsHtml5TreeOperation.h" +#include "nsAHtml5TreeOpSink.h" +#include "nsTArray.h" +#include "mozilla/Attributes.h" +#include "mozilla/UniquePtr.h" + +class nsHtml5Speculation final : public nsAHtml5TreeOpSink { + public: + nsHtml5Speculation(nsHtml5OwningUTF16Buffer* aBuffer, int32_t aStart, + int32_t aStartLineNumber, int32_t aStartColumnNumber, + nsAHtml5TreeBuilderState* aSnapshot); + + ~nsHtml5Speculation(); + + nsHtml5OwningUTF16Buffer* GetBuffer() { return mBuffer; } + + int32_t GetStart() { return mStart; } + + int32_t GetStartLineNumber() { return mStartLineNumber; } + + int32_t GetStartColumnNumber() { return mStartColumnNumber; } + + nsAHtml5TreeBuilderState* GetSnapshot() { return mSnapshot.get(); } + + /** + * Flush the operations from the tree operations from the argument + * queue unconditionally. + */ + [[nodiscard]] virtual bool MoveOpsFrom( + nsTArray<nsHtml5TreeOperation>& aOpQueue) override; + + [[nodiscard]] bool FlushToSink(nsAHtml5TreeOpSink* aSink); + + private: + /** + * The first buffer in the pending UTF-16 buffer queue + */ + RefPtr<nsHtml5OwningUTF16Buffer> mBuffer; + + /** + * The start index of this speculation in the first buffer + */ + int32_t mStart; + + /** + * The current line number at the start of the speculation + */ + int32_t mStartLineNumber; + + /** + * The current line number at the start of the speculation. + */ + int32_t mStartColumnNumber; + + mozilla::UniquePtr<nsAHtml5TreeBuilderState> mSnapshot; + + nsTArray<nsHtml5TreeOperation> mOpQueue; +}; + +#endif // nsHtml5Speculation_h diff --git a/parser/html/nsHtml5SpeculativeLoad.cpp b/parser/html/nsHtml5SpeculativeLoad.cpp new file mode 100644 index 0000000000..f7994495a6 --- /dev/null +++ b/parser/html/nsHtml5SpeculativeLoad.cpp @@ -0,0 +1,158 @@ +/* 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/. */ + +#include "nsHtml5SpeculativeLoad.h" +#include "mozilla/Encoding.h" +#include "nsHtml5TreeOpExecutor.h" + +using namespace mozilla; + +nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad() + : mOpCode(eSpeculativeLoadUninitialized), + mIsAsync(false), + mIsDefer(false), + mIsLinkPreload(false), + mIsError(false), + mEncoding(nullptr) { + MOZ_COUNT_CTOR(nsHtml5SpeculativeLoad); + new (&mCharsetOrSrcset) nsString; +} + +nsHtml5SpeculativeLoad::~nsHtml5SpeculativeLoad() { + MOZ_COUNT_DTOR(nsHtml5SpeculativeLoad); + NS_ASSERTION(mOpCode != eSpeculativeLoadUninitialized, + "Uninitialized speculative load."); + if (!(mOpCode == eSpeculativeLoadSetDocumentCharset || + mOpCode == eSpeculativeLoadMaybeComplainAboutCharset)) { + mCharsetOrSrcset.~nsString(); + } +} + +void nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor) { + switch (mOpCode) { + case eSpeculativeLoadBase: + aExecutor->SetSpeculationBase(mUrlOrSizes); + break; + case eSpeculativeLoadCSP: + aExecutor->AddSpeculationCSP( + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); + break; + case eSpeculativeLoadMetaReferrer: + aExecutor->UpdateReferrerInfoFromMeta(mReferrerPolicyOrIntegrity); + break; + case eSpeculativeLoadImage: + aExecutor->PreloadImage( + mUrlOrSizes, mCrossOrigin, mMedia, mCharsetOrSrcset, + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity, + mReferrerPolicyOrIntegrity, mIsLinkPreload, mInitTimestamp); + break; + case eSpeculativeLoadOpenPicture: + aExecutor->PreloadOpenPicture(); + break; + case eSpeculativeLoadEndPicture: + aExecutor->PreloadEndPicture(); + break; + case eSpeculativeLoadPictureSource: + aExecutor->PreloadPictureSource( + mCharsetOrSrcset, mUrlOrSizes, + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity, + mMedia); + break; + case eSpeculativeLoadScript: + aExecutor->PreloadScript( + mUrlOrSizes, mCharsetOrSrcset, + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity, + mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity, + mScriptReferrerPolicy, false, mIsAsync, mIsDefer, false, + mIsLinkPreload); + break; + case eSpeculativeLoadScriptFromHead: + aExecutor->PreloadScript( + mUrlOrSizes, mCharsetOrSrcset, + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity, + mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity, + mScriptReferrerPolicy, true, mIsAsync, mIsDefer, false, + mIsLinkPreload); + break; + case eSpeculativeLoadNoModuleScript: + aExecutor->PreloadScript( + mUrlOrSizes, mCharsetOrSrcset, + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity, + mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity, + mScriptReferrerPolicy, false, mIsAsync, mIsDefer, true, + mIsLinkPreload); + break; + case eSpeculativeLoadNoModuleScriptFromHead: + aExecutor->PreloadScript( + mUrlOrSizes, mCharsetOrSrcset, + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity, + mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity, + mScriptReferrerPolicy, true, mIsAsync, mIsDefer, true, + mIsLinkPreload); + break; + case eSpeculativeLoadStyle: + aExecutor->PreloadStyle( + mUrlOrSizes, mCharsetOrSrcset, mCrossOrigin, mMedia, + mReferrerPolicyOrIntegrity, + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity, + mIsLinkPreload); + break; + case eSpeculativeLoadManifest: + // TODO: remove this + break; + case eSpeculativeLoadSetDocumentCharset: { + MOZ_ASSERT(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity + .Length() == 1, + "Unexpected charset source string"); + nsCharsetSource enumSource = + (nsCharsetSource) + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity + .First(); + aExecutor->SetDocumentCharsetAndSource(WrapNotNull(mEncoding), + enumSource); + if (mCommitEncodingSpeculation) { + aExecutor->CommitToInternalEncoding(); + } + } break; + case eSpeculativeLoadSetDocumentMode: { + NS_ASSERTION(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity + .Length() == 1, + "Unexpected document mode string"); + nsHtml5DocumentMode mode = + (nsHtml5DocumentMode) + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity + .First(); + aExecutor->SetDocumentMode(mode); + } break; + case eSpeculativeLoadPreconnect: + aExecutor->Preconnect(mUrlOrSizes, mCrossOrigin); + break; + case eSpeculativeLoadFont: + aExecutor->PreloadFont(mUrlOrSizes, mCrossOrigin, mMedia, + mReferrerPolicyOrIntegrity); + break; + case eSpeculativeLoadFetch: + aExecutor->PreloadFetch(mUrlOrSizes, mCrossOrigin, mMedia, + mReferrerPolicyOrIntegrity); + break; + case eSpeculativeLoadMaybeComplainAboutCharset: { + MOZ_ASSERT(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity + .Length() == 2, + "Unexpected line number string"); + uint32_t high = + (uint32_t) + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity + .CharAt(0); + uint32_t low = + (uint32_t) + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity + .CharAt(1); + uint32_t line = (high << 16) | low; + aExecutor->MaybeComplainAboutCharset(mMsgId, mIsError, (int32_t)line); + } break; + default: + MOZ_ASSERT_UNREACHABLE("Bogus speculative load."); + break; + } +} diff --git a/parser/html/nsHtml5SpeculativeLoad.h b/parser/html/nsHtml5SpeculativeLoad.h new file mode 100644 index 0000000000..4b2f755857 --- /dev/null +++ b/parser/html/nsHtml5SpeculativeLoad.h @@ -0,0 +1,419 @@ +/* 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/. */ + +#ifndef nsHtml5SpeculativeLoad_h +#define nsHtml5SpeculativeLoad_h + +#include "nsString.h" +#include "nsContentUtils.h" +#include "nsHtml5DocumentMode.h" +#include "nsHtml5String.h" +#include "ReferrerInfo.h" + +class nsHtml5TreeOpExecutor; + +enum eHtml5SpeculativeLoad { + eSpeculativeLoadUninitialized, + eSpeculativeLoadBase, + eSpeculativeLoadCSP, + eSpeculativeLoadMetaReferrer, + eSpeculativeLoadImage, + eSpeculativeLoadOpenPicture, + eSpeculativeLoadEndPicture, + eSpeculativeLoadPictureSource, + eSpeculativeLoadScript, + eSpeculativeLoadScriptFromHead, + eSpeculativeLoadNoModuleScript, + eSpeculativeLoadNoModuleScriptFromHead, + eSpeculativeLoadStyle, + eSpeculativeLoadManifest, + eSpeculativeLoadSetDocumentCharset, + eSpeculativeLoadSetDocumentMode, + eSpeculativeLoadPreconnect, + eSpeculativeLoadFont, + eSpeculativeLoadFetch, + eSpeculativeLoadMaybeComplainAboutCharset +}; + +class nsHtml5SpeculativeLoad { + using Encoding = mozilla::Encoding; + template <typename T> + using NotNull = mozilla::NotNull<T>; + + public: + nsHtml5SpeculativeLoad(); + ~nsHtml5SpeculativeLoad(); + + inline void InitBase(nsHtml5String aUrl) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadBase; + aUrl.ToString(mUrlOrSizes); + } + + inline void InitMetaCSP(nsHtml5String aCSP) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadCSP; + nsString csp; // Not Auto, because using it to hold nsStringBuffer* + aCSP.ToString(csp); + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign( + nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp)); + } + + inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadMetaReferrer; + nsString + referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* + aReferrerPolicy.ToString(referrerPolicy); + mReferrerPolicyOrIntegrity.Assign( + nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( + referrerPolicy)); + } + + inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin, + nsHtml5String aMedia, nsHtml5String aReferrerPolicy, + nsHtml5String aSrcset, nsHtml5String aSizes, + bool aLinkPreload) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadImage; + aUrl.ToString(mUrlOrSizes); + aCrossOrigin.ToString(mCrossOrigin); + aMedia.ToString(mMedia); + nsString + referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* + aReferrerPolicy.ToString(referrerPolicy); + mReferrerPolicyOrIntegrity.Assign( + nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( + referrerPolicy)); + aSrcset.ToString(mCharsetOrSrcset); + aSizes.ToString( + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); + mIsLinkPreload = aLinkPreload; + mInitTimestamp = mozilla::TimeStamp::Now(); + } + + inline void InitFont(nsHtml5String aUrl, nsHtml5String aCrossOrigin, + nsHtml5String aMedia, nsHtml5String aReferrerPolicy) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadFont; + aUrl.ToString(mUrlOrSizes); + aCrossOrigin.ToString(mCrossOrigin); + aMedia.ToString(mMedia); + nsString + referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* + aReferrerPolicy.ToString(referrerPolicy); + mReferrerPolicyOrIntegrity.Assign( + nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( + referrerPolicy)); + // This can be only triggered by <link rel=preload type=font> + mIsLinkPreload = true; + } + + inline void InitFetch(nsHtml5String aUrl, nsHtml5String aCrossOrigin, + nsHtml5String aMedia, nsHtml5String aReferrerPolicy) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadFetch; + aUrl.ToString(mUrlOrSizes); + aCrossOrigin.ToString(mCrossOrigin); + aMedia.ToString(mMedia); + nsString + referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* + aReferrerPolicy.ToString(referrerPolicy); + mReferrerPolicyOrIntegrity.Assign( + nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( + referrerPolicy)); + + // This method can be only be triggered by <link rel=preload type=fetch>, + // hence this operation is always a preload. + mIsLinkPreload = true; + } + + // <picture> elements have multiple <source> nodes followed by an <img>, + // where we use the first valid source, which may be the img. Because we + // can't determine validity at this point without parsing CSS and getting + // main thread state, we push preload operations for picture pushed and + // popped, so that the target of the preload ops can determine what picture + // and nesting level each source/img from the main preloading code exists + // at. + inline void InitOpenPicture() { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadOpenPicture; + } + + inline void InitEndPicture() { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadEndPicture; + } + + inline void InitPictureSource(nsHtml5String aSrcset, nsHtml5String aSizes, + nsHtml5String aType, nsHtml5String aMedia) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadPictureSource; + aSrcset.ToString(mCharsetOrSrcset); + aSizes.ToString(mUrlOrSizes); + aType.ToString( + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); + aMedia.ToString(mMedia); + } + + inline void InitScript(nsHtml5String aUrl, nsHtml5String aCharset, + nsHtml5String aType, nsHtml5String aCrossOrigin, + nsHtml5String aMedia, nsHtml5String aIntegrity, + nsHtml5String aReferrerPolicy, bool aParserInHead, + bool aAsync, bool aDefer, bool aNoModule, + bool aLinkPreload) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + if (aNoModule) { + mOpCode = aParserInHead ? eSpeculativeLoadNoModuleScriptFromHead + : eSpeculativeLoadNoModuleScript; + } else { + mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead + : eSpeculativeLoadScript; + } + aUrl.ToString(mUrlOrSizes); + aCharset.ToString(mCharsetOrSrcset); + aType.ToString( + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); + aCrossOrigin.ToString(mCrossOrigin); + aMedia.ToString(mMedia); + aIntegrity.ToString(mReferrerPolicyOrIntegrity); + nsAutoString referrerPolicy; + aReferrerPolicy.ToString(referrerPolicy); + referrerPolicy = + nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( + referrerPolicy); + mScriptReferrerPolicy = + mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString( + referrerPolicy); + + mIsAsync = aAsync; + mIsDefer = aDefer; + mIsLinkPreload = aLinkPreload; + } + + inline void InitImportStyle(nsString&& aUrl) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadStyle; + mUrlOrSizes = std::move(aUrl); + mCharsetOrSrcset.SetIsVoid(true); + mCrossOrigin.SetIsVoid(true); + mMedia.SetIsVoid(true); + mReferrerPolicyOrIntegrity.SetIsVoid(true); + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.SetIsVoid( + true); + } + + inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset, + nsHtml5String aCrossOrigin, nsHtml5String aMedia, + nsHtml5String aReferrerPolicy, nsHtml5String aIntegrity, + bool aLinkPreload) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadStyle; + aUrl.ToString(mUrlOrSizes); + aCharset.ToString(mCharsetOrSrcset); + aCrossOrigin.ToString(mCrossOrigin); + aMedia.ToString(mMedia); + nsString + referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* + aReferrerPolicy.ToString(referrerPolicy); + mReferrerPolicyOrIntegrity.Assign( + nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( + referrerPolicy)); + aIntegrity.ToString( + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); + mIsLinkPreload = aLinkPreload; + } + + /** + * "Speculative" manifest loads aren't truly speculative--if a manifest + * gets loaded, we are committed to it. There can never be a <script> + * before the manifest, so the situation of having to undo a manifest due + * to document.write() never arises. The reason why a parser + * thread-discovered manifest gets loaded via the speculative load queue + * as opposed to tree operation queue is that the manifest must get + * processed before any actual speculative loads such as scripts. Thus, + * manifests seen by the parser thread have to maintain the queue order + * relative to true speculative loads. See bug 541079. + */ + inline void InitManifest(nsHtml5String aUrl) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadManifest; + aUrl.ToString(mUrlOrSizes); + } + + /** + * We communicate the encoding change via the speculative operation + * queue in order to act upon it as soon as possible and so as not to + * have speculative loads generated after an encoding change fail to + * make use of the encoding change. + */ + inline void InitSetDocumentCharset(NotNull<const Encoding*> aEncoding, + int32_t aCharsetSource, + bool aCommitEncodingSpeculation) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadSetDocumentCharset; + mCharsetOrSrcset.~nsString(); + mEncoding = aEncoding; + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign( + (char16_t)aCharsetSource); + mCommitEncodingSpeculation = aCommitEncodingSpeculation; + } + + inline void InitMaybeComplainAboutCharset(const char* aMsgId, bool aError, + int32_t aLineNumber) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadMaybeComplainAboutCharset; + mCharsetOrSrcset.~nsString(); + mMsgId = aMsgId; + mIsError = aError; + // Transport a 32-bit integer as two 16-bit code units of a string + // in order to avoid adding an integer field to the object. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1733043 for a better + // eventual approach. + char16_t high = (char16_t)(((uint32_t)aLineNumber) >> 16); + char16_t low = (char16_t)(((uint32_t)aLineNumber) & 0xFFFF); + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(high); + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Append(low); + } + + /** + * Speculative document mode setting isn't really speculative. Once it + * happens, we are committed to it. However, this information needs to + * travel in the speculation queue in order to have this information + * available before parsing the speculatively loaded style sheets. + */ + inline void InitSetDocumentMode(nsHtml5DocumentMode aMode) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadSetDocumentMode; + mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign( + (char16_t)aMode); + } + + inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) { + MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadPreconnect; + aUrl.ToString(mUrlOrSizes); + aCrossOrigin.ToString(mCrossOrigin); + } + + void Perform(nsHtml5TreeOpExecutor* aExecutor); + + private: + nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete; + nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete; + + eHtml5SpeculativeLoad mOpCode; + + /** + * Whether the refering element has async attribute. + */ + bool mIsAsync; + + /** + * Whether the refering element has defer attribute. + */ + bool mIsDefer; + + /** + * True if and only if this is a speculative load initiated by <link + * rel="preload"> or <link rel="modulepreload"> tag encounter. Passed to the + * handling loader as an indication to raise the priority. + */ + bool mIsLinkPreload; + + /** + * Whether the charset complaint is an error. + */ + bool mIsError; + + /** + * Whether setting document encoding involves also committing to an encoding + * speculation. + */ + bool mCommitEncodingSpeculation; + + /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the + * "sizes" attribute. If the attribute is not set, this will be a void + * string. Otherwise it empty or the value of the url. + */ + nsString mUrlOrSizes; + /** + * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the + * "integrity" attribute. If the attribute is not set, this will be a void + * string. Otherwise it is empty or the value of the referrer policy. + */ + nsString mReferrerPolicyOrIntegrity; + /** + * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead] + * then this is the value of the "charset" attribute. For + * eSpeculativeLoadSetDocumentCharset it is the charset that the + * document's charset is being set to. If mOpCode is eSpeculativeLoadImage + * or eSpeculativeLoadPictureSource, this is the value of the "srcset" + * attribute. If the attribute is not set, this will be a void string. + * Otherwise it's empty. + * For eSpeculativeLoadMaybeComplainAboutCharset mMsgId is used. + */ + union { + nsString mCharsetOrSrcset; + const Encoding* mEncoding; + const char* mMsgId; + }; + /** + * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a + * one-character string whose single character's code point is to be + * interpreted as a charset source integer. If mOpCode is + * eSpeculativeLoadSetDocumentMode, this is a one-character string whose + * single character's code point is to be interpreted as an + * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta + * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the + * value of the "sizes" attribute. If the attribute is not set, this will + * be a void string. If mOpCode is eSpeculativeLoadStyle, this + * is the value of the "integrity" attribute. If the attribute is not set, + * this will be a void string. Otherwise, it is empty or the value of the type + * attribute. + */ + nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity; + /** + * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead] + * or eSpeculativeLoadPreconnect or eSpeculativeLoadStyle this is the value of + * the "crossorigin" attribute. If the attribute is not set, this will be a + * void string. + */ + nsString mCrossOrigin; + /** + * If mOpCode is eSpeculativeLoadPictureSource or eSpeculativeLoadStyle or + * Fetch or Image or Media or Script this is the value of the relevant "media" + * attribute of the <link rel="preload"> or <link rel="stylesheet">. If the + * attribute is not set, or the preload didn't originate from a <link>, this + * will be a void string. + */ + nsString mMedia; + /** + * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value + * of the "referrerpolicy" attribute. This field holds one of the values + * (REFERRER_POLICY_*) defined in nsIHttpChannel. + */ + mozilla::dom::ReferrerPolicy mScriptReferrerPolicy; + + mozilla::TimeStamp mInitTimestamp; +}; + +#endif // nsHtml5SpeculativeLoad_h diff --git a/parser/html/nsHtml5StackNode.cpp b/parser/html/nsHtml5StackNode.cpp new file mode 100644 index 0000000000..34b5ab1b12 --- /dev/null +++ b/parser/html/nsHtml5StackNode.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2007-2011 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit StackNode.java instead and regenerate. + */ + +#define nsHtml5StackNode_cpp__ + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +#include "nsHtml5AttributeName.h" +#include "nsHtml5ElementName.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5Portability.h" + +#include "nsHtml5StackNode.h" + +int32_t nsHtml5StackNode::getGroup() { + return flags & nsHtml5ElementName::GROUP_MASK; +} + +bool nsHtml5StackNode::isScoping() { + return (flags & nsHtml5ElementName::SCOPING); +} + +bool nsHtml5StackNode::isSpecial() { + return (flags & nsHtml5ElementName::SPECIAL); +} + +bool nsHtml5StackNode::isFosterParenting() { + return (flags & nsHtml5ElementName::FOSTER_PARENTING); +} + +bool nsHtml5StackNode::isHtmlIntegrationPoint() { + return (flags & nsHtml5ElementName::HTML_INTEGRATION_POINT); +} + +nsHtml5StackNode::nsHtml5StackNode(int32_t idxInTreeBuilder) + : idxInTreeBuilder(idxInTreeBuilder), + flags(0), + name(nullptr), + popName(nullptr), + ns(0), + node(nullptr), + attributes(nullptr), + refcount(0), + htmlCreator(nullptr) { + MOZ_COUNT_CTOR(nsHtml5StackNode); +} + +mozilla::dom::HTMLContentCreatorFunction nsHtml5StackNode::getHtmlCreator() { + return htmlCreator; +} + +void nsHtml5StackNode::setValues( + int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node, + nsAtom* popName, nsHtml5HtmlAttributes* attributes, + mozilla::dom::HTMLContentCreatorFunction htmlCreator) { + MOZ_ASSERT(isUnused()); + this->flags = flags; + this->name = name; + this->popName = popName; + this->ns = ns; + this->node = node; + this->attributes = attributes; + this->refcount = 1; + this->htmlCreator = htmlCreator; +} + +void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName, + nsIContentHandle* node) { + MOZ_ASSERT(isUnused()); + this->flags = elementName->getFlags(); + this->name = elementName->getName(); + this->popName = elementName->getName(); + this->ns = kNameSpaceID_XHTML; + this->node = node; + this->attributes = nullptr; + this->refcount = 1; + MOZ_ASSERT(elementName->isInterned(), + "Don't use this constructor for custom elements."); + this->htmlCreator = nullptr; +} + +void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName, + nsIContentHandle* node, + nsHtml5HtmlAttributes* attributes) { + MOZ_ASSERT(isUnused()); + this->flags = elementName->getFlags(); + this->name = elementName->getName(); + this->popName = elementName->getName(); + this->ns = kNameSpaceID_XHTML; + this->node = node; + this->attributes = attributes; + this->refcount = 1; + MOZ_ASSERT(elementName->isInterned(), + "Don't use this constructor for custom elements."); + this->htmlCreator = elementName->getHtmlCreator(); +} + +void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName, + nsIContentHandle* node, nsAtom* popName) { + MOZ_ASSERT(isUnused()); + this->flags = elementName->getFlags(); + this->name = elementName->getName(); + this->popName = popName; + this->ns = kNameSpaceID_XHTML; + this->node = node; + this->attributes = nullptr; + this->refcount = 1; + this->htmlCreator = nullptr; +} + +void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName, + nsAtom* popName, nsIContentHandle* node) { + MOZ_ASSERT(isUnused()); + this->flags = prepareSvgFlags(elementName->getFlags()); + this->name = elementName->getName(); + this->popName = popName; + this->ns = kNameSpaceID_SVG; + this->node = node; + this->attributes = nullptr; + this->refcount = 1; + this->htmlCreator = nullptr; +} + +void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName, + nsIContentHandle* node, nsAtom* popName, + bool markAsIntegrationPoint) { + MOZ_ASSERT(isUnused()); + this->flags = + prepareMathFlags(elementName->getFlags(), markAsIntegrationPoint); + this->name = elementName->getName(); + this->popName = popName; + this->ns = kNameSpaceID_MathML; + this->node = node; + this->attributes = nullptr; + this->refcount = 1; + this->htmlCreator = nullptr; +} + +int32_t nsHtml5StackNode::prepareSvgFlags(int32_t flags) { + flags &= + ~(nsHtml5ElementName::FOSTER_PARENTING | nsHtml5ElementName::SCOPING | + nsHtml5ElementName::SPECIAL | nsHtml5ElementName::OPTIONAL_END_TAG); + if ((flags & nsHtml5ElementName::SCOPING_AS_SVG)) { + flags |= (nsHtml5ElementName::SCOPING | nsHtml5ElementName::SPECIAL | + nsHtml5ElementName::HTML_INTEGRATION_POINT); + } + return flags; +} + +int32_t nsHtml5StackNode::prepareMathFlags(int32_t flags, + bool markAsIntegrationPoint) { + flags &= + ~(nsHtml5ElementName::FOSTER_PARENTING | nsHtml5ElementName::SCOPING | + nsHtml5ElementName::SPECIAL | nsHtml5ElementName::OPTIONAL_END_TAG); + if ((flags & nsHtml5ElementName::SCOPING_AS_MATHML)) { + flags |= (nsHtml5ElementName::SCOPING | nsHtml5ElementName::SPECIAL); + } + if (markAsIntegrationPoint) { + flags |= nsHtml5ElementName::HTML_INTEGRATION_POINT; + } + return flags; +} + +nsHtml5StackNode::~nsHtml5StackNode() { MOZ_COUNT_DTOR(nsHtml5StackNode); } + +void nsHtml5StackNode::dropAttributes() { attributes = nullptr; } + +void nsHtml5StackNode::retain() { refcount++; } + +void nsHtml5StackNode::release(nsHtml5TreeBuilder* owningTreeBuilder) { + refcount--; + MOZ_ASSERT(refcount >= 0); + if (!refcount) { + delete attributes; + if (idxInTreeBuilder >= 0) { + owningTreeBuilder->notifyUnusedStackNode(idxInTreeBuilder); + } else { + MOZ_ASSERT(!owningTreeBuilder); + delete this; + } + } +} + +bool nsHtml5StackNode::isUnused() { return !refcount; } + +void nsHtml5StackNode::initializeStatics() {} + +void nsHtml5StackNode::releaseStatics() {} diff --git a/parser/html/nsHtml5StackNode.h b/parser/html/nsHtml5StackNode.h new file mode 100644 index 0000000000..b73dc57a69 --- /dev/null +++ b/parser/html/nsHtml5StackNode.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2007-2011 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit StackNode.java instead and regenerate. + */ + +#ifndef nsHtml5StackNode_h +#define nsHtml5StackNode_h + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5HtmlAttributes.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +class nsHtml5StreamParser; + +class nsHtml5AttributeName; +class nsHtml5ElementName; +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5UTF16Buffer; +class nsHtml5StateSnapshot; +class nsHtml5Portability; + +class nsHtml5StackNode { + public: + int32_t idxInTreeBuilder; + int32_t flags; + RefPtr<nsAtom> name; + RefPtr<nsAtom> popName; + int32_t ns; + nsIContentHandle* node; + nsHtml5HtmlAttributes* attributes; + + private: + int32_t refcount; + mozilla::dom::HTMLContentCreatorFunction htmlCreator; + + public: + inline int32_t getFlags() { return flags; } + + int32_t getGroup(); + bool isScoping(); + bool isSpecial(); + bool isFosterParenting(); + bool isHtmlIntegrationPoint(); + explicit nsHtml5StackNode(int32_t idxInTreeBuilder); + mozilla::dom::HTMLContentCreatorFunction getHtmlCreator(); + void setValues(int32_t flags, int32_t ns, nsAtom* name, + nsIContentHandle* node, nsAtom* popName, + nsHtml5HtmlAttributes* attributes, + mozilla::dom::HTMLContentCreatorFunction htmlCreator); + void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node); + void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node, + nsHtml5HtmlAttributes* attributes); + void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node, + nsAtom* popName); + void setValues(nsHtml5ElementName* elementName, nsAtom* popName, + nsIContentHandle* node); + void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node, + nsAtom* popName, bool markAsIntegrationPoint); + + private: + static int32_t prepareSvgFlags(int32_t flags); + static int32_t prepareMathFlags(int32_t flags, bool markAsIntegrationPoint); + + public: + ~nsHtml5StackNode(); + void dropAttributes(); + void retain(); + void release(nsHtml5TreeBuilder* owningTreeBuilder); + bool isUnused(); + static void initializeStatics(); + static void releaseStatics(); +}; + +#endif diff --git a/parser/html/nsHtml5StateSnapshot.cpp b/parser/html/nsHtml5StateSnapshot.cpp new file mode 100644 index 0000000000..2a38e0c7d0 --- /dev/null +++ b/parser/html/nsHtml5StateSnapshot.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit StateSnapshot.java instead and regenerate. + */ + +#define nsHtml5StateSnapshot_cpp__ + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +#include "nsHtml5AttributeName.h" +#include "nsHtml5ElementName.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsHtml5Portability.h" + +#include "nsHtml5StateSnapshot.h" + +nsHtml5StateSnapshot::nsHtml5StateSnapshot( + jArray<nsHtml5StackNode*, int32_t> stack, + jArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements, + jArray<int32_t, int32_t> templateModeStack, nsIContentHandle* formPointer, + nsIContentHandle* headPointer, int32_t mode, int32_t originalMode, + bool framesetOk, bool needToDropLF, bool quirks) + : stack(stack), + listOfActiveFormattingElements(listOfActiveFormattingElements), + templateModeStack(templateModeStack), + formPointer(formPointer), + headPointer(headPointer), + mode(mode), + originalMode(originalMode), + framesetOk(framesetOk), + needToDropLF(needToDropLF), + quirks(quirks) { + MOZ_COUNT_CTOR(nsHtml5StateSnapshot); +} + +jArray<nsHtml5StackNode*, int32_t> nsHtml5StateSnapshot::getStack() { + return stack; +} + +jArray<int32_t, int32_t> nsHtml5StateSnapshot::getTemplateModeStack() { + return templateModeStack; +} + +jArray<nsHtml5StackNode*, int32_t> +nsHtml5StateSnapshot::getListOfActiveFormattingElements() { + return listOfActiveFormattingElements; +} + +nsIContentHandle* nsHtml5StateSnapshot::getFormPointer() { return formPointer; } + +nsIContentHandle* nsHtml5StateSnapshot::getHeadPointer() { return headPointer; } + +int32_t nsHtml5StateSnapshot::getMode() { return mode; } + +int32_t nsHtml5StateSnapshot::getOriginalMode() { return originalMode; } + +bool nsHtml5StateSnapshot::isFramesetOk() { return framesetOk; } + +bool nsHtml5StateSnapshot::isNeedToDropLF() { return needToDropLF; } + +bool nsHtml5StateSnapshot::isQuirks() { return quirks; } + +int32_t nsHtml5StateSnapshot::getListOfActiveFormattingElementsLength() { + return listOfActiveFormattingElements.length; +} + +int32_t nsHtml5StateSnapshot::getStackLength() { return stack.length; } + +int32_t nsHtml5StateSnapshot::getTemplateModeStackLength() { + return templateModeStack.length; +} + +nsHtml5StateSnapshot::~nsHtml5StateSnapshot() { + MOZ_COUNT_DTOR(nsHtml5StateSnapshot); + for (int32_t i = 0; i < stack.length; i++) { + stack[i]->release(nullptr); + } + for (int32_t i = 0; i < listOfActiveFormattingElements.length; i++) { + if (listOfActiveFormattingElements[i]) { + listOfActiveFormattingElements[i]->release(nullptr); + } + } +} + +void nsHtml5StateSnapshot::initializeStatics() {} + +void nsHtml5StateSnapshot::releaseStatics() {} diff --git a/parser/html/nsHtml5StateSnapshot.h b/parser/html/nsHtml5StateSnapshot.h new file mode 100644 index 0000000000..b5c80bf346 --- /dev/null +++ b/parser/html/nsHtml5StateSnapshot.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit StateSnapshot.java instead and regenerate. + */ + +#ifndef nsHtml5StateSnapshot_h +#define nsHtml5StateSnapshot_h + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +class nsHtml5StreamParser; + +class nsHtml5AttributeName; +class nsHtml5ElementName; +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5UTF16Buffer; +class nsHtml5Portability; + +class nsHtml5StateSnapshot : public nsAHtml5TreeBuilderState { + private: + autoJArray<nsHtml5StackNode*, int32_t> stack; + autoJArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements; + autoJArray<int32_t, int32_t> templateModeStack; + nsIContentHandle* formPointer; + nsIContentHandle* headPointer; + int32_t mode; + int32_t originalMode; + bool framesetOk; + bool needToDropLF; + bool quirks; + + public: + nsHtml5StateSnapshot( + jArray<nsHtml5StackNode*, int32_t> stack, + jArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements, + jArray<int32_t, int32_t> templateModeStack, nsIContentHandle* formPointer, + nsIContentHandle* headPointer, int32_t mode, int32_t originalMode, + bool framesetOk, bool needToDropLF, bool quirks); + jArray<nsHtml5StackNode*, int32_t> getStack() override; + jArray<int32_t, int32_t> getTemplateModeStack() override; + jArray<nsHtml5StackNode*, int32_t> getListOfActiveFormattingElements() + override; + nsIContentHandle* getFormPointer() override; + nsIContentHandle* getHeadPointer() override; + int32_t getMode() override; + int32_t getOriginalMode() override; + bool isFramesetOk() override; + bool isNeedToDropLF() override; + bool isQuirks() override; + int32_t getListOfActiveFormattingElementsLength() override; + int32_t getStackLength() override; + int32_t getTemplateModeStackLength() override; + ~nsHtml5StateSnapshot(); + static void initializeStatics(); + static void releaseStatics(); +}; + +#endif diff --git a/parser/html/nsHtml5StreamListener.cpp b/parser/html/nsHtml5StreamListener.cpp new file mode 100644 index 0000000000..86e18c0296 --- /dev/null +++ b/parser/html/nsHtml5StreamListener.cpp @@ -0,0 +1,92 @@ +/* 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/. */ + +#include "nsHtml5StreamListener.h" + +#include "nsHtml5StreamParserReleaser.h" + +NS_IMPL_ADDREF(nsHtml5StreamListener) +NS_IMPL_RELEASE(nsHtml5StreamListener) + +NS_INTERFACE_MAP_BEGIN(nsHtml5StreamListener) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver) + NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) + NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener) +NS_INTERFACE_MAP_END + +nsHtml5StreamListener::nsHtml5StreamListener(nsHtml5StreamParser* aDelegate) + : mDelegateMonitor("nsHtml5StreamListener mDelegateMonitor"), + mDelegate(aDelegate) { + MOZ_ASSERT(aDelegate, "Must have delegate"); + aDelegate->AddRef(); +} + +nsHtml5StreamListener::~nsHtml5StreamListener() { DropDelegateImpl(); } + +void nsHtml5StreamListener::DropDelegate() { + MOZ_ASSERT(NS_IsMainThread(), + "Must not call DropDelegate from non-main threads."); + DropDelegateImpl(); +} + +void nsHtml5StreamListener::DropDelegateImpl() { + mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor); + if (mDelegate) { + nsCOMPtr<nsIRunnable> releaser = new nsHtml5StreamParserReleaser(mDelegate); + if (NS_FAILED(((nsHtml5StreamParser*)mDelegate) + ->DispatchToMain(releaser.forget()))) { + NS_WARNING("Failed to dispatch releaser event."); + } + mDelegate = nullptr; + } +} + +nsHtml5StreamParser* nsHtml5StreamListener::GetDelegate() { + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + // Since this can be called only on the main + // thread and DropDelegate() can only be called on the main thread + // it's OK that the monitor here doesn't protect the use of the + // return value. + return mDelegate; +} + +NS_IMETHODIMP +nsHtml5StreamListener::CheckListenerChain() { + if (MOZ_UNLIKELY(!mDelegate)) { + return NS_ERROR_NOT_AVAILABLE; + } + return NS_OK; +} + +NS_IMETHODIMP +nsHtml5StreamListener::OnStartRequest(nsIRequest* aRequest) { + mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor); + if (MOZ_UNLIKELY(!mDelegate)) { + return NS_ERROR_NOT_AVAILABLE; + } + return ((nsHtml5StreamParser*)mDelegate)->OnStartRequest(aRequest); +} + +NS_IMETHODIMP +nsHtml5StreamListener::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) { + mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor); + if (MOZ_UNLIKELY(!mDelegate)) { + return NS_ERROR_NOT_AVAILABLE; + } + return ((nsHtml5StreamParser*)mDelegate)->OnStopRequest(aRequest, aStatus); +} + +NS_IMETHODIMP +nsHtml5StreamListener::OnDataAvailable(nsIRequest* aRequest, + nsIInputStream* aInStream, + uint64_t aSourceOffset, + uint32_t aLength) { + mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor); + if (MOZ_UNLIKELY(!mDelegate)) { + return NS_ERROR_NOT_AVAILABLE; + } + return ((nsHtml5StreamParser*)mDelegate) + ->OnDataAvailable(aRequest, aInStream, aSourceOffset, aLength); +} diff --git a/parser/html/nsHtml5StreamListener.h b/parser/html/nsHtml5StreamListener.h new file mode 100644 index 0000000000..46056eacee --- /dev/null +++ b/parser/html/nsHtml5StreamListener.h @@ -0,0 +1,62 @@ +/* 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/. */ + +#ifndef nsHtml5StreamListener_h +#define nsHtml5StreamListener_h + +#include "nsIStreamListener.h" +#include "nsIThreadRetargetableStreamListener.h" +#include "nsHtml5StreamParser.h" +#include "mozilla/ReentrantMonitor.h" + +/** + * The purpose of this class is to reconcile the problem that + * nsHtml5StreamParser is a cycle collection participant, which means that it + * can only be refcounted on the main thread, but + * nsIThreadRetargetableStreamListener can be refcounted from another thread, + * so nsHtml5StreamParser being an nsIThreadRetargetableStreamListener was + * a memory corruption problem. + * + * mDelegate is an nsHtml5StreamParserPtr, which releases the object that it + * points to from a runnable on the main thread. DropDelegate() is only called + * on the main thread. This call will finish before the main-thread derefs the + * nsHtml5StreamListener itself, so there is no risk of another thread making + * the refcount of nsHtml5StreamListener go to zero and running the destructor + * concurrently. Other than that, the thread-safe nsISupports implementation + * takes care of the destructor not running concurrently from different + * threads, so there is no need to have a mutex around nsHtml5StreamParserPtr to + * prevent it from double-releasing nsHtml5StreamParser. + */ +class nsHtml5StreamListener : public nsIStreamListener, + public nsIThreadRetargetableStreamListener { + public: + explicit nsHtml5StreamListener(nsHtml5StreamParser* aDelegate); + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER + + // Main-thread-only + nsHtml5StreamParser* GetDelegate(); + + // Main-thread-only + void DropDelegate(); + + private: + void DropDelegateImpl(); + virtual ~nsHtml5StreamListener(); + + // ReentrantMonitor instead of Mutex, because `GetDelegate()` + // can be called from within the Necko callbacks when Necko events + // are delivered on the main thread. + mozilla::ReentrantMonitor mDelegateMonitor MOZ_UNANNOTATED; + // Owning pointer with manually-managed refcounting, protected by + // mDelegateMonitor. Access to it is Atomic, which avoids getting a lock + // to check if it's set or to return the pointer. Access to the data within + // it needs the monitor. MOZ_PT_GUARDED_BY() can't be used with Atomic<...*> + mozilla::Atomic<nsHtml5StreamParser*, mozilla::ReleaseAcquire> mDelegate; +}; + +#endif // nsHtml5StreamListener_h diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp new file mode 100644 index 0000000000..8f53b37057 --- /dev/null +++ b/parser/html/nsHtml5StreamParser.cpp @@ -0,0 +1,2865 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=2 et tw=80: */ +/* 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/. */ + +#include "nsHtml5StreamParser.h" + +#include <stdlib.h> +#include <string.h> +#include <algorithm> +#include <new> +#include <type_traits> +#include <utility> +#include "ErrorList.h" +#include "GeckoProfiler.h" +#include "js/GCAPI.h" +#include "mozilla/ArrayIterator.h" +#include "mozilla/Buffer.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/Encoding.h" +#include "mozilla/EncodingDetector.h" +#include "mozilla/Likely.h" +#include "mozilla/Maybe.h" +#include "mozilla/SchedulerGroup.h" +#include "mozilla/ScopeExit.h" +#include "mozilla/Services.h" +#include "mozilla/StaticPrefs_html5.h" +#include "mozilla/StaticPrefs_intl.h" +#include "mozilla/TaskCategory.h" +#include "mozilla/TextUtils.h" + +#include "mozilla/UniquePtrExtensions.h" +#include "mozilla/Unused.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/DebuggerUtilsBinding.h" +#include "mozilla/dom/DocGroup.h" +#include "mozilla/dom/Document.h" +#include "mozilla/mozalloc.h" +#include "mozilla/Vector.h" +#include "nsContentSink.h" +#include "nsContentUtils.h" +#include "nsCycleCollectionTraversalCallback.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Highlighter.h" +#include "nsHtml5Module.h" +#include "nsHtml5OwningUTF16Buffer.h" +#include "nsHtml5Parser.h" +#include "nsHtml5Speculation.h" +#include "nsHtml5StreamParserPtr.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5TreeOpExecutor.h" +#include "nsHtml5TreeOpStage.h" +#include "nsIChannel.h" +#include "nsIContentSink.h" +#include "nsID.h" +#include "nsIDTD.h" +#include "nsIDocShell.h" +#include "nsIEventTarget.h" +#include "nsIHttpChannel.h" +#include "nsIInputStream.h" +#include "nsINestedURI.h" +#include "nsIObserverService.h" +#include "nsIRequest.h" +#include "nsIRunnable.h" +#include "nsIScriptError.h" +#include "nsIThread.h" +#include "nsIThreadRetargetableRequest.h" +#include "nsIThreadRetargetableStreamListener.h" +#include "nsITimer.h" +#include "nsIURI.h" +#include "nsJSEnvironment.h" +#include "nsLiteralString.h" +#include "nsNetUtil.h" +#include "nsString.h" +#include "nsTPromiseFlatString.h" +#include "nsThreadUtils.h" +#include "nsXULAppAPI.h" + +extern "C" { +// Defined in intl/encoding_glue/src/lib.rs +const mozilla::Encoding* xmldecl_parse(const uint8_t* buf, size_t buf_len); +}; + +using namespace mozilla; +using namespace mozilla::dom; + +/* + * Note that nsHtml5StreamParser implements cycle collecting AddRef and + * Release. Therefore, nsHtml5StreamParser must never be refcounted from + * the parser thread! + * + * To work around this limitation, runnables posted by the main thread to the + * parser thread hold their reference to the stream parser in an + * nsHtml5StreamParserPtr. Upon creation, nsHtml5StreamParserPtr addrefs the + * object it holds + * just like a regular nsRefPtr. This is OK, since the creation of the + * runnable and the nsHtml5StreamParserPtr happens on the main thread. + * + * When the runnable is done on the parser thread, the destructor of + * nsHtml5StreamParserPtr runs there. It doesn't call Release on the held object + * directly. Instead, it posts another runnable back to the main thread where + * that runnable calls Release on the wrapped object. + * + * When posting runnables in the other direction, the runnables have to be + * created on the main thread when nsHtml5StreamParser is instantiated and + * held for the lifetime of the nsHtml5StreamParser. This works, because the + * same runnabled can be dispatched multiple times and currently runnables + * posted from the parser thread to main thread don't need to wrap any + * runnable-specific data. (In the other direction, the runnables most notably + * wrap the byte data of the stream.) + */ +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5StreamParser) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5StreamParser) + +NS_INTERFACE_TABLE_HEAD(nsHtml5StreamParser) + NS_INTERFACE_TABLE(nsHtml5StreamParser, nsISupports) + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHtml5StreamParser) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5StreamParser) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5StreamParser) + tmp->DropTimer(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner) + tmp->mExecutorFlusher = nullptr; + tmp->mLoadFlusher = nullptr; + tmp->mExecutor = nullptr; +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5StreamParser) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) + // hack: count the strongly owned edge wrapped in the runnable + if (tmp->mExecutorFlusher) { + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExecutorFlusher->mExecutor"); + cb.NoteXPCOMChild(static_cast<nsIContentSink*>(tmp->mExecutor)); + } + // hack: count the strongly owned edge wrapped in the runnable + if (tmp->mLoadFlusher) { + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mLoadFlusher->mExecutor"); + cb.NoteXPCOMChild(static_cast<nsIContentSink*>(tmp->mExecutor)); + } +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +class nsHtml5ExecutorFlusher : public Runnable { + private: + RefPtr<nsHtml5TreeOpExecutor> mExecutor; + + public: + explicit nsHtml5ExecutorFlusher(nsHtml5TreeOpExecutor* aExecutor) + : Runnable("nsHtml5ExecutorFlusher"), mExecutor(aExecutor) {} + NS_IMETHOD Run() override { + if (!mExecutor->isInList()) { + Document* doc = mExecutor->GetDocument(); + if (XRE_IsContentProcess() && + nsContentUtils:: + HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint( + doc)) { + // Possible early paint pending, reuse the runnable and try to + // call RunFlushLoop later. + nsCOMPtr<nsIRunnable> flusher = this; + if (NS_SUCCEEDED( + doc->Dispatch(TaskCategory::Network, flusher.forget()))) { + PROFILER_MARKER_UNTYPED("HighPrio blocking parser flushing(1)", DOM); + return NS_OK; + } + } + mExecutor->RunFlushLoop(); + } + return NS_OK; + } +}; + +class nsHtml5LoadFlusher : public Runnable { + private: + RefPtr<nsHtml5TreeOpExecutor> mExecutor; + + public: + explicit nsHtml5LoadFlusher(nsHtml5TreeOpExecutor* aExecutor) + : Runnable("nsHtml5LoadFlusher"), mExecutor(aExecutor) {} + NS_IMETHOD Run() override { + mExecutor->FlushSpeculativeLoads(); + return NS_OK; + } +}; + +nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor, + nsHtml5Parser* aOwner, + eParserMode aMode) + : mBomState(eBomState::BOM_SNIFFING_NOT_STARTED), + mCharsetSource(kCharsetUninitialized), + mEncodingSwitchSource(kCharsetUninitialized), + mEncoding(X_USER_DEFINED_ENCODING), // Obviously bogus value to notice if + // not updated + mNeedsEncodingSwitchTo(nullptr), + mSeenEligibleMetaCharset(false), + mChardetEof(false), +#ifdef DEBUG + mStartedFeedingDetector(false), + mStartedFeedingDevTools(false), +#endif + mReparseForbidden(false), + mForceAutoDetection(false), + mChannelHadCharset(false), + mLookingForMetaCharset(false), + mStartsWithLtQuestion(false), + mLookingForXmlDeclarationForXmlViewSource(false), + mTemplatePushedOrHeadPopped(false), + mGtBuffer(nullptr), + mGtPos(0), + mLastBuffer(nullptr), // Will be filled when starting + mExecutor(aExecutor), + mTreeBuilder(new nsHtml5TreeBuilder( + (aMode == VIEW_SOURCE_HTML || aMode == VIEW_SOURCE_XML) + ? nullptr + : mExecutor->GetStage(), + mExecutor->GetStage(), aMode == NORMAL)), + mTokenizer( + new nsHtml5Tokenizer(mTreeBuilder.get(), aMode == VIEW_SOURCE_XML)), + mTokenizerMutex("nsHtml5StreamParser mTokenizerMutex"), + mOwner(aOwner), + mLastWasCR(false), + mStreamState(eHtml5StreamState::STREAM_NOT_STARTED), + mSpeculating(false), + mAtEOF(false), + mSpeculationMutex("nsHtml5StreamParser mSpeculationMutex"), + mSpeculationFailureCount(0), + mNumBytesBuffered(0), + mTerminated(false), + mInterrupted(false), + mEventTarget(nsHtml5Module::GetStreamParserEventTarget()), + mExecutorFlusher(new nsHtml5ExecutorFlusher(aExecutor)), + mLoadFlusher(new nsHtml5LoadFlusher(aExecutor)), + mInitialEncodingWasFromParentFrame(false), + mHasHadErrors(false), + mDetectorHasSeenNonAscii(false), + mDecodingLocalFileWithoutTokenizing(false), + mBufferingBytes(false), + mFlushTimer(NS_NewTimer(mEventTarget)), + mFlushTimerMutex("nsHtml5StreamParser mFlushTimerMutex"), + mFlushTimerArmed(false), + mFlushTimerEverFired(false), + mMode(aMode) { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); +#ifdef DEBUG + mAtomTable.SetPermittedLookupEventTarget(mEventTarget); +#endif + mTokenizer->setInterner(&mAtomTable); + mTokenizer->setEncodingDeclarationHandler(this); + + if (aMode == VIEW_SOURCE_HTML || aMode == VIEW_SOURCE_XML) { + nsHtml5Highlighter* highlighter = + new nsHtml5Highlighter(mExecutor->GetStage()); + mTokenizer->EnableViewSource(highlighter); // takes ownership + mTreeBuilder->EnableViewSource(highlighter); // doesn't own + } + + // There's a zeroing operator new for everything else +} + +nsHtml5StreamParser::~nsHtml5StreamParser() { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + mTokenizer->end(); +#ifdef DEBUG + { + mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex); + MOZ_ASSERT(!mFlushTimer, "Flush timer was not dropped before dtor!"); + } + mRequest = nullptr; + mUnicodeDecoder = nullptr; + mFirstBuffer = nullptr; + mExecutor = nullptr; + mTreeBuilder = nullptr; + mTokenizer = nullptr; + mOwner = nullptr; +#endif +} + +nsresult nsHtml5StreamParser::GetChannel(nsIChannel** aChannel) { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + return mRequest ? CallQueryInterface(mRequest, aChannel) + : NS_ERROR_NOT_AVAILABLE; +} + +std::tuple<NotNull<const Encoding*>, nsCharsetSource> +nsHtml5StreamParser::GuessEncoding(bool aInitial) { + MOZ_ASSERT( + mCharsetSource != kCharsetFromFinalUserForcedAutoDetection && + mCharsetSource != + kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && + mCharsetSource != + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic && + mCharsetSource != + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII && + mCharsetSource != + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content && + mCharsetSource != + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII && + mCharsetSource != + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD && + mCharsetSource != + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII && + mCharsetSource != kCharsetFromFinalAutoDetectionFile); + auto ifHadBeenForced = mDetector->Guess(EmptyCString(), true); + auto encoding = + mForceAutoDetection + ? ifHadBeenForced + : mDetector->Guess(mTLD, mDecodingLocalFileWithoutTokenizing); + nsCharsetSource source = + aInitial + ? (mForceAutoDetection + ? kCharsetFromInitialUserForcedAutoDetection + : (mDecodingLocalFileWithoutTokenizing + ? kCharsetFromFinalAutoDetectionFile + : kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic)) + : (mForceAutoDetection + ? kCharsetFromFinalUserForcedAutoDetection + : (mDecodingLocalFileWithoutTokenizing + ? kCharsetFromFinalAutoDetectionFile + : kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic)); + if (source == kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic) { + if (encoding == ISO_2022_JP_ENCODING) { + if (EncodingDetector::TldMayAffectGuess(mTLD)) { + source = kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content; + } + } else if (!mDetectorHasSeenNonAscii) { + source = kCharsetFromInitialAutoDetectionASCII; // deliberately Initial + } else if (ifHadBeenForced == UTF_8_ENCODING) { + MOZ_ASSERT(mCharsetSource == kCharsetFromInitialAutoDetectionASCII || + mCharsetSource == + kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8 || + mEncoding == ISO_2022_JP_ENCODING); + source = kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII; + } else if (encoding != ifHadBeenForced) { + if (mCharsetSource == kCharsetFromInitialAutoDetectionASCII) { + source = + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII; + } else { + source = + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD; + } + } else if (EncodingDetector::TldMayAffectGuess(mTLD)) { + if (mCharsetSource == kCharsetFromInitialAutoDetectionASCII) { + source = + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII; + } else { + source = kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content; + } + } else if (mCharsetSource == kCharsetFromInitialAutoDetectionASCII) { + source = + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII; + } + } else if (source == + kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic) { + if (encoding == ISO_2022_JP_ENCODING) { + if (EncodingDetector::TldMayAffectGuess(mTLD)) { + source = kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content; + } + } else if (!mDetectorHasSeenNonAscii) { + source = kCharsetFromInitialAutoDetectionASCII; + } else if (ifHadBeenForced == UTF_8_ENCODING) { + source = kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8; + } else if (encoding != ifHadBeenForced) { + source = + kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD; + } else if (EncodingDetector::TldMayAffectGuess(mTLD)) { + source = kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content; + } + } + return {encoding, source}; +} + +void nsHtml5StreamParser::FeedDetector(Span<const uint8_t> aBuffer) { +#ifdef DEBUG + mStartedFeedingDetector = true; +#endif + MOZ_ASSERT(!mChardetEof); + mDetectorHasSeenNonAscii = mDetector->Feed(aBuffer, false); +} + +void nsHtml5StreamParser::DetectorEof() { +#ifdef DEBUG + mStartedFeedingDetector = true; +#endif + if (mChardetEof) { + return; + } + mChardetEof = true; + mDetectorHasSeenNonAscii = mDetector->Feed(Span<const uint8_t>(), true); +} + +void nsHtml5StreamParser::SetViewSourceTitle(nsIURI* aURL) { + MOZ_ASSERT(NS_IsMainThread()); + + BrowsingContext* browsingContext = + mExecutor->GetDocument()->GetBrowsingContext(); + if (browsingContext && browsingContext->WatchedByDevTools()) { + mURIToSendToDevtools = aURL; + + nsID uuid; + nsresult rv = nsID::GenerateUUIDInPlace(uuid); + if (!NS_FAILED(rv)) { + char buffer[NSID_LENGTH]; + uuid.ToProvidedString(buffer); + mUUIDForDevtools = NS_ConvertASCIItoUTF16(buffer); + } + } + + if (aURL) { + nsCOMPtr<nsIURI> temp; + if (aURL->SchemeIs("view-source")) { + nsCOMPtr<nsINestedURI> nested = do_QueryInterface(aURL); + nested->GetInnerURI(getter_AddRefs(temp)); + } else { + temp = aURL; + } + if (temp->SchemeIs("data")) { + // Avoid showing potentially huge data: URLs. The three last bytes are + // UTF-8 for an ellipsis. + mViewSourceTitle.AssignLiteral("data:\xE2\x80\xA6"); + } else { + nsresult rv = temp->GetSpec(mViewSourceTitle); + if (NS_FAILED(rv)) { + mViewSourceTitle.AssignLiteral("\xE2\x80\xA6"); + } + } + } +} + +nsresult +nsHtml5StreamParser::SetupDecodingAndWriteSniffingBufferAndCurrentSegment( + Span<const uint8_t> aPrefix, Span<const uint8_t> aFromSegment) { + NS_ASSERTION(IsParserThread(), "Wrong thread!"); + mUnicodeDecoder = mEncoding->NewDecoderWithBOMRemoval(); + nsresult rv = WriteStreamBytes(aPrefix); + NS_ENSURE_SUCCESS(rv, rv); + return WriteStreamBytes(aFromSegment); +} + +void nsHtml5StreamParser::SetupDecodingFromBom( + NotNull<const Encoding*> aEncoding) { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mEncoding = aEncoding; + mDecodingLocalFileWithoutTokenizing = false; + mLookingForMetaCharset = false; + mBufferingBytes = false; + mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling(); + mCharsetSource = kCharsetFromByteOrderMark; + mForceAutoDetection = false; + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false); + mBomState = BOM_SNIFFING_OVER; + if (mMode == VIEW_SOURCE_HTML) { + mTokenizer->StartViewSourceCharacters(); + } +} + +void nsHtml5StreamParser::SetupDecodingFromUtf16BogoXml( + NotNull<const Encoding*> aEncoding) { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mEncoding = aEncoding; + mDecodingLocalFileWithoutTokenizing = false; + mLookingForMetaCharset = false; + mBufferingBytes = false; + mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling(); + mCharsetSource = kCharsetFromXmlDeclarationUtf16; + mForceAutoDetection = false; + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false); + mBomState = BOM_SNIFFING_OVER; + if (mMode == VIEW_SOURCE_HTML) { + mTokenizer->StartViewSourceCharacters(); + } + auto dst = mLastBuffer->TailAsSpan(READ_BUFFER_SIZE); + dst[0] = '<'; + dst[1] = '?'; + dst[2] = 'x'; + mLastBuffer->AdvanceEnd(3); + MOZ_ASSERT(!mStartedFeedingDevTools); + OnNewContent(dst.To(3)); +} + +size_t nsHtml5StreamParser::LengthOfLtContainingPrefixInSecondBuffer() { + MOZ_ASSERT(mBufferedBytes.Length() <= 2); + if (mBufferedBytes.Length() < 2) { + return 0; + } + Buffer<uint8_t>& second = mBufferedBytes[1]; + const uint8_t* elements = second.Elements(); + const uint8_t* lt = (const uint8_t*)memchr(elements, '>', second.Length()); + if (lt) { + return (lt - elements) + 1; + } + return 0; +} + +nsresult nsHtml5StreamParser::SniffStreamBytes(Span<const uint8_t> aFromSegment, + bool aEof) { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + MOZ_ASSERT_IF(aEof, aFromSegment.IsEmpty()); + + if (mCharsetSource >= + kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && + mCharsetSource <= kCharsetFromFinalUserForcedAutoDetection) { + if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) { + mTreeBuilder->MaybeComplainAboutCharset("EncDetectorReloadPlain", true, + 0); + } else { + mTreeBuilder->MaybeComplainAboutCharset("EncDetectorReload", true, 0); + } + } + + // mEncoding and mCharsetSource potentially have come from channel or higher + // by now. If we find a BOM, SetupDecodingFromBom() will overwrite them. + // If we don't find a BOM, the previously set values of mEncoding and + // mCharsetSource are not modified by the BOM sniffing here. + static uint8_t utf8[] = {0xEF, 0xBB}; + static uint8_t utf16le[] = {0xFF}; + static uint8_t utf16be[] = {0xFE}; + static uint8_t utf16leXml[] = {'<', 0x00, '?', 0x00, 'x'}; + static uint8_t utf16beXml[] = {0x00, '<', 0x00, '?', 0x00}; + // Buffer for replaying past bytes based on state machine state. If + // writing this from scratch, probably wouldn't do it this way, but + // let's keep the changes to a minimum. + const uint8_t* prefix = utf8; + size_t prefixLength = 0; + if (aEof && mBomState == BOM_SNIFFING_NOT_STARTED) { + // Avoid handling aEof in the BOM_SNIFFING_NOT_STARTED state below. + mBomState = BOM_SNIFFING_OVER; + } + for (size_t i = 0; + (i < aFromSegment.Length() && mBomState != BOM_SNIFFING_OVER) || aEof; + i++) { + switch (mBomState) { + case BOM_SNIFFING_NOT_STARTED: + MOZ_ASSERT(i == 0, "Bad BOM sniffing state."); + MOZ_ASSERT(!aEof, "Should have checked for aEof above!"); + switch (aFromSegment[0]) { + case 0xEF: + mBomState = SEEN_UTF_8_FIRST_BYTE; + break; + case 0xFF: + mBomState = SEEN_UTF_16_LE_FIRST_BYTE; + break; + case 0xFE: + mBomState = SEEN_UTF_16_BE_FIRST_BYTE; + break; + case 0x00: + if (mCharsetSource < kCharsetFromXmlDeclarationUtf16 && + mCharsetSource != kCharsetFromChannel) { + mBomState = SEEN_UTF_16_BE_XML_FIRST; + } else { + mBomState = BOM_SNIFFING_OVER; + } + break; + case '<': + if (mCharsetSource < kCharsetFromXmlDeclarationUtf16 && + mCharsetSource != kCharsetFromChannel) { + mBomState = SEEN_UTF_16_LE_XML_FIRST; + } else { + mBomState = BOM_SNIFFING_OVER; + } + break; + default: + mBomState = BOM_SNIFFING_OVER; + break; + } + break; + case SEEN_UTF_16_LE_FIRST_BYTE: + if (!aEof && aFromSegment[i] == 0xFE) { + SetupDecodingFromBom(UTF_16LE_ENCODING); + return WriteStreamBytes(aFromSegment.From(i + 1)); + } + prefix = utf16le; + prefixLength = 1 - i; + mBomState = BOM_SNIFFING_OVER; + break; + case SEEN_UTF_16_BE_FIRST_BYTE: + if (!aEof && aFromSegment[i] == 0xFF) { + SetupDecodingFromBom(UTF_16BE_ENCODING); + return WriteStreamBytes(aFromSegment.From(i + 1)); + } + prefix = utf16be; + prefixLength = 1 - i; + mBomState = BOM_SNIFFING_OVER; + break; + case SEEN_UTF_8_FIRST_BYTE: + if (!aEof && aFromSegment[i] == 0xBB) { + mBomState = SEEN_UTF_8_SECOND_BYTE; + } else { + prefixLength = 1 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_8_SECOND_BYTE: + if (!aEof && aFromSegment[i] == 0xBF) { + SetupDecodingFromBom(UTF_8_ENCODING); + return WriteStreamBytes(aFromSegment.From(i + 1)); + } + prefixLength = 2 - i; + mBomState = BOM_SNIFFING_OVER; + break; + case SEEN_UTF_16_BE_XML_FIRST: + if (!aEof && aFromSegment[i] == '<') { + mBomState = SEEN_UTF_16_BE_XML_SECOND; + } else { + prefix = utf16beXml; + prefixLength = 1 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_BE_XML_SECOND: + if (!aEof && aFromSegment[i] == 0x00) { + mBomState = SEEN_UTF_16_BE_XML_THIRD; + } else { + prefix = utf16beXml; + prefixLength = 2 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_BE_XML_THIRD: + if (!aEof && aFromSegment[i] == '?') { + mBomState = SEEN_UTF_16_BE_XML_FOURTH; + } else { + prefix = utf16beXml; + prefixLength = 3 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_BE_XML_FOURTH: + if (!aEof && aFromSegment[i] == 0x00) { + mBomState = SEEN_UTF_16_BE_XML_FIFTH; + } else { + prefix = utf16beXml; + prefixLength = 4 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_BE_XML_FIFTH: + if (!aEof && aFromSegment[i] == 'x') { + SetupDecodingFromUtf16BogoXml(UTF_16BE_ENCODING); + return WriteStreamBytes(aFromSegment.From(i + 1)); + } + prefix = utf16beXml; + prefixLength = 5 - i; + mBomState = BOM_SNIFFING_OVER; + break; + case SEEN_UTF_16_LE_XML_FIRST: + if (!aEof && aFromSegment[i] == 0x00) { + mBomState = SEEN_UTF_16_LE_XML_SECOND; + } else { + if (!aEof && aFromSegment[i] == '?' && + !(mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN)) { + mStartsWithLtQuestion = true; + } + prefix = utf16leXml; + prefixLength = 1 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_LE_XML_SECOND: + if (!aEof && aFromSegment[i] == '?') { + mBomState = SEEN_UTF_16_LE_XML_THIRD; + } else { + prefix = utf16leXml; + prefixLength = 2 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_LE_XML_THIRD: + if (!aEof && aFromSegment[i] == 0x00) { + mBomState = SEEN_UTF_16_LE_XML_FOURTH; + } else { + prefix = utf16leXml; + prefixLength = 3 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_LE_XML_FOURTH: + if (!aEof && aFromSegment[i] == 'x') { + mBomState = SEEN_UTF_16_LE_XML_FIFTH; + } else { + prefix = utf16leXml; + prefixLength = 4 - i; + mBomState = BOM_SNIFFING_OVER; + } + break; + case SEEN_UTF_16_LE_XML_FIFTH: + if (!aEof && aFromSegment[i] == 0x00) { + SetupDecodingFromUtf16BogoXml(UTF_16LE_ENCODING); + return WriteStreamBytes(aFromSegment.From(i + 1)); + } + prefix = utf16leXml; + prefixLength = 5 - i; + mBomState = BOM_SNIFFING_OVER; + break; + default: + mBomState = BOM_SNIFFING_OVER; + break; + } + if (aEof) { + break; + } + } + // if we get here, there either was no BOM or the BOM sniffing isn't complete + // yet + + MOZ_ASSERT(mCharsetSource != kCharsetFromByteOrderMark, + "Should not come here if BOM was found."); + MOZ_ASSERT(mCharsetSource != kCharsetFromXmlDeclarationUtf16, + "Should not come here if UTF-16 bogo-XML declaration was found."); + MOZ_ASSERT(mCharsetSource != kCharsetFromOtherComponent, + "kCharsetFromOtherComponent is for XSLT."); + + if (mBomState == BOM_SNIFFING_OVER) { + if (mMode == VIEW_SOURCE_XML && mStartsWithLtQuestion && + mCharsetSource < kCharsetFromChannel) { + // Sniff for XML declaration only. + MOZ_ASSERT(!mLookingForXmlDeclarationForXmlViewSource); + MOZ_ASSERT(!aEof); + MOZ_ASSERT(!mLookingForMetaCharset); + MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing); + // Maybe we've already buffered a '>'. + MOZ_ASSERT(!mBufferedBytes.IsEmpty(), + "How did at least <? not get buffered?"); + Buffer<uint8_t>& first = mBufferedBytes[0]; + const Encoding* encoding = + xmldecl_parse(first.Elements(), first.Length()); + if (encoding) { + mEncoding = WrapNotNull(encoding); + mCharsetSource = kCharsetFromXmlDeclaration; + } else if (memchr(first.Elements(), '>', first.Length())) { + // There was a '>', but an encoding still wasn't found. + ; // fall through to commit to the UTF-8 default. + } else if (size_t lengthOfPrefix = + LengthOfLtContainingPrefixInSecondBuffer()) { + // This can only happen if the first buffer was a lone '<', because + // we come here upon seeing the second byte '?' if the first two bytes + // were "<?". That is, the only way how we aren't dealing with the first + // buffer is if the first buffer only contained a single '<' and we are + // dealing with the second buffer that starts with '?'. + MOZ_ASSERT(first.Length() == 1); + MOZ_ASSERT(mBufferedBytes[1][0] == '?'); + // Our scanner for XML declaration-like syntax wants to see a contiguous + // buffer, so let's linearize the data. (Ideally, the XML declaration + // scanner would be incremental, but this is the rare path anyway.) + Vector<uint8_t> contiguous; + if (!contiguous.append(first.Elements(), first.Length())) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return NS_ERROR_OUT_OF_MEMORY; + } + if (!contiguous.append(mBufferedBytes[1].Elements(), lengthOfPrefix)) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return NS_ERROR_OUT_OF_MEMORY; + } + encoding = xmldecl_parse(contiguous.begin(), contiguous.length()); + if (encoding) { + mEncoding = WrapNotNull(encoding); + mCharsetSource = kCharsetFromXmlDeclaration; + } + // else no XML decl, commit to the UTF-8 default. + } else { + MOZ_ASSERT(mBufferingBytes); + mLookingForXmlDeclarationForXmlViewSource = true; + return NS_OK; + } + } else if (mMode != VIEW_SOURCE_XML && + (mForceAutoDetection || mCharsetSource < kCharsetFromChannel)) { + // In order to use the buffering logic for meta with mForceAutoDetection, + // we set mLookingForMetaCharset but still actually potentially ignore the + // meta. + mFirstBufferOfMetaScan = mFirstBuffer; + MOZ_ASSERT(mLookingForMetaCharset); + + if (mMode == VIEW_SOURCE_HTML) { + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + return r.unwrapErr(); + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return r.unwrapErr(); + } + // Encoding committer flushes the ops on the main thread. + + mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex); + nsHtml5Speculation* speculation = new nsHtml5Speculation( + mFirstBuffer, mFirstBuffer->getStart(), mTokenizer->getLineNumber(), + mTokenizer->getColumnNumber(), mTreeBuilder->newSnapshot()); + MOZ_ASSERT(!mFlushTimerArmed, "How did we end up arming the timer?"); + if (mMode == VIEW_SOURCE_HTML) { + mTokenizer->SetViewSourceOpSink(speculation); + mTokenizer->StartViewSourceCharacters(); + } else { + MOZ_ASSERT(mMode != VIEW_SOURCE_XML); + mTreeBuilder->SetOpSink(speculation); + } + mSpeculations.AppendElement(speculation); // adopts the pointer + mSpeculating = true; + } else { + mLookingForMetaCharset = false; + mBufferingBytes = false; + mDecodingLocalFileWithoutTokenizing = false; + if (mMode == VIEW_SOURCE_HTML) { + mTokenizer->StartViewSourceCharacters(); + } + } + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false); + return SetupDecodingAndWriteSniffingBufferAndCurrentSegment( + Span(prefix, prefixLength), aFromSegment); + } + + return NS_OK; +} + +class AddContentRunnable : public Runnable { + public: + AddContentRunnable(const nsAString& aParserID, nsIURI* aURI, + Span<const char16_t> aData, bool aComplete) + : Runnable("AddContent") { + nsAutoCString spec; + aURI->GetSpec(spec); + mData.mUri.Construct(NS_ConvertUTF8toUTF16(spec)); + mData.mParserID.Construct(aParserID); + mData.mContents.Construct(aData.Elements(), aData.Length()); + mData.mComplete.Construct(aComplete); + } + + NS_IMETHOD Run() override { + nsAutoString json; + if (!mData.ToJSON(json)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIObserverService> obsService = services::GetObserverService(); + if (obsService) { + obsService->NotifyObservers(nullptr, "devtools-html-content", + PromiseFlatString(json).get()); + } + + return NS_OK; + } + + HTMLContent mData; +}; + +inline void nsHtml5StreamParser::OnNewContent(Span<const char16_t> aData) { +#ifdef DEBUG + mStartedFeedingDevTools = true; +#endif + if (mURIToSendToDevtools) { + if (aData.IsEmpty()) { + // Optimize out the runnable. + return; + } + NS_DispatchToMainThread(new AddContentRunnable(mUUIDForDevtools, + mURIToSendToDevtools, aData, + /* aComplete */ false)); + } +} + +inline void nsHtml5StreamParser::OnContentComplete() { +#ifdef DEBUG + mStartedFeedingDevTools = true; +#endif + if (mURIToSendToDevtools) { + NS_DispatchToMainThread(new AddContentRunnable( + mUUIDForDevtools, mURIToSendToDevtools, Span<const char16_t>(), + /* aComplete */ true)); + mURIToSendToDevtools = nullptr; + } +} + +nsresult nsHtml5StreamParser::WriteStreamBytes( + Span<const uint8_t> aFromSegment) { + NS_ASSERTION(IsParserThread(), "Wrong thread!"); + mTokenizerMutex.AssertCurrentThreadOwns(); + // mLastBuffer should always point to a buffer of the size + // READ_BUFFER_SIZE. + if (!mLastBuffer) { + NS_WARNING("mLastBuffer should not be null!"); + MarkAsBroken(NS_ERROR_NULL_POINTER); + return NS_ERROR_NULL_POINTER; + } + size_t totalRead = 0; + auto src = aFromSegment; + for (;;) { + auto dst = mLastBuffer->TailAsSpan(READ_BUFFER_SIZE); + auto [result, read, written, hadErrors] = + mUnicodeDecoder->DecodeToUTF16(src, dst, false); + if (!(mLookingForMetaCharset || mDecodingLocalFileWithoutTokenizing)) { + OnNewContent(dst.To(written)); + } + if (hadErrors && !mHasHadErrors) { + mHasHadErrors = true; + if (mEncoding == UTF_8_ENCODING) { + mTreeBuilder->TryToEnableEncodingMenu(); + } + } + src = src.From(read); + totalRead += read; + mLastBuffer->AdvanceEnd(written); + if (result == kOutputFull) { + RefPtr<nsHtml5OwningUTF16Buffer> newBuf = + nsHtml5OwningUTF16Buffer::FalliblyCreate(READ_BUFFER_SIZE); + if (!newBuf) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return NS_ERROR_OUT_OF_MEMORY; + } + mLastBuffer = (mLastBuffer->next = std::move(newBuf)); + } else { + MOZ_ASSERT(totalRead == aFromSegment.Length(), + "The Unicode decoder consumed the wrong number of bytes."); + (void)totalRead; + if (!mLookingForMetaCharset && mDecodingLocalFileWithoutTokenizing && + mNumBytesBuffered == LOCAL_FILE_UTF_8_BUFFER_SIZE) { + MOZ_ASSERT(!mStartedFeedingDetector); + for (auto&& buffer : mBufferedBytes) { + FeedDetector(buffer); + } + // If the file is exactly LOCAL_FILE_UTF_8_BUFFER_SIZE bytes long + // we end up not considering the EOF. That's not fatal, since we + // don't consider the EOF if the file is + // LOCAL_FILE_UTF_8_BUFFER_SIZE + 1 bytes long. + auto [encoding, source] = GuessEncoding(true); + mCharsetSource = source; + if (encoding != mEncoding) { + mEncoding = encoding; + nsresult rv = ReDecodeLocalFile(); + if (NS_FAILED(rv)) { + return rv; + } + } else { + MOZ_ASSERT(mEncoding == UTF_8_ENCODING); + nsresult rv = CommitLocalFileToEncoding(); + if (NS_FAILED(rv)) { + return rv; + } + } + } + return NS_OK; + } + } +} + +[[nodiscard]] nsresult nsHtml5StreamParser::ReDecodeLocalFile() { + MOZ_ASSERT(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset); + MOZ_ASSERT(mFirstBufferOfMetaScan); + MOZ_ASSERT(mCharsetSource == kCharsetFromFinalAutoDetectionFile || + (mForceAutoDetection && + mCharsetSource == kCharsetFromInitialUserForcedAutoDetection)); + + DiscardMetaSpeculation(); + + MOZ_ASSERT(mEncoding != UTF_8_ENCODING); + + mDecodingLocalFileWithoutTokenizing = false; + + mEncoding->NewDecoderWithBOMRemovalInto(*mUnicodeDecoder); + mHasHadErrors = false; + + // Throw away previous decoded data + mLastBuffer = mFirstBuffer; + mLastBuffer->next = nullptr; + mLastBuffer->setStart(0); + mLastBuffer->setEnd(0); + + mBufferingBytes = false; + mForceAutoDetection = false; // To stop feeding the detector + mFirstBufferOfMetaScan = nullptr; + + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, true); + + // Decode again + for (auto&& buffer : mBufferedBytes) { + DoDataAvailable(buffer); + } + + if (mMode == VIEW_SOURCE_HTML) { + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + return r.unwrapErr(); + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return r.unwrapErr(); + } + return NS_OK; +} + +[[nodiscard]] nsresult nsHtml5StreamParser::CommitLocalFileToEncoding() { + MOZ_ASSERT(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset); + MOZ_ASSERT(mFirstBufferOfMetaScan); + mDecodingLocalFileWithoutTokenizing = false; + MOZ_ASSERT(mCharsetSource == kCharsetFromFinalAutoDetectionFile || + (mForceAutoDetection && + mCharsetSource == kCharsetFromInitialUserForcedAutoDetection)); + MOZ_ASSERT(mEncoding == UTF_8_ENCODING); + + MOZ_ASSERT(!mStartedFeedingDevTools); + if (mURIToSendToDevtools) { + nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan; + while (buffer) { + Span<const char16_t> data(buffer->getBuffer() + buffer->getStart(), + buffer->getLength()); + OnNewContent(data); + buffer = buffer->next; + } + } + + mFirstBufferOfMetaScan = nullptr; + + mBufferingBytes = false; + mForceAutoDetection = false; // To stop feeding the detector + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, true); + if (mMode == VIEW_SOURCE_HTML) { + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + return r.unwrapErr(); + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return r.unwrapErr(); + } + return NS_OK; +} + +class MaybeRunCollector : public Runnable { + public: + explicit MaybeRunCollector(nsIDocShell* aDocShell) + : Runnable("MaybeRunCollector"), mDocShell(aDocShell) {} + + NS_IMETHOD Run() override { + nsJSContext::MaybeRunNextCollectorSlice(mDocShell, + JS::GCReason::HTML_PARSER); + return NS_OK; + } + + nsCOMPtr<nsIDocShell> mDocShell; +}; + +nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) { + MOZ_RELEASE_ASSERT(STREAM_NOT_STARTED == mStreamState, + "Got OnStartRequest when the stream had already started."); + MOZ_ASSERT( + !mExecutor->HasStarted(), + "Got OnStartRequest at the wrong stage in the executor life cycle."); + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + + // To avoid the cost of instantiating the detector when it's not needed, + // let's instantiate only if we make it out of this method with the + // intent to use it. + auto detectorCreator = MakeScopeExit([&] { + if ((mForceAutoDetection || mCharsetSource < kCharsetFromParentFrame) || + !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML)) { + mDetector = mozilla::EncodingDetector::Create(); + } + }); + + mRequest = aRequest; + + mStreamState = STREAM_BEING_READ; + + // For View Source, the parser should run with scripts "enabled" if a normal + // load would have scripts enabled. + bool scriptingEnabled = + mMode == LOAD_AS_DATA ? false : mExecutor->IsScriptEnabled(); + mOwner->StartTokenizer(scriptingEnabled); + + MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing); + bool isSrcdoc = false; + nsCOMPtr<nsIChannel> channel; + nsresult rv = GetChannel(getter_AddRefs(channel)); + if (NS_SUCCEEDED(rv)) { + isSrcdoc = NS_IsSrcdocChannel(channel); + if (!isSrcdoc && mCharsetSource <= kCharsetFromFallback) { + nsCOMPtr<nsIURI> originalURI; + rv = channel->GetOriginalURI(getter_AddRefs(originalURI)); + if (NS_SUCCEEDED(rv)) { + if (originalURI->SchemeIs("resource")) { + mCharsetSource = kCharsetFromBuiltIn; + mEncoding = UTF_8_ENCODING; + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false); + } else { + nsCOMPtr<nsIURI> currentURI; + rv = channel->GetURI(getter_AddRefs(currentURI)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr<nsIURI> innermost = NS_GetInnermostURI(currentURI); + if (innermost->SchemeIs("file")) { + MOZ_ASSERT(mEncoding == UTF_8_ENCODING); + if (!(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML)) { + mDecodingLocalFileWithoutTokenizing = true; + } + } else { + nsAutoCString host; + innermost->GetAsciiHost(host); + if (!host.IsEmpty()) { + // First let's see if the host is DNS-absolute and ends with a + // dot and get rid of that one. + if (host.Last() == '.') { + host.SetLength(host.Length() - 1); + } + int32_t index = host.RFindChar('.'); + if (index != kNotFound) { + // We tolerate an IPv4 component as generic "TLD", so don't + // bother checking. + ToLowerCase( + Substring(host, index + 1, host.Length() - (index + 1)), + mTLD); + } + } + } + } + } + } + } + } + mTreeBuilder->setIsSrcdocDocument(isSrcdoc); + mTreeBuilder->setScriptingEnabled(scriptingEnabled); + mTreeBuilder->SetPreventScriptExecution( + !((mMode == NORMAL) && scriptingEnabled)); + mTokenizer->start(); + mExecutor->Start(); + mExecutor->StartReadingFromStage(); + + if (mMode == PLAIN_TEXT) { + mTreeBuilder->StartPlainText(); + mTokenizer->StartPlainText(); + MOZ_ASSERT( + mTemplatePushedOrHeadPopped); // Needed to force 1024-byte sniffing + // Flush the ops to put them where ContinueAfterScriptsOrEncodingCommitment + // can find them. + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return mExecutor->MarkAsBroken(r.unwrapErr()); + } + } else if (mMode == VIEW_SOURCE_PLAIN) { + nsAutoString viewSourceTitle; + CopyUTF8toUTF16(mViewSourceTitle, viewSourceTitle); + mTreeBuilder->EnsureBufferSpace(viewSourceTitle.Length()); + mTreeBuilder->StartPlainTextViewSource(viewSourceTitle); + mTokenizer->StartPlainText(); + MOZ_ASSERT( + mTemplatePushedOrHeadPopped); // Needed to force 1024-byte sniffing + // Flush the ops to put them where ContinueAfterScriptsOrEncodingCommitment + // can find them. + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + return mExecutor->MarkAsBroken(r.unwrapErr()); + } + } else if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) { + // Generate and flush the View Source document up to and including the + // pre element start. + mTokenizer->StartViewSource(NS_ConvertUTF8toUTF16(mViewSourceTitle)); + if (mMode == VIEW_SOURCE_XML) { + mTokenizer->StartViewSourceCharacters(); + } + // Flush the ops to put them where ContinueAfterScriptsOrEncodingCommitment + // can find them. + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + return mExecutor->MarkAsBroken(r.unwrapErr()); + } + } + + /* + * If you move the following line, be very careful not to cause + * WillBuildModel to be called before the document has had its + * script global object set. + */ + rv = mExecutor->WillBuildModel(); + NS_ENSURE_SUCCESS(rv, rv); + + RefPtr<nsHtml5OwningUTF16Buffer> newBuf = + nsHtml5OwningUTF16Buffer::FalliblyCreate(READ_BUFFER_SIZE); + if (!newBuf) { + // marks this stream parser as terminated, + // which prevents entry to code paths that + // would use mFirstBuffer or mLastBuffer. + return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + MOZ_ASSERT(!mFirstBuffer, "How come we have the first buffer set?"); + MOZ_ASSERT(!mLastBuffer, "How come we have the last buffer set?"); + mFirstBuffer = mLastBuffer = newBuf; + + rv = NS_OK; + + mNetworkEventTarget = + mExecutor->GetDocument()->EventTargetFor(TaskCategory::Network); + + nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mRequest, &rv)); + if (NS_SUCCEEDED(rv)) { + // Non-HTTP channels are bogus enough that we let them work with unlabeled + // runnables for now. Asserting for HTTP channels only. + MOZ_ASSERT(mNetworkEventTarget || mMode == LOAD_AS_DATA, + "How come the network event target is still null?"); + + nsAutoCString method; + Unused << httpChannel->GetRequestMethod(method); + // XXX does Necko have a way to renavigate POST, etc. without hitting + // the network? + if (!method.EqualsLiteral("GET")) { + // This is the old Gecko behavior but the HTML5 spec disagrees. + // Don't reparse on POST. + mReparseForbidden = true; + } + } + + // Attempt to retarget delivery of data (via OnDataAvailable) to the parser + // thread, rather than through the main thread. + nsCOMPtr<nsIThreadRetargetableRequest> threadRetargetableRequest = + do_QueryInterface(mRequest, &rv); + if (threadRetargetableRequest) { + rv = threadRetargetableRequest->RetargetDeliveryTo(mEventTarget); + if (NS_SUCCEEDED(rv)) { + // Parser thread should be now ready to get data from necko and parse it + // and main thread might have a chance to process a collector slice. + // We need to do this asynchronously so that necko may continue processing + // the request. + nsCOMPtr<nsIRunnable> runnable = + new MaybeRunCollector(mExecutor->GetDocument()->GetDocShell()); + mozilla::SchedulerGroup::Dispatch( + mozilla::TaskCategory::GarbageCollection, runnable.forget()); + } + } + + if (NS_FAILED(rv)) { + NS_WARNING("Failed to retarget HTML data delivery to the parser thread."); + } + + if (mCharsetSource == kCharsetFromParentFrame) { + // Remember this for error reporting. + mInitialEncodingWasFromParentFrame = true; + MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing); + } + + if (mForceAutoDetection || mCharsetSource < kCharsetFromChannel) { + mBufferingBytes = true; + if (mMode != VIEW_SOURCE_XML) { + // We need to set mLookingForMetaCharset to true here in case the first + // buffer to arrive is larger than 1024. We need the code that splits + // the buffers at 1024 bytes to work even in that case. + mLookingForMetaCharset = true; + } + } + + if (mCharsetSource < kCharsetFromUtf8OnlyMime) { + // we aren't ready to commit to an encoding yet + // leave converter uninstantiated for now + return NS_OK; + } + + MOZ_ASSERT(!(mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML)); + + MOZ_ASSERT(mEncoding == UTF_8_ENCODING, + "How come UTF-8-only MIME type didn't set encoding to UTF-8?"); + + // We are loading JSON/WebVTT/etc. into a browsing context. + // There's no need to remove the BOM manually here, because + // the UTF-8 decoder removes it. + mReparseForbidden = true; + mForceAutoDetection = false; + + // Instantiate the converter here to avoid BOM sniffing. + mDecodingLocalFileWithoutTokenizing = false; + mUnicodeDecoder = mEncoding->NewDecoderWithBOMRemoval(); + return NS_OK; +} + +void nsHtml5StreamParser::DoStopRequest() { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + MOZ_RELEASE_ASSERT(STREAM_BEING_READ == mStreamState, + "Stream ended without being open."); + mTokenizerMutex.AssertCurrentThreadOwns(); + + auto guard = MakeScopeExit([&] { OnContentComplete(); }); + + if (IsTerminated()) { + return; + } + + if (MOZ_UNLIKELY(mLookingForXmlDeclarationForXmlViewSource)) { + mLookingForXmlDeclarationForXmlViewSource = false; + mBufferingBytes = false; + mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling(); + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false); + + for (auto&& buffer : mBufferedBytes) { + nsresult rv = WriteStreamBytes(buffer); + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + return; + } + } + } else if (!mUnicodeDecoder) { + nsresult rv; + if (NS_FAILED(rv = SniffStreamBytes(Span<const uint8_t>(), true))) { + MarkAsBroken(rv); + return; + } + } + + MOZ_ASSERT(mUnicodeDecoder, + "Should have a decoder after finalizing sniffing."); + + // mLastBuffer should always point to a buffer of the size + // READ_BUFFER_SIZE. + if (!mLastBuffer) { + NS_WARNING("mLastBuffer should not be null!"); + MarkAsBroken(NS_ERROR_NULL_POINTER); + return; + } + + Span<uint8_t> src; // empty span + for (;;) { + auto dst = mLastBuffer->TailAsSpan(READ_BUFFER_SIZE); + uint32_t result; + size_t read; + size_t written; + bool hadErrors; + // Do not use structured binding lest deal with [-Werror=unused-variable] + std::tie(result, read, written, hadErrors) = + mUnicodeDecoder->DecodeToUTF16(src, dst, true); + if (!(mLookingForMetaCharset || mDecodingLocalFileWithoutTokenizing)) { + OnNewContent(dst.To(written)); + } + if (hadErrors) { + mHasHadErrors = true; + } + MOZ_ASSERT(read == 0, "How come an empty span was read form?"); + mLastBuffer->AdvanceEnd(written); + if (result == kOutputFull) { + RefPtr<nsHtml5OwningUTF16Buffer> newBuf = + nsHtml5OwningUTF16Buffer::FalliblyCreate(READ_BUFFER_SIZE); + if (!newBuf) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + mLastBuffer = (mLastBuffer->next = std::move(newBuf)); + } else { + if (!mLookingForMetaCharset && mDecodingLocalFileWithoutTokenizing) { + MOZ_ASSERT(mNumBytesBuffered < LOCAL_FILE_UTF_8_BUFFER_SIZE); + MOZ_ASSERT(!mStartedFeedingDetector); + for (auto&& buffer : mBufferedBytes) { + FeedDetector(buffer); + } + MOZ_ASSERT(!mChardetEof); + DetectorEof(); + auto [encoding, source] = GuessEncoding(true); + mCharsetSource = source; + if (encoding != mEncoding) { + mEncoding = encoding; + nsresult rv = ReDecodeLocalFile(); + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + return; + } + DoStopRequest(); + return; + } + MOZ_ASSERT(mEncoding == UTF_8_ENCODING); + nsresult rv = CommitLocalFileToEncoding(); + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + return; + } + } + break; + } + } + + mStreamState = STREAM_ENDED; + + if (IsTerminatedOrInterrupted()) { + return; + } + + ParseAvailableData(); +} + +class nsHtml5RequestStopper : public Runnable { + private: + nsHtml5StreamParserPtr mStreamParser; + + public: + explicit nsHtml5RequestStopper(nsHtml5StreamParser* aStreamParser) + : Runnable("nsHtml5RequestStopper"), mStreamParser(aStreamParser) {} + NS_IMETHOD Run() override { + mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex); + mStreamParser->DoStopRequest(); + mStreamParser->PostLoadFlusher(); + return NS_OK; + } +}; + +nsresult nsHtml5StreamParser::OnStopRequest(nsIRequest* aRequest, + nsresult status) { + MOZ_ASSERT(mRequest == aRequest, "Got Stop on wrong stream."); + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + nsCOMPtr<nsIRunnable> stopper = new nsHtml5RequestStopper(this); + if (NS_FAILED(mEventTarget->Dispatch(stopper, nsIThread::DISPATCH_NORMAL))) { + NS_WARNING("Dispatching StopRequest event failed."); + } + return NS_OK; +} + +void nsHtml5StreamParser::DoDataAvailableBuffer( + mozilla::Buffer<uint8_t>&& aBuffer) { + if (MOZ_UNLIKELY(!mBufferingBytes)) { + DoDataAvailable(aBuffer); + return; + } + if (MOZ_UNLIKELY(mLookingForXmlDeclarationForXmlViewSource)) { + const uint8_t* elements = aBuffer.Elements(); + size_t length = aBuffer.Length(); + const uint8_t* lt = (const uint8_t*)memchr(elements, '>', length); + if (!lt) { + mBufferedBytes.AppendElement(std::move(aBuffer)); + return; + } + + // We found an '>'. Now there either is or isn't an XML decl. + length = (lt - elements) + 1; + Vector<uint8_t> contiguous; + for (auto&& buffer : mBufferedBytes) { + if (!contiguous.append(buffer.Elements(), buffer.Length())) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + } + if (!contiguous.append(elements, length)) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + + const Encoding* encoding = + xmldecl_parse(contiguous.begin(), contiguous.length()); + if (encoding) { + mEncoding = WrapNotNull(encoding); + mCharsetSource = kCharsetFromXmlDeclaration; + } + + mLookingForXmlDeclarationForXmlViewSource = false; + mBufferingBytes = false; + mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling(); + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false); + + for (auto&& buffer : mBufferedBytes) { + DoDataAvailable(buffer); + } + DoDataAvailable(aBuffer); + mBufferedBytes.Clear(); + return; + } + CheckedInt<size_t> bufferedPlusLength(aBuffer.Length()); + bufferedPlusLength += mNumBytesBuffered; + if (!bufferedPlusLength.isValid()) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + // Ensure that WriteStreamBytes() sees buffers ending + // exactly at the two special boundaries. + bool metaBoundaryWithinBuffer = + mLookingForMetaCharset && + mNumBytesBuffered < UNCONDITIONAL_META_SCAN_BOUNDARY && + bufferedPlusLength.value() > UNCONDITIONAL_META_SCAN_BOUNDARY; + bool localFileLimitWithinBuffer = + mDecodingLocalFileWithoutTokenizing && + mNumBytesBuffered < LOCAL_FILE_UTF_8_BUFFER_SIZE && + bufferedPlusLength.value() > LOCAL_FILE_UTF_8_BUFFER_SIZE; + if (!metaBoundaryWithinBuffer && !localFileLimitWithinBuffer) { + // Truncation OK, because we just checked the range. + mNumBytesBuffered = bufferedPlusLength.value(); + mBufferedBytes.AppendElement(std::move(aBuffer)); + DoDataAvailable(mBufferedBytes.LastElement()); + } else { + MOZ_RELEASE_ASSERT( + !(metaBoundaryWithinBuffer && localFileLimitWithinBuffer), + "How can Necko give us a buffer this large?"); + size_t boundary = metaBoundaryWithinBuffer + ? UNCONDITIONAL_META_SCAN_BOUNDARY + : LOCAL_FILE_UTF_8_BUFFER_SIZE; + // Truncation OK, because the constant is small enough. + size_t overBoundary = bufferedPlusLength.value() - boundary; + MOZ_RELEASE_ASSERT(overBoundary < aBuffer.Length()); + size_t untilBoundary = aBuffer.Length() - overBoundary; + auto span = aBuffer.AsSpan(); + auto head = span.To(untilBoundary); + auto tail = span.From(untilBoundary); + MOZ_RELEASE_ASSERT(mNumBytesBuffered + untilBoundary == boundary); + // The following copies may end up being useless, but optimizing + // them away would add complexity. + Maybe<Buffer<uint8_t>> maybeHead = Buffer<uint8_t>::CopyFrom(head); + if (maybeHead.isNothing()) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + mNumBytesBuffered = boundary; + mBufferedBytes.AppendElement(std::move(*maybeHead)); + DoDataAvailable(mBufferedBytes.LastElement()); + // Re-decode may have happened here. + + Maybe<Buffer<uint8_t>> maybeTail = Buffer<uint8_t>::CopyFrom(tail); + if (maybeTail.isNothing()) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + mNumBytesBuffered += tail.Length(); + mBufferedBytes.AppendElement(std::move(*maybeTail)); + DoDataAvailable(mBufferedBytes.LastElement()); + } + // Do this clean-up here to avoid use-after-free when + // DoDataAvailable is passed a span pointing into an + // element of mBufferedBytes. + if (!mBufferingBytes) { + mBufferedBytes.Clear(); + } +} + +void nsHtml5StreamParser::DoDataAvailable(Span<const uint8_t> aBuffer) { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + MOZ_RELEASE_ASSERT(STREAM_BEING_READ == mStreamState, + "DoDataAvailable called when stream not open."); + mTokenizerMutex.AssertCurrentThreadOwns(); + + if (IsTerminated()) { + return; + } + + nsresult rv; + if (HasDecoder()) { + if ((mForceAutoDetection || mCharsetSource < kCharsetFromParentFrame) && + !mBufferingBytes && !mReparseForbidden && + !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML)) { + MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing, + "How is mBufferingBytes false if " + "mDecodingLocalFileWithoutTokenizing is true?"); + FeedDetector(aBuffer); + } + rv = WriteStreamBytes(aBuffer); + } else { + rv = SniffStreamBytes(aBuffer, false); + } + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + return; + } + + if (IsTerminatedOrInterrupted()) { + return; + } + + if (!mLookingForMetaCharset && mDecodingLocalFileWithoutTokenizing) { + return; + } + + ParseAvailableData(); + + if (mBomState != BOM_SNIFFING_OVER || mFlushTimerArmed || mSpeculating) { + return; + } + + { + mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex); + mFlushTimer->InitWithNamedFuncCallback( + nsHtml5StreamParser::TimerCallback, static_cast<void*>(this), + mFlushTimerEverFired ? StaticPrefs::html5_flushtimer_initialdelay() + : StaticPrefs::html5_flushtimer_subsequentdelay(), + nsITimer::TYPE_ONE_SHOT, "nsHtml5StreamParser::DoDataAvailable"); + } + mFlushTimerArmed = true; +} + +class nsHtml5DataAvailable : public Runnable { + private: + nsHtml5StreamParserPtr mStreamParser; + Buffer<uint8_t> mData; + + public: + nsHtml5DataAvailable(nsHtml5StreamParser* aStreamParser, + Buffer<uint8_t>&& aData) + : Runnable("nsHtml5DataAvailable"), + mStreamParser(aStreamParser), + mData(std::move(aData)) {} + NS_IMETHOD Run() override { + mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex); + mStreamParser->DoDataAvailableBuffer(std::move(mData)); + mStreamParser->PostLoadFlusher(); + return NS_OK; + } +}; + +nsresult nsHtml5StreamParser::OnDataAvailable(nsIRequest* aRequest, + nsIInputStream* aInStream, + uint64_t aSourceOffset, + uint32_t aLength) { + nsresult rv; + + MOZ_ASSERT(mRequest == aRequest, "Got data on wrong stream."); + uint32_t totalRead; + // Main thread to parser thread dispatch requires copying to buffer first. + if (MOZ_UNLIKELY(NS_IsMainThread())) { + if (NS_FAILED(rv = mExecutor->IsBroken())) { + return rv; + } + Maybe<Buffer<uint8_t>> maybe = Buffer<uint8_t>::Alloc(aLength); + if (maybe.isNothing()) { + return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + Buffer<uint8_t> data(std::move(*maybe)); + rv = aInStream->Read(reinterpret_cast<char*>(data.Elements()), + data.Length(), &totalRead); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_ASSERT(totalRead == aLength); + + nsCOMPtr<nsIRunnable> dataAvailable = + new nsHtml5DataAvailable(this, std::move(data)); + if (NS_FAILED(mEventTarget->Dispatch(dataAvailable, + nsIThread::DISPATCH_NORMAL))) { + NS_WARNING("Dispatching DataAvailable event failed."); + } + return rv; + } + + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mozilla::MutexAutoLock autoLock(mTokenizerMutex); + + if (NS_FAILED(rv = mTreeBuilder->IsBroken())) { + return rv; + } + + // Since we're getting OnDataAvailable directly on the parser thread, + // there is no nsHtml5DataAvailable that would call PostLoadFlusher. + // Hence, we need to call PostLoadFlusher() before this method returns. + // Braces for RAII clarity relative to the mutex despite not being + // strictly necessary. + { + auto speculationFlusher = MakeScopeExit([&] { PostLoadFlusher(); }); + + if (mBufferingBytes) { + Maybe<Buffer<uint8_t>> maybe = Buffer<uint8_t>::Alloc(aLength); + if (maybe.isNothing()) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return NS_ERROR_OUT_OF_MEMORY; + } + Buffer<uint8_t> data(std::move(*maybe)); + rv = aInStream->Read(reinterpret_cast<char*>(data.Elements()), + data.Length(), &totalRead); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_ASSERT(totalRead == aLength); + DoDataAvailableBuffer(std::move(data)); + return rv; + } + // Read directly from response buffer. + rv = aInStream->ReadSegments(CopySegmentsToParser, this, aLength, + &totalRead); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_ASSERT(totalRead == aLength); + return rv; + } +} + +// Called under lock by function ptr +/* static */ +nsresult nsHtml5StreamParser::CopySegmentsToParser( + nsIInputStream* aInStream, void* aClosure, const char* aFromSegment, + uint32_t aToOffset, uint32_t aCount, + uint32_t* aWriteCount) MOZ_NO_THREAD_SAFETY_ANALYSIS { + nsHtml5StreamParser* parser = static_cast<nsHtml5StreamParser*>(aClosure); + + parser->DoDataAvailable(AsBytes(Span(aFromSegment, aCount))); + // Assume DoDataAvailable consumed all available bytes. + *aWriteCount = aCount; + return NS_OK; +} + +const Encoding* nsHtml5StreamParser::PreferredForInternalEncodingDecl( + const nsAString& aEncoding) { + const Encoding* newEncoding = Encoding::ForLabel(aEncoding); + if (!newEncoding) { + // the encoding name is bogus + mTreeBuilder->MaybeComplainAboutCharset("EncMetaUnsupported", true, + mTokenizer->getLineNumber()); + return nullptr; + } + + if (newEncoding == UTF_16BE_ENCODING || newEncoding == UTF_16LE_ENCODING) { + mTreeBuilder->MaybeComplainAboutCharset("EncMetaUtf16", true, + mTokenizer->getLineNumber()); + newEncoding = UTF_8_ENCODING; + } + + if (newEncoding == X_USER_DEFINED_ENCODING) { + // WebKit/Blink hack for Indian and Armenian legacy sites + mTreeBuilder->MaybeComplainAboutCharset("EncMetaUserDefined", true, + mTokenizer->getLineNumber()); + newEncoding = WINDOWS_1252_ENCODING; + } + + if (newEncoding == REPLACEMENT_ENCODING) { + // No line number, because the replacement encoding doesn't allow + // showing the lines. + mTreeBuilder->MaybeComplainAboutCharset("EncMetaReplacement", true, 0); + } + + return newEncoding; +} + +bool nsHtml5StreamParser::internalEncodingDeclaration(nsHtml5String aEncoding) { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + if ((mCharsetSource >= kCharsetFromMetaTag && + mCharsetSource != kCharsetFromFinalAutoDetectionFile) || + mSeenEligibleMetaCharset) { + return false; + } + + nsString newEncoding; // Not Auto, because using it to hold nsStringBuffer* + aEncoding.ToString(newEncoding); + auto encoding = PreferredForInternalEncodingDecl(newEncoding); + if (!encoding) { + return false; + } + + mSeenEligibleMetaCharset = true; + + if (!mLookingForMetaCharset) { + if (mInitialEncodingWasFromParentFrame) { + mTreeBuilder->MaybeComplainAboutCharset("EncMetaTooLateFrame", true, + mTokenizer->getLineNumber()); + } else { + mTreeBuilder->MaybeComplainAboutCharset("EncMetaTooLate", true, + mTokenizer->getLineNumber()); + } + return false; + } + if (mTemplatePushedOrHeadPopped) { + mTreeBuilder->MaybeComplainAboutCharset("EncMetaAfterHeadInKilobyte", false, + mTokenizer->getLineNumber()); + } + + if (mForceAutoDetection && + (encoding->IsAsciiCompatible() || encoding == ISO_2022_JP_ENCODING)) { + return false; + } + + mNeedsEncodingSwitchTo = encoding; + mEncodingSwitchSource = kCharsetFromMetaTag; + return true; +} + +bool nsHtml5StreamParser::TemplatePushedOrHeadPopped() { + MOZ_ASSERT( + IsParserThread() || mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN, + "Wrong thread!"); + mTemplatePushedOrHeadPopped = true; + return mNumBytesBuffered >= UNCONDITIONAL_META_SCAN_BOUNDARY; +} + +void nsHtml5StreamParser::RememberGt(int32_t aPos) { + if (mLookingForMetaCharset) { + mGtBuffer = mFirstBuffer; + mGtPos = aPos; + } +} + +void nsHtml5StreamParser::PostLoadFlusher() { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mTokenizerMutex.AssertCurrentThreadOwns(); + + mTreeBuilder->FlushLoads(); + // Dispatch this runnable unconditionally, because the loads + // that need flushing may have been flushed earlier even if the + // flush right above here did nothing. (Is this still true?) + nsCOMPtr<nsIRunnable> runnable(mLoadFlusher); + if (NS_FAILED( + DispatchToMain(CreateRenderBlockingRunnable(runnable.forget())))) { + NS_WARNING("failed to dispatch load flush event"); + } + + if ((mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) && + mTokenizer->ShouldFlushViewSource()) { + auto r = mTreeBuilder->Flush(); // delete useless ops + MOZ_ASSERT(r.isOk(), "Should have null sink with View Source"); + r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return; + } + if (r.unwrap()) { + nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher); + if (NS_FAILED(DispatchToMain(runnable.forget()))) { + NS_WARNING("failed to dispatch executor flush event"); + } + } + } +} + +void nsHtml5StreamParser::FlushTreeOpsAndDisarmTimer() { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + if (mFlushTimerArmed) { + // avoid calling Cancel if the flush timer isn't armed to avoid acquiring + // a mutex + { + mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex); + mFlushTimer->Cancel(); + } + mFlushTimerArmed = false; + } + if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) { + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + } + nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher); + if (NS_FAILED(DispatchToMain(runnable.forget()))) { + NS_WARNING("failed to dispatch executor flush event"); + } +} + +void nsHtml5StreamParser::SwitchDecoderIfAsciiSoFar( + NotNull<const Encoding*> aEncoding) { + if (mEncoding == aEncoding) { + MOZ_ASSERT(!mStartedFeedingDevTools); + // Report all already-decoded buffers to the dev tools if needed. + if (mURIToSendToDevtools) { + nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan; + while (buffer) { + auto s = Span(buffer->getBuffer(), buffer->getEnd()); + OnNewContent(s); + buffer = buffer->next; + } + } + return; + } + if (!mEncoding->IsAsciiCompatible() || !aEncoding->IsAsciiCompatible()) { + return; + } + size_t numAscii = 0; + MOZ_ASSERT(mFirstBufferOfMetaScan, + "Why did we come here without starting meta scan?"); + nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan; + while (buffer != mFirstBuffer) { + MOZ_ASSERT(buffer, "mFirstBuffer should have acted as sentinel!"); + MOZ_ASSERT(buffer->getStart() == buffer->getEnd(), + "Why wasn't an early buffer fully consumed?"); + auto s = Span(buffer->getBuffer(), buffer->getStart()); + if (!IsAscii(s)) { + return; + } + numAscii += s.Length(); + buffer = buffer->next; + } + auto s = Span(mFirstBuffer->getBuffer(), mFirstBuffer->getStart()); + if (!IsAscii(s)) { + return; + } + numAscii += s.Length(); + + MOZ_ASSERT(!mStartedFeedingDevTools); + // Report the ASCII prefix to dev tools if needed + if (mURIToSendToDevtools) { + buffer = mFirstBufferOfMetaScan; + while (buffer != mFirstBuffer) { + MOZ_ASSERT(buffer, "mFirstBuffer should have acted as sentinel!"); + MOZ_ASSERT(buffer->getStart() == buffer->getEnd(), + "Why wasn't an early buffer fully consumed?"); + auto s = Span(buffer->getBuffer(), buffer->getStart()); + OnNewContent(s); + buffer = buffer->next; + } + auto s = Span(mFirstBuffer->getBuffer(), mFirstBuffer->getStart()); + OnNewContent(s); + } + + // Success! Now let's get rid of the already-decoded but not tokenized data: + mFirstBuffer->setEnd(mFirstBuffer->getStart()); + mLastBuffer = mFirstBuffer; + mFirstBuffer->next = nullptr; + + // Note: We could have scanned further for ASCII, which could avoid some + // buffer deallocation and reallocation. However, chances are that if we got + // until meta without non-ASCII before, there's going to be a title with + // non-ASCII soon after anyway, so let's avoid the complexity of finding out. + + MOZ_ASSERT(mUnicodeDecoder, "How come we scanned meta without a decoder?"); + mEncoding = aEncoding; + mEncoding->NewDecoderWithoutBOMHandlingInto(*mUnicodeDecoder); + mHasHadErrors = false; + + MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing, + "Must have set mDecodingLocalFileWithoutTokenizing to false to " + "report data to dev tools below"); + MOZ_ASSERT(!mLookingForMetaCharset, + "Must have set mLookingForMetaCharset to false to report data to " + "dev tools below"); + + // Now skip over as many bytes and redecode the tail of the + // buffered bytes. + size_t skipped = 0; + for (auto&& buffer : mBufferedBytes) { + size_t nextSkipped = skipped + buffer.Length(); + if (nextSkipped <= numAscii) { + skipped = nextSkipped; + continue; + } + if (skipped >= numAscii) { + WriteStreamBytes(buffer); + skipped = nextSkipped; + continue; + } + size_t tailLength = nextSkipped - numAscii; + WriteStreamBytes(Span<uint8_t>(buffer).From(buffer.Length() - tailLength)); + skipped = nextSkipped; + } +} + +size_t nsHtml5StreamParser::CountGts() { + if (!mGtBuffer) { + return 0; + } + size_t gts = 0; + nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan; + for (;;) { + MOZ_ASSERT(buffer, "How did we walk past mGtBuffer?"); + char16_t* buf = buffer->getBuffer(); + if (buffer == mGtBuffer) { + for (int32_t i = 0; i <= mGtPos; ++i) { + if (buf[i] == u'>') { + ++gts; + } + } + break; + } + for (int32_t i = 0; i < buffer->getEnd(); ++i) { + if (buf[i] == u'>') { + ++gts; + } + } + buffer = buffer->next; + } + return gts; +} + +void nsHtml5StreamParser::DiscardMetaSpeculation() { + mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex); + // Rewind the stream + MOZ_ASSERT(!mAtEOF, "How did we end up setting this?"); + mTokenizer->resetToDataState(); + mTokenizer->setLineNumber(1); + mLastWasCR = false; + + if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) { + // resetToDataState() above logically rewinds to the state before + // the plain text start, so we need to start plain text again to + // put the tokenizer into the plain text state. + mTokenizer->StartPlainText(); + } + + mFirstBuffer = mLastBuffer; + mFirstBuffer->setStart(0); + mFirstBuffer->setEnd(0); + mFirstBuffer->next = nullptr; + + mTreeBuilder->flushCharacters(); // empty the pending buffer + mTreeBuilder->ClearOps(); // now get rid of the failed ops + + if (mMode == VIEW_SOURCE_HTML) { + mTokenizer->RewindViewSource(); + } + + { + // We know that this resets the tree builder back to the start state. + // This must happen _after_ the flushCharacters() call above! + const auto& speculation = mSpeculations.ElementAt(0); + mTreeBuilder->loadState(speculation->GetSnapshot()); + } + + // Experimentation suggests that we don't need to do anything special + // for ignoring the leading LF in View Source here. + + mSpeculations.Clear(); // potentially a huge number of destructors + // run here synchronously... + + // Now set up a new speculation for the main thread to find. + // Note that we stay in the speculating state, because the main thread + // knows how to come out of that state and this thread does not. + + nsHtml5Speculation* speculation = new nsHtml5Speculation( + mFirstBuffer, mFirstBuffer->getStart(), mTokenizer->getLineNumber(), + mTokenizer->getColumnNumber(), mTreeBuilder->newSnapshot()); + MOZ_ASSERT(!mFlushTimerArmed, "How did we end up arming the timer?"); + if (mMode == VIEW_SOURCE_HTML) { + mTokenizer->SetViewSourceOpSink(speculation); + mTokenizer->StartViewSourceCharacters(); + } else { + MOZ_ASSERT(mMode != VIEW_SOURCE_XML); + mTreeBuilder->SetOpSink(speculation); + } + mSpeculations.AppendElement(speculation); // adopts the pointer + MOZ_ASSERT(mSpeculating, "How did we end speculating?"); +} + +/* + * The general idea is to match WebKit and Blink exactly for meta + * scan except: + * + * 1. WebKit and Blink look for meta as if scripting was disabled + * for `noscript` purposes. This implementation matches the + * `noscript` treatment of the observable DOM building (in order + * to be able to use the same tree builder run). + * 2. WebKit and Blink look for meta as if the foreign content + * feedback from the tree builder to the tokenizer didn't exist. + * This implementation considers the foreign content rules in + * order to be able to use the same tree builder run for meta + * and the observable DOM building. Note that since <svg> and + * <math> imply the end of head, this only matters for meta after + * head but starting within the 1024-byte zone. + * + * Template is treated specially, because that WebKit/Blink behavior + * is easy to emulate unlike the above two exceptions. In general, + * the meta scan token handler in WebKit and Blink behaves as if there + * was a scripting-disabled tree builder predating the introduction + * of foreign content and template. + * + * Meta is honored if it _starts_ within the first 1024 kilobytes or, + * if by the 1024-byte boundary head hasn't ended and a template + * element hasn't started, a meta occurs before the first of the head + * ending or a template element starting. + * + * If a meta isn't honored according to the above definition, and + * we aren't dealing with plain text, the buffered bytes, which by + * now have to contain `>` character unless we encountered EOF, are + * scanned for syntax resembling an XML declaration. + * + * If neither a meta nor syntax resembling an XML declaration has + * been honored and we aren't inheriting the encoding from a + * same-origin parent or parsing for XHR, chardetng is used. + * chardetng runs first for the part of the document that was searched + * for meta and then at EOF. The part searched for meta is defined as + * follows in order to avoid network buffer boundary-dependent + * behavior: + * + * 1. At least the first 1024 bytes. (This is what happens for plain + * text.) + * 2. If the 1024-byte boundary is within a tag, comment, doctype, + * or CDATA section, at least up to the end of that token or CDATA + * section. (Exception: If the 1024-byte boundary is in an RCDATA + * end tag that hasn't yet been decided to be an end tag, the + * token is not considered.) + * 3. If at the 1024-byte boundary, head hasn't ended and there hasn't + * been a template tag, up to the end of the first template tag + * or token ending the head, whichever comes first. + * 4. Except if head is ended by a text token, only to the end of the + * most recent tag, comment, or doctype token. (Because text is + * coalesced, so it would be harder to correlate the text to the + * bytes.) + * + * An encoding-related reload is still possible if chardetng's guess + * at EOF differs from its initial guess. + */ +bool nsHtml5StreamParser::ProcessLookingForMetaCharset(bool aEof) { + MOZ_ASSERT(mBomState == BOM_SNIFFING_OVER); + MOZ_ASSERT(mMode != VIEW_SOURCE_XML); + bool rewound = false; + MOZ_ASSERT(mForceAutoDetection || + mCharsetSource < kCharsetFromInitialAutoDetectionASCII || + mCharsetSource == kCharsetFromParentFrame, + "Why are we looking for meta charset if we've seen it?"); + // NOTE! We may come here multiple times with + // mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY + // if the tokenizer suspends multiple times after decoding has reached + // mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY. That's why + // we need to also check whether the we are at the end of the last + // decoded buffer. + // Note that DoDataAvailableBuffer() ensures that the code here has + // the opportunity to run at the exact UNCONDITIONAL_META_SCAN_BOUNDARY + // even if there isn't a network buffer boundary there. + bool atKilobyte = false; + if ((mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY && + mFirstBuffer == mLastBuffer && !mFirstBuffer->hasMore())) { + atKilobyte = true; + mTokenizer->AtKilobyteBoundary(); + } + if (!mNeedsEncodingSwitchTo && + (aEof || (mTemplatePushedOrHeadPopped && + !mTokenizer->IsInTokenStartedAtKilobyteBoundary() && + (atKilobyte || + mNumBytesBuffered > UNCONDITIONAL_META_SCAN_BOUNDARY)))) { + // meta charset was not found + mLookingForMetaCharset = false; + if (mStartsWithLtQuestion && mCharsetSource < kCharsetFromXmlDeclaration) { + // Look for bogo XML declaration. + // Search the first buffer in the hope that '>' is within it. + MOZ_ASSERT(!mBufferedBytes.IsEmpty(), + "How did at least <? not get buffered?"); + Buffer<uint8_t>& first = mBufferedBytes[0]; + const Encoding* encoding = + xmldecl_parse(first.Elements(), first.Length()); + if (!encoding) { + // Our bogo XML declaration scanner wants to see a contiguous buffer, so + // let's linearize the data. (Ideally, the XML declaration scanner would + // be incremental, but this is the rare path anyway.) + Vector<uint8_t> contiguous; + if (!contiguous.append(first.Elements(), first.Length())) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return false; + } + for (size_t i = 1; i < mBufferedBytes.Length(); ++i) { + Buffer<uint8_t>& buffer = mBufferedBytes[i]; + const uint8_t* elements = buffer.Elements(); + size_t length = buffer.Length(); + const uint8_t* lt = (const uint8_t*)memchr(elements, '>', length); + bool stop = false; + if (lt) { + length = (lt - elements) + 1; + stop = true; + } + if (!contiguous.append(elements, length)) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return false; + } + if (stop) { + // Avoid linearizing all buffered bytes unnecessarily. + break; + } + } + encoding = xmldecl_parse(contiguous.begin(), contiguous.length()); + } + if (encoding) { + if (!(mForceAutoDetection && (encoding->IsAsciiCompatible() || + encoding == ISO_2022_JP_ENCODING))) { + mForceAutoDetection = false; + mNeedsEncodingSwitchTo = encoding; + mEncodingSwitchSource = kCharsetFromXmlDeclaration; + } + } + } + // Check again in case we found an encoding in the bogo XML declaration. + if (!mNeedsEncodingSwitchTo && + (mForceAutoDetection || + mCharsetSource < kCharsetFromInitialAutoDetectionASCII) && + !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML) && + !(mDecodingLocalFileWithoutTokenizing && !aEof && + mNumBytesBuffered <= LOCAL_FILE_UTF_8_BUFFER_SIZE)) { + MOZ_ASSERT(!mStartedFeedingDetector); + if (mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY || aEof) { + // We know that all the buffered bytes have been tokenized, so feed + // them all to chardetng. + for (auto&& buffer : mBufferedBytes) { + FeedDetector(buffer); + } + if (aEof) { + MOZ_ASSERT(!mChardetEof); + DetectorEof(); + } + auto [encoding, source] = GuessEncoding(true); + mNeedsEncodingSwitchTo = encoding; + mEncodingSwitchSource = source; + } else if (mNumBytesBuffered > UNCONDITIONAL_META_SCAN_BOUNDARY) { + size_t gtsLeftToFind = CountGts(); + size_t bytesSeen = 0; + // We sync the bytes to the UTF-16 code units seen to avoid depending + // on network buffer boundaries. We do the syncing by counting '>' + // bytes / code units. However, we always scan at least 1024 bytes. + // The 1024-byte boundary is guaranteed to be between buffers. + // The guarantee is implemented in DoDataAvailableBuffer(). + for (auto&& buffer : mBufferedBytes) { + if (!mNeedsEncodingSwitchTo) { + if (gtsLeftToFind) { + auto span = buffer.AsSpan(); + bool feed = true; + for (size_t i = 0; i < span.Length(); ++i) { + if (span[i] == uint8_t('>')) { + --gtsLeftToFind; + if (!gtsLeftToFind) { + if (bytesSeen < UNCONDITIONAL_META_SCAN_BOUNDARY) { + break; + } + ++i; // Skip the gt + FeedDetector(span.To(i)); + auto [encoding, source] = GuessEncoding(true); + mNeedsEncodingSwitchTo = encoding; + mEncodingSwitchSource = source; + FeedDetector(span.From(i)); + bytesSeen += buffer.Length(); + // No need to update bytesSeen anymore, but let's do it for + // debugging. + // We should do `continue outer;` but C++ can't. + feed = false; + break; + } + } + } + if (feed) { + FeedDetector(buffer); + bytesSeen += buffer.Length(); + } + continue; + } + if (bytesSeen == UNCONDITIONAL_META_SCAN_BOUNDARY) { + auto [encoding, source] = GuessEncoding(true); + mNeedsEncodingSwitchTo = encoding; + mEncodingSwitchSource = source; + } + } + FeedDetector(buffer); + bytesSeen += buffer.Length(); + } + } + MOZ_ASSERT(mNeedsEncodingSwitchTo, + "How come we didn't call GuessEncoding()?"); + } + } + if (mNeedsEncodingSwitchTo) { + mDecodingLocalFileWithoutTokenizing = false; + mLookingForMetaCharset = false; + + auto needsEncodingSwitchTo = WrapNotNull(mNeedsEncodingSwitchTo); + mNeedsEncodingSwitchTo = nullptr; + + SwitchDecoderIfAsciiSoFar(needsEncodingSwitchTo); + // The above line may have changed mEncoding so that mEncoding equals + // needsEncodingSwitchTo. + + mCharsetSource = mEncodingSwitchSource; + + if (mMode == VIEW_SOURCE_HTML) { + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return false; + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return false; + } + + if (mEncoding != needsEncodingSwitchTo) { + // Speculation failed + rewound = true; + + if (mEncoding == ISO_2022_JP_ENCODING || + needsEncodingSwitchTo == ISO_2022_JP_ENCODING) { + // Chances are no Web author will fix anything due to this message, so + // this is here to help understanding issues when debugging sites made + // by someone else. + mTreeBuilder->MaybeComplainAboutCharset("EncSpeculationFail2022", false, + mTokenizer->getLineNumber()); + } else { + if (mCharsetSource == kCharsetFromMetaTag) { + mTreeBuilder->MaybeComplainAboutCharset( + "EncSpeculationFailMeta", false, mTokenizer->getLineNumber()); + } else if (mCharsetSource == kCharsetFromXmlDeclaration) { + // This intentionally refers to the line number of how far ahead + // the document was parsed even though the bogo XML decl is always + // on line 1. + mTreeBuilder->MaybeComplainAboutCharset( + "EncSpeculationFailXml", false, mTokenizer->getLineNumber()); + } + } + + DiscardMetaSpeculation(); + // Redecode the stream. + mEncoding = needsEncodingSwitchTo; + mUnicodeDecoder = mEncoding->NewDecoderWithBOMRemoval(); + mHasHadErrors = false; + + MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing, + "Must have set mDecodingLocalFileWithoutTokenizing to false " + "to report data to dev tools below"); + MOZ_ASSERT(!mLookingForMetaCharset, + "Must have set mLookingForMetaCharset to false to report data " + "to dev tools below"); + for (auto&& buffer : mBufferedBytes) { + nsresult rv = WriteStreamBytes(buffer); + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + return false; + } + } + } + } else if (!mLookingForMetaCharset && !mDecodingLocalFileWithoutTokenizing) { + MOZ_ASSERT(!mStartedFeedingDevTools); + // Report all already-decoded buffers to the dev tools if needed. + if (mURIToSendToDevtools) { + nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan; + while (buffer) { + auto s = Span(buffer->getBuffer(), buffer->getEnd()); + OnNewContent(s); + buffer = buffer->next; + } + } + } + if (!mLookingForMetaCharset) { + mGtBuffer = nullptr; + mGtPos = 0; + + if (!mDecodingLocalFileWithoutTokenizing) { + mFirstBufferOfMetaScan = nullptr; + mBufferingBytes = false; + mBufferedBytes.Clear(); + mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, true); + if (mMode == VIEW_SOURCE_HTML) { + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return false; + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return false; + } + } + } + return rewound; +} + +void nsHtml5StreamParser::ParseAvailableData() { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mTokenizerMutex.AssertCurrentThreadOwns(); + MOZ_ASSERT(!(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset)); + + if (IsTerminatedOrInterrupted()) { + return; + } + + if (mSpeculating && !IsSpeculationEnabled()) { + return; + } + + bool requestedReload = false; + for (;;) { + if (!mFirstBuffer->hasMore()) { + if (mFirstBuffer == mLastBuffer) { + switch (mStreamState) { + case STREAM_BEING_READ: + // never release the last buffer. + if (!mSpeculating) { + // reuse buffer space if not speculating + mFirstBuffer->setStart(0); + mFirstBuffer->setEnd(0); + } + return; // no more data for now but expecting more + case STREAM_ENDED: + if (mAtEOF) { + return; + } + if (mLookingForMetaCharset) { + // When called with aEof=true, ProcessLookingForMetaCharset() + // is guaranteed to set mLookingForMetaCharset to false so + // that we can't come here twice. + if (ProcessLookingForMetaCharset(true)) { + if (IsTerminatedOrInterrupted()) { + return; + } + continue; + } + } else if ((mForceAutoDetection || + mCharsetSource < kCharsetFromParentFrame) && + !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML) && + !mReparseForbidden) { + // An earlier DetectorEof() call is possible in which case + // the one here is a no-op. + DetectorEof(); + auto [encoding, source] = GuessEncoding(false); + if (encoding != mEncoding) { + // Request a reload from the docshell. + MOZ_ASSERT( + (source >= + kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && + source <= + kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || + source == kCharsetFromFinalUserForcedAutoDetection); + mTreeBuilder->NeedsCharsetSwitchTo(encoding, source, 0); + requestedReload = true; + } else if (mCharsetSource == + kCharsetFromInitialAutoDetectionASCII && + mDetectorHasSeenNonAscii) { + mCharsetSource = source; + mTreeBuilder->UpdateCharsetSource(mCharsetSource); + } + } + + mAtEOF = true; + if (!mForceAutoDetection && !requestedReload) { + if (mCharsetSource == kCharsetFromParentFrame) { + mTreeBuilder->MaybeComplainAboutCharset("EncNoDeclarationFrame", + false, 0); + } else if (mCharsetSource == kCharsetFromXmlDeclaration) { + // We know the bogo XML decl is always on the first line. + mTreeBuilder->MaybeComplainAboutCharset("EncXmlDecl", false, 1); + } else if ( + mCharsetSource >= + kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8 && + mCharsetSource <= + kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD) { + if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) { + mTreeBuilder->MaybeComplainAboutCharset("EncNoDeclPlain", + true, 0); + } else { + mTreeBuilder->MaybeComplainAboutCharset("EncNoDecl", true, 0); + } + } + + if (mHasHadErrors && mEncoding != REPLACEMENT_ENCODING) { + if (mEncoding == UTF_8_ENCODING) { + mTreeBuilder->TryToEnableEncodingMenu(); + } + if (mCharsetSource == kCharsetFromParentFrame) { + if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) { + mTreeBuilder->MaybeComplainAboutCharset( + "EncErrorFramePlain", true, 0); + } else { + mTreeBuilder->MaybeComplainAboutCharset("EncErrorFrame", + true, 0); + } + } else if ( + mCharsetSource >= kCharsetFromXmlDeclaration && + !(mCharsetSource >= + kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && + mCharsetSource <= + kCharsetFromFinalUserForcedAutoDetection)) { + mTreeBuilder->MaybeComplainAboutCharset("EncError", true, 0); + } + } + } + if (NS_SUCCEEDED(mTreeBuilder->IsBroken())) { + mTokenizer->eof(); + nsresult rv; + if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) { + MarkAsBroken(rv); + } else { + mTreeBuilder->StreamEnded(); + if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) { + if (!mTokenizer->EndViewSource()) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + } + } + } + FlushTreeOpsAndDisarmTimer(); + return; // no more data and not expecting more + default: + MOZ_ASSERT_UNREACHABLE("It should be impossible to reach this."); + return; + } + } + mFirstBuffer = mFirstBuffer->next; + continue; + } + + // now we have a non-empty buffer + mFirstBuffer->adjust(mLastWasCR); + mLastWasCR = false; + if (mFirstBuffer->hasMore()) { + if (!mTokenizer->EnsureBufferSpace(mFirstBuffer->getLength())) { + MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer); + nsresult rv; + if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) { + MarkAsBroken(rv); + return; + } + if (mTreeBuilder->HasScript()) { + // HasScript() cannot return true if the tree builder is preventing + // script execution. + MOZ_ASSERT(mMode == NORMAL); + mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex); + nsHtml5Speculation* speculation = new nsHtml5Speculation( + mFirstBuffer, mFirstBuffer->getStart(), mTokenizer->getLineNumber(), + mTokenizer->getColumnNumber(), mTreeBuilder->newSnapshot()); + mTreeBuilder->AddSnapshotToScript(speculation->GetSnapshot(), + speculation->GetStartLineNumber()); + if (mLookingForMetaCharset) { + if (mMode == VIEW_SOURCE_HTML) { + auto r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return; + } + } + auto r = mTreeBuilder->Flush(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return; + } + } else { + FlushTreeOpsAndDisarmTimer(); + } + mTreeBuilder->SetOpSink(speculation); + mSpeculations.AppendElement(speculation); // adopts the pointer + mSpeculating = true; + } + if (IsTerminatedOrInterrupted()) { + return; + } + } + if (mLookingForMetaCharset) { + Unused << ProcessLookingForMetaCharset(false); + } + } +} + +class nsHtml5StreamParserContinuation : public Runnable { + private: + nsHtml5StreamParserPtr mStreamParser; + + public: + explicit nsHtml5StreamParserContinuation(nsHtml5StreamParser* aStreamParser) + : Runnable("nsHtml5StreamParserContinuation"), + mStreamParser(aStreamParser) {} + NS_IMETHOD Run() override { + mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex); + mStreamParser->Uninterrupt(); + mStreamParser->ParseAvailableData(); + return NS_OK; + } +}; + +void nsHtml5StreamParser::ContinueAfterScriptsOrEncodingCommitment( + nsHtml5Tokenizer* aTokenizer, nsHtml5TreeBuilder* aTreeBuilder, + bool aLastWasCR) { + // nullptr for aTokenizer means encoding commitment as opposed to the "after + // scripts" case. + + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + MOZ_ASSERT(mMode != VIEW_SOURCE_XML, + "ContinueAfterScriptsOrEncodingCommitment called in XML view " + "source mode!"); + MOZ_ASSERT(!(aTokenizer && mMode == VIEW_SOURCE_HTML), + "ContinueAfterScriptsOrEncodingCommitment called with non-null " + "tokenizer in HTML view " + "source mode."); + if (NS_FAILED(mExecutor->IsBroken())) { + return; + } + MOZ_ASSERT(!(aTokenizer && mMode != NORMAL), + "We should only be executing scripts in the normal mode."); + if (!aTokenizer && (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN || + mMode == VIEW_SOURCE_HTML)) { + // Take the ops that were generated from OnStartRequest for the synthetic + // head section of the document for plain text and HTML View Source. + // XML View Source never needs this kind of encoding commitment. + // We need to take the ops here so that they end up in the queue before + // the ops that we take from a speculation later in this method. + if (!mExecutor->TakeOpsFromStage()) { + mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + } else { +#ifdef DEBUG + mExecutor->AssertStageEmpty(); +#endif + } + bool speculationFailed = false; + { + mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex); + if (mSpeculations.IsEmpty()) { + MOZ_ASSERT_UNREACHABLE( + "ContinueAfterScriptsOrEncodingCommitment called without " + "speculations."); + return; + } + + const auto& speculation = mSpeculations.ElementAt(0); + if (aTokenizer && + (aLastWasCR || !aTokenizer->isInDataState() || + !aTreeBuilder->snapshotMatches(speculation->GetSnapshot()))) { + speculationFailed = true; + // We've got a failed speculation :-( + MaybeDisableFutureSpeculation(); + Interrupt(); // Make the parser thread release the tokenizer mutex sooner + // Note that the interrupted state continues across possible intervening + // Necko events until the nsHtml5StreamParserContinuation posted at the + // end of this method runs. Therefore, this thread is guaranteed to + // acquire mTokenizerMutex soon even if an intervening Necko event grabbed + // it between now and the acquisition below. + + // now fall out of the speculationAutoLock into the tokenizerAutoLock + // block + } else { + // We've got a successful speculation! + if (mSpeculations.Length() > 1) { + // the first speculation isn't the current speculation, so there's + // no need to bother the parser thread. + if (!speculation->FlushToSink(mExecutor)) { + mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + MOZ_ASSERT(!mExecutor->IsScriptExecuting(), + "ParseUntilBlocked() was supposed to ensure we don't come " + "here when scripts are executing."); + MOZ_ASSERT(!aTokenizer || mExecutor->IsInFlushLoop(), + "How are we here if " + "RunFlushLoop() didn't call ParseUntilBlocked() or we're " + "not committing to an encoding?"); + mSpeculations.RemoveElementAt(0); + return; + } + // else + Interrupt(); // Make the parser thread release the tokenizer mutex sooner + // Note that the interrupted state continues across possible intervening + // Necko events until the nsHtml5StreamParserContinuation posted at the + // end of this method runs. Therefore, this thread is guaranteed to + // acquire mTokenizerMutex soon even if an intervening Necko event grabbed + // it between now and the acquisition below. + + // now fall through + // the first speculation is the current speculation. Need to + // release the the speculation mutex and acquire the tokenizer + // mutex. (Just acquiring the other mutex here would deadlock) + } + } + { + mozilla::MutexAutoLock tokenizerAutoLock(mTokenizerMutex); +#ifdef DEBUG + { + mAtomTable.SetPermittedLookupEventTarget( + GetMainThreadSerialEventTarget()); + } +#endif + // In principle, the speculation mutex should be acquired here, + // but there's no point, because the parser thread only acquires it + // when it has also acquired the tokenizer mutex and we are already + // holding the tokenizer mutex. + if (speculationFailed) { + MOZ_ASSERT(mMode == NORMAL); + // Rewind the stream + mAtEOF = false; + const auto& speculation = mSpeculations.ElementAt(0); + mFirstBuffer = speculation->GetBuffer(); + mFirstBuffer->setStart(speculation->GetStart()); + mTokenizer->setLineNumber(speculation->GetStartLineNumber()); + mTokenizer->setColumnNumberAndResetNextLine( + speculation->GetStartColumnNumber()); + + nsContentUtils::ReportToConsole( + nsIScriptError::warningFlag, "DOM Events"_ns, + mExecutor->GetDocument(), nsContentUtils::eDOM_PROPERTIES, + "SpeculationFailed2", nsTArray<nsString>(), nullptr, u""_ns, + speculation->GetStartLineNumber(), + speculation->GetStartColumnNumber()); + + nsHtml5OwningUTF16Buffer* buffer = mFirstBuffer->next; + while (buffer) { + buffer->setStart(0); + buffer = buffer->next; + } + + mSpeculations.Clear(); // potentially a huge number of destructors + // run here synchronously on the main thread... + + mTreeBuilder->flushCharacters(); // empty the pending buffer + mTreeBuilder->ClearOps(); // now get rid of the failed ops + + mTreeBuilder->SetOpSink(mExecutor->GetStage()); + mExecutor->StartReadingFromStage(); + mSpeculating = false; + + // Copy state over + mLastWasCR = aLastWasCR; + mTokenizer->loadState(aTokenizer); + mTreeBuilder->loadState(aTreeBuilder); + } else { + // We've got a successful speculation and at least a moment ago it was + // the current speculation + if (!mSpeculations.ElementAt(0)->FlushToSink(mExecutor)) { + mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + return; + } + MOZ_ASSERT(!mExecutor->IsScriptExecuting(), + "ParseUntilBlocked() was supposed to ensure we don't come " + "here when scripts are executing."); + MOZ_ASSERT(!aTokenizer || mExecutor->IsInFlushLoop(), + "How are we here if " + "RunFlushLoop() didn't call ParseUntilBlocked() or we're not " + "committing to an encoding?"); + mSpeculations.RemoveElementAt(0); + if (mSpeculations.IsEmpty()) { + if (mMode == VIEW_SOURCE_HTML) { + // If we looked for meta charset in the HTML View Source case. + mTokenizer->SetViewSourceOpSink(mExecutor->GetStage()); + } else { + // yes, it was still the only speculation. Now stop speculating + // However, before telling the executor to read from stage, flush + // any pending ops straight to the executor, because otherwise + // they remain unflushed until we get more data from the network. + mTreeBuilder->SetOpSink(mExecutor); + auto r = mTreeBuilder->Flush(true); + if (r.isErr()) { + mExecutor->MarkAsBroken(r.unwrapErr()); + return; + } + mTreeBuilder->SetOpSink(mExecutor->GetStage()); + } + mExecutor->StartReadingFromStage(); + mSpeculating = false; + } + } + nsCOMPtr<nsIRunnable> event = new nsHtml5StreamParserContinuation(this); + if (NS_FAILED(mEventTarget->Dispatch(event, nsIThread::DISPATCH_NORMAL))) { + NS_WARNING("Failed to dispatch nsHtml5StreamParserContinuation"); + } +// A stream event might run before this event runs, but that's harmless. +#ifdef DEBUG + mAtomTable.SetPermittedLookupEventTarget(mEventTarget); +#endif + } +} + +void nsHtml5StreamParser::ContinueAfterFailedCharsetSwitch() { + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + nsCOMPtr<nsIRunnable> event = new nsHtml5StreamParserContinuation(this); + if (NS_FAILED(mEventTarget->Dispatch(event, nsIThread::DISPATCH_NORMAL))) { + NS_WARNING("Failed to dispatch nsHtml5StreamParserContinuation"); + } +} + +class nsHtml5TimerKungFu : public Runnable { + private: + nsHtml5StreamParserPtr mStreamParser; + + public: + explicit nsHtml5TimerKungFu(nsHtml5StreamParser* aStreamParser) + : Runnable("nsHtml5TimerKungFu"), mStreamParser(aStreamParser) {} + NS_IMETHOD Run() override { + mozilla::MutexAutoLock flushTimerLock(mStreamParser->mFlushTimerMutex); + if (mStreamParser->mFlushTimer) { + mStreamParser->mFlushTimer->Cancel(); + mStreamParser->mFlushTimer = nullptr; + } + return NS_OK; + } +}; + +void nsHtml5StreamParser::DropTimer() { + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + /* + * Simply nulling out the timer wouldn't work, because if the timer is + * armed, it needs to be canceled first. Simply canceling it first wouldn't + * work, because nsTimerImpl::Cancel is not safe for calling from outside + * the thread where nsTimerImpl::Fire would run. It's not safe to + * dispatch a runnable to cancel the timer from the destructor of this + * class, because the timer has a weak (void*) pointer back to this instance + * of the stream parser and having the timer fire before the runnable + * cancels it would make the timer access a deleted object. + * + * This DropTimer method addresses these issues. This method must be called + * on the main thread before the destructor of this class is reached. + * The nsHtml5TimerKungFu object has an nsHtml5StreamParserPtr that addrefs + * this + * stream parser object to keep it alive until the runnable is done. + * The runnable cancels the timer on the parser thread, drops the timer + * and lets nsHtml5StreamParserPtr send a runnable back to the main thread to + * release the stream parser. + */ + mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex); + if (mFlushTimer) { + nsCOMPtr<nsIRunnable> event = new nsHtml5TimerKungFu(this); + if (NS_FAILED(mEventTarget->Dispatch(event, nsIThread::DISPATCH_NORMAL))) { + NS_WARNING("Failed to dispatch TimerKungFu event"); + } + } +} + +// Using a static, because the method name Notify is taken by the chardet +// callback. +void nsHtml5StreamParser::TimerCallback(nsITimer* aTimer, void* aClosure) { + (static_cast<nsHtml5StreamParser*>(aClosure))->TimerFlush(); +} + +void nsHtml5StreamParser::TimerFlush() { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mozilla::MutexAutoLock autoLock(mTokenizerMutex); + + MOZ_ASSERT(!mSpeculating, "Flush timer fired while speculating."); + + // The timer fired if we got here. No need to cancel it. Mark it as + // not armed, though. + mFlushTimerArmed = false; + + mFlushTimerEverFired = true; + + if (IsTerminatedOrInterrupted()) { + return; + } + + if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) { + auto r = mTreeBuilder->Flush(); // delete useless ops + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return; + } + r = mTokenizer->FlushViewSource(); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return; + } + if (r.unwrap()) { + nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher); + if (NS_FAILED(DispatchToMain(runnable.forget()))) { + NS_WARNING("failed to dispatch executor flush event"); + } + } + } else { + // we aren't speculating and we don't know when new data is + // going to arrive. Send data to the main thread. + auto r = mTreeBuilder->Flush(true); + if (r.isErr()) { + MarkAsBroken(r.unwrapErr()); + return; + } + if (r.unwrap()) { + nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher); + if (NS_FAILED(DispatchToMain(runnable.forget()))) { + NS_WARNING("failed to dispatch executor flush event"); + } + } + } +} + +void nsHtml5StreamParser::MarkAsBroken(nsresult aRv) { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mTokenizerMutex.AssertCurrentThreadOwns(); + + Terminate(); + mTreeBuilder->MarkAsBroken(aRv); + auto r = mTreeBuilder->Flush(false); + if (r.isOk()) { + MOZ_ASSERT(r.unwrap(), "Should have had the markAsBroken op!"); + } else { + MOZ_CRASH("OOM prevents propagation of OOM state"); + } + nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher); + if (NS_FAILED(DispatchToMain(runnable.forget()))) { + NS_WARNING("failed to dispatch executor flush event"); + } +} + +nsresult nsHtml5StreamParser::DispatchToMain( + already_AddRefed<nsIRunnable>&& aRunnable) { + if (mNetworkEventTarget) { + return mNetworkEventTarget->Dispatch(std::move(aRunnable)); + } + return SchedulerGroup::UnlabeledDispatch(TaskCategory::Network, + std::move(aRunnable)); +} diff --git a/parser/html/nsHtml5StreamParser.h b/parser/html/nsHtml5StreamParser.h new file mode 100644 index 0000000000..0dacf257bf --- /dev/null +++ b/parser/html/nsHtml5StreamParser.h @@ -0,0 +1,766 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef nsHtml5StreamParser_h +#define nsHtml5StreamParser_h + +#include <tuple> + +#include "MainThreadUtils.h" +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Assertions.h" +#include "mozilla/Encoding.h" +#include "mozilla/Mutex.h" +#include "mozilla/NotNull.h" +#include "mozilla/RefPtr.h" +#include "mozilla/Span.h" +#include "mozilla/UniquePtr.h" +#include "nsCharsetSource.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsDebug.h" +#include "nsHtml5AtomTable.h" +#include "nsIRequestObserver.h" +#include "nsISerialEventTarget.h" +#include "nsISupports.h" +#include "nsStringFwd.h" +#include "nsTArray.h" +#include "nscore.h" + +class nsCycleCollectionTraversalCallback; +class nsHtml5OwningUTF16Buffer; +class nsHtml5Parser; +class nsHtml5Speculation; +class nsHtml5String; +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5TreeOpExecutor; +class nsIChannel; +class nsIInputStream; +class nsIRequest; +class nsIRunnable; +class nsITimer; +class nsIURI; + +namespace mozilla { +class EncodingDetector; +template <typename T> +class Buffer; + +namespace dom { +class DocGroup; +} +} // namespace mozilla + +enum eParserMode { + /** + * Parse a document normally as HTML. + */ + NORMAL, + + /** + * View document as HTML source. + */ + VIEW_SOURCE_HTML, + + /** + * View document as XML source + */ + VIEW_SOURCE_XML, + + /** + * View document as plain text source + */ + VIEW_SOURCE_PLAIN, + + /** + * View document as plain text + */ + PLAIN_TEXT, + + /** + * Load as data (XHR) + */ + LOAD_AS_DATA +}; + +enum eBomState { + /** + * BOM sniffing hasn't started. + */ + BOM_SNIFFING_NOT_STARTED, + + /** + * BOM sniffing is ongoing, and the first byte of an UTF-16LE BOM has been + * seen. + */ + SEEN_UTF_16_LE_FIRST_BYTE, + + /** + * BOM sniffing is ongoing, and the first byte of an UTF-16BE BOM has been + * seen. + */ + SEEN_UTF_16_BE_FIRST_BYTE, + + /** + * BOM sniffing is ongoing, and the first byte of an UTF-8 BOM has been + * seen. + */ + SEEN_UTF_8_FIRST_BYTE, + + /** + * BOM sniffing is ongoing, and the first and second bytes of an UTF-8 BOM + * have been seen. + */ + SEEN_UTF_8_SECOND_BYTE, + + /** + * Seen \x00 in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_BE_XML_FIRST, + + /** + * Seen \x00< in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_BE_XML_SECOND, + + /** + * Seen \x00<\x00 in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_BE_XML_THIRD, + + /** + * Seen \x00<\x00? in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_BE_XML_FOURTH, + + /** + * Seen \x00<\x00?\x00 in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_BE_XML_FIFTH, + + /** + * Seen < in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_LE_XML_FIRST, + + /** + * Seen <\x00 in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_LE_XML_SECOND, + + /** + * Seen <\x00? in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_LE_XML_THIRD, + + /** + * Seen <\x00?\x00 in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_LE_XML_FOURTH, + + /** + * Seen <\x00?\x00x in UTF-16BE bogo-XML declaration. + */ + SEEN_UTF_16_LE_XML_FIFTH, + + /** + * BOM sniffing was started but is now over for whatever reason. + */ + BOM_SNIFFING_OVER, +}; + +enum eHtml5StreamState { + STREAM_NOT_STARTED = 0, + STREAM_BEING_READ = 1, + STREAM_ENDED = 2 +}; + +class nsHtml5StreamParser final : public nsISupports { + template <typename T> + using NotNull = mozilla::NotNull<T>; + using Encoding = mozilla::Encoding; + + const uint32_t UNCONDITIONAL_META_SCAN_BOUNDARY = 1024; + const uint32_t READ_BUFFER_SIZE = 1024; + const uint32_t LOCAL_FILE_UTF_8_BUFFER_SIZE = 1024 * 1024 * 4; // 4 MB + + friend class nsHtml5RequestStopper; + friend class nsHtml5DataAvailable; + friend class nsHtml5StreamParserContinuation; + friend class nsHtml5TimerKungFu; + friend class nsHtml5StreamParserPtr; + friend class nsHtml5StreamListener; + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(nsHtml5StreamParser) + + nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor, nsHtml5Parser* aOwner, + eParserMode aMode); + + nsresult OnStartRequest(nsIRequest* aRequest); + + nsresult OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInStream, + uint64_t aSourceOffset, uint32_t aLength); + + nsresult OnStopRequest(nsIRequest* aRequest, nsresult status); + + // EncodingDeclarationHandler + // https://hg.mozilla.org/projects/htmlparser/file/tip/src/nu/validator/htmlparser/common/EncodingDeclarationHandler.java + /** + * Tree builder uses this to report a late <meta charset> + */ + bool internalEncodingDeclaration(nsHtml5String aEncoding); + + bool TemplatePushedOrHeadPopped(); + + void RememberGt(int32_t aPos); + + // Not from an external interface + + /** + * Post a runnable to the main thread to perform the speculative load + * operations without performing the tree operations. + * + * This should be called at the end of each data available or stop + * request runnable running on the parser thread. + */ + void PostLoadFlusher(); + + /** + * Pass a buffer to chardetng. + */ + void FeedDetector(mozilla::Span<const uint8_t> aBuffer); + + /** + * Report EOF to chardetng. + */ + void DetectorEof(); + + /** + * Call this method once you've created a parser, and want to instruct it + * about what charset to load + * + * @param aEncoding the charset of a document + * @param aCharsetSource the source of the charset + */ + inline void SetDocumentCharset(NotNull<const Encoding*> aEncoding, + nsCharsetSource aSource, + bool aForceAutoDetection) { + MOZ_ASSERT(mStreamState == STREAM_NOT_STARTED, + "SetDocumentCharset called too late."); + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + MOZ_ASSERT(!(aForceAutoDetection && aSource >= kCharsetFromOtherComponent), + "Can't force with high-ranking source."); + mEncoding = aEncoding; + mCharsetSource = aSource; + mForceAutoDetection = aForceAutoDetection; + mChannelHadCharset = (aSource == kCharsetFromChannel); + } + + nsresult GetChannel(nsIChannel** aChannel); + + /** + * The owner parser must call this after script execution + * when no scripts are executing and the document.written + * buffer has been exhausted. + * + * If the first two arguments are nullptr, instead of + * continuing after scripts, this method commits to an + * internally-discovered encoding. + */ + void ContinueAfterScriptsOrEncodingCommitment( + nsHtml5Tokenizer* aTokenizer, nsHtml5TreeBuilder* aTreeBuilder, + bool aLastWasCR); + + /** + * Continues the stream parser if the charset switch failed. + */ + void ContinueAfterFailedCharsetSwitch(); + + void Terminate() { mTerminated = true; } + + void DropTimer(); + + /** + * Sets the URL for View Source title in case this parser ends up being + * used for View Source. If aURL is a view-source: URL, takes the inner + * URL. data: URLs are shown with an ellipsis instead of the actual data. + */ + void SetViewSourceTitle(nsIURI* aURL); + + private: + virtual ~nsHtml5StreamParser(); + +#ifdef DEBUG + bool IsParserThread() { return mEventTarget->IsOnCurrentThread(); } +#endif + + void MarkAsBroken(nsresult aRv); + + /** + * Marks the stream parser as interrupted. If you ever add calls to this + * method, be sure to review Uninterrupt usage very, very carefully to + * avoid having a previous in-flight runnable cancel your Interrupt() + * call on the other thread too soon. + */ + void Interrupt() { + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + mInterrupted = true; + } + + void Uninterrupt() MOZ_NO_THREAD_SAFETY_ANALYSIS { + MOZ_ASSERT(IsParserThread(), "Wrong thread!"); + mTokenizerMutex.AssertCurrentThreadOwns(); + mInterrupted = false; + } + + /** + * Flushes the tree ops from the tree builder and disarms the flush + * timer. + */ + void FlushTreeOpsAndDisarmTimer(); + + void SwitchDecoderIfAsciiSoFar(NotNull<const Encoding*> aEncoding) + MOZ_REQUIRES(mTokenizerMutex); + ; + + size_t CountGts(); + + void DiscardMetaSpeculation(); + + bool ProcessLookingForMetaCharset(bool aEof) MOZ_REQUIRES(mTokenizerMutex); + + void ParseAvailableData(); + + void DoStopRequest(); + + void DoDataAvailableBuffer(mozilla::Buffer<uint8_t>&& aBuffer) + MOZ_REQUIRES(mTokenizerMutex); + + void DoDataAvailable(mozilla::Span<const uint8_t> aBuffer) + MOZ_REQUIRES(mTokenizerMutex); + + static nsresult CopySegmentsToParser(nsIInputStream* aInStream, + void* aClosure, const char* aFromSegment, + uint32_t aToOffset, uint32_t aCount, + uint32_t* aWriteCount) + MOZ_REQUIRES(mTokenizerMutex); + + bool IsTerminatedOrInterrupted() { return mTerminated || mInterrupted; } + + bool IsTerminated() { return mTerminated; } + + /** + * True when there is a Unicode decoder already + */ + inline bool HasDecoder() { return !!mUnicodeDecoder; } + + /** + * Returns 0 if 1) there aren't at least 2 buffers in mBufferedBytes + * or 2) there is no byte '>' in the second buffer. + * Otherwise, returns the length of the prefix of the second buffer + * that is long enough to contain the first byte '>' in the second + * buffer (including the '>' byte). + */ + size_t LengthOfLtContainingPrefixInSecondBuffer(); + + /** + * Push bytes from network when there is no Unicode decoder yet + */ + nsresult SniffStreamBytes(mozilla::Span<const uint8_t> aFromSegment, + bool aEof) MOZ_REQUIRES(mTokenizerMutex); + + /** + * Push bytes from network when there is a Unicode decoder already + */ + nsresult WriteStreamBytes(mozilla::Span<const uint8_t> aFromSegment) + MOZ_REQUIRES(mTokenizerMutex); + + /** + * Set up the Unicode decoder and write the sniffing buffer into it + * followed by the current network buffer. + * + * @param aPrefix the part of the stream that has already been seen + * prior to aFromSegment. In practice, these are the + * bytes that are baked into the state of the BOM + * and UTF-16 XML declaration-like sniffing state + * machine state. + * @param aFromSegment The current network buffer + */ + nsresult SetupDecodingAndWriteSniffingBufferAndCurrentSegment( + mozilla::Span<const uint8_t> aPrefix, + mozilla::Span<const uint8_t> aFromSegment) MOZ_REQUIRES(mTokenizerMutex); + + /** + * Initialize the Unicode decoder, mark the BOM as the source and + * drop the sniffer. + * + * @param aDecoderCharsetName The name for the decoder's charset + * (UTF-16BE, UTF-16LE or UTF-8; the BOM has + * been swallowed) + */ + void SetupDecodingFromBom(NotNull<const Encoding*> aEncoding); + + void SetupDecodingFromUtf16BogoXml(NotNull<const Encoding*> aEncoding); + + /** + * When speculatively decoding from file: URL as UTF-8, commit + * to UTF-8 as the non-speculative encoding and start processing + * the decoded data. + */ + [[nodiscard]] nsresult CommitLocalFileToEncoding(); + + /** + * When speculatively decoding from file: URL as UTF-8, redecode + * using fallback and then continue normally with the fallback. + */ + [[nodiscard]] nsresult ReDecodeLocalFile() MOZ_REQUIRES(mTokenizerMutex); + + /** + * Potentially guess the encoding using mozilla::EncodingDetector. + * Returns the guessed encoding and a telemetry-appropriate source. + */ + std::tuple<NotNull<const Encoding*>, nsCharsetSource> GuessEncoding( + bool aInitial); + + /** + * Become confident or resolve and encoding name to its preferred form. + * @param aEncoding the value of an internal encoding decl. Acts as an + * out param, too, when the method returns true. + * @return true if the parser needs to start using the new value of + * aEncoding and false if the parser became confident or if + * the encoding name did not specify a usable encoding + */ + const Encoding* PreferredForInternalEncodingDecl(const nsAString& aEncoding); + + /** + * Callback for mFlushTimer. + */ + static void TimerCallback(nsITimer* aTimer, void* aClosure); + + /** + * Parser thread entry point for (maybe) flushing the ops and posting + * a flush runnable back on the main thread. + */ + void TimerFlush(); + + /** + * Called when speculation fails. + */ + void MaybeDisableFutureSpeculation() { mSpeculationFailureCount++; } + + /** + * Used to check whether we're getting too many speculation failures and + * should just stop trying. The 100 is picked pretty randomly to be not too + * small (so most pages are not affected) but small enough that we don't end + * up with failed speculations over and over in pathological cases. + */ + bool IsSpeculationEnabled() { return mSpeculationFailureCount < 100; } + + /** + * Dispatch an event to a Quantum DOM main thread-ish thread. + * (Not the parser thread.) + */ + nsresult DispatchToMain(already_AddRefed<nsIRunnable>&& aRunnable); + + /** + * Notify any devtools listeners about content newly received for parsing. + */ + inline void OnNewContent(mozilla::Span<const char16_t> aData); + + /** + * Notify any devtools listeners after all parse content has been received. + */ + inline void OnContentComplete(); + + nsCOMPtr<nsIRequest> mRequest; + + /** + * The document title to use if this turns out to be a View Source parser. + */ + nsCString mViewSourceTitle; + + /** + * The Unicode decoder + */ + mozilla::UniquePtr<mozilla::Decoder> mUnicodeDecoder; + + /** + * BOM sniffing state + */ + eBomState mBomState; + + // encoding-related stuff + /** + * The source (confidence) of the character encoding in use + */ + nsCharsetSource mCharsetSource; + + nsCharsetSource mEncodingSwitchSource; + + /** + * The character encoding in use + */ + NotNull<const Encoding*> mEncoding; + + const Encoding* mNeedsEncodingSwitchTo; + + bool mSeenEligibleMetaCharset; + + bool mChardetEof; + +#ifdef DEBUG + + bool mStartedFeedingDetector; + + bool mStartedFeedingDevTools; + +#endif + + /** + * Whether reparse is forbidden + */ + bool mReparseForbidden; + + /** + * Whether the Repair Text Encoding menu item was invoked + */ + bool mForceAutoDetection; + + /** + * Whether there was a valid charset parameter on the HTTP layer. + */ + bool mChannelHadCharset; + + /** + * We are in the process of looking for <meta charset> + */ + bool mLookingForMetaCharset; + + /** + * Whether the byte stream started with ASCII <? + */ + bool mStartsWithLtQuestion; + + /** + * If we are viewing XML source and are waiting for a '>' form the network. + */ + bool mLookingForXmlDeclarationForXmlViewSource; + + /** + * Whether template has been pushed or head popped within the first 1024 + * bytes. + */ + bool mTemplatePushedOrHeadPopped; + + // Portable parser objects + /** + * The first buffer in the pending UTF-16 buffer queue + */ + RefPtr<nsHtml5OwningUTF16Buffer> mFirstBuffer; + + /** + * Non-owning pointer to the most recent buffer that contains the most recent + * remembered greater-than sign. Used only while mLookingForMetaCharset is + * true. While mLookingForMetaCharset is true, mFirstBuffer is not changed and + * keeps the whole linked list of buffers alive. This pointer is non-owning to + * avoid frequent refcounting. + */ + nsHtml5OwningUTF16Buffer* mGtBuffer; + + int32_t mGtPos; + + /** + * The last buffer in the pending UTF-16 buffer queue + */ + nsHtml5OwningUTF16Buffer* + mLastBuffer; // weak ref; always points to + // a buffer of the size + // NS_HTML5_STREAM_PARSER_READ_BUFFER_SIZE + + /** + * The first buffer of the document if looking for <meta charset> or + * nullptr afterwards. + */ + RefPtr<nsHtml5OwningUTF16Buffer> mFirstBufferOfMetaScan; + + /** + * The tree operation executor + */ + nsHtml5TreeOpExecutor* mExecutor; + + /** + * Network event target for mExecutor->mDocument + */ + nsCOMPtr<nsISerialEventTarget> mNetworkEventTarget; + + /** + * The HTML5 tree builder + */ + mozilla::UniquePtr<nsHtml5TreeBuilder> mTreeBuilder; + + /** + * The HTML5 tokenizer + */ + mozilla::UniquePtr<nsHtml5Tokenizer> mTokenizer; + + /** + * Makes sure the main thread can't mess the tokenizer state while it's + * tokenizing. This mutex also protects the current speculation. + */ + mozilla::Mutex mTokenizerMutex; + + /** + * The scoped atom table + */ + nsHtml5AtomTable mAtomTable; + + /** + * The owner parser. + */ + RefPtr<nsHtml5Parser> mOwner; + + /** + * Whether the last character tokenized was a carriage return (for CRLF) + */ + bool mLastWasCR; + + /** + * For tracking stream life cycle + */ + eHtml5StreamState mStreamState; + + /** + * Whether we are speculating. + */ + bool mSpeculating; + + /** + * Whether the tokenizer has reached EOF. (Reset when stream rewinded.) + */ + bool mAtEOF; + + /** + * The speculations. The mutex protects the nsTArray itself. + * To access the queue of current speculation, mTokenizerMutex must be + * obtained. + * The current speculation is the last element + */ + nsTArray<mozilla::UniquePtr<nsHtml5Speculation>> mSpeculations; + mozilla::Mutex mSpeculationMutex; + + /** + * Number of times speculation has failed for this parser. + */ + mozilla::Atomic<uint32_t> mSpeculationFailureCount; + + /** + * Number of bytes already buffered into mBufferedBytes. + */ + uint32_t mNumBytesBuffered; + + nsTArray<mozilla::Buffer<uint8_t>> mBufferedBytes; + + /** + * True to terminate early. + */ + mozilla::Atomic<bool> mTerminated; + + /** + * True to release mTokenizerMutex early. + */ + mozilla::Atomic<bool> mInterrupted; + + /** + * The thread this stream parser runs on. + */ + nsCOMPtr<nsISerialEventTarget> mEventTarget; + + nsCOMPtr<nsIRunnable> mExecutorFlusher; + + nsCOMPtr<nsIRunnable> mLoadFlusher; + + /** + * This runnable is distinct from the regular flushers to + * signal the intent of encoding commitment without having to + * protect mPendingEncodingCommitment in the executer with a + * mutex. + */ + nsCOMPtr<nsIRunnable> mEncodingCommitter; + + /** + * The generict detector. + */ + mozilla::UniquePtr<mozilla::EncodingDetector> mDetector; + + /** + * The TLD we're loading from or empty if unknown. + */ + nsCString mTLD; + + /** + * Whether the initial charset source was kCharsetFromParentFrame + */ + bool mInitialEncodingWasFromParentFrame; + + bool mHasHadErrors; + + bool mDetectorHasSeenNonAscii; + + /** + * If true, we are decoding a local file that lacks an encoding + * declaration and we are not tokenizing yet. + */ + bool mDecodingLocalFileWithoutTokenizing; + + /** + * Whether we are keeping the incoming bytes. + */ + bool mBufferingBytes; + + /** + * Timer for flushing tree ops once in a while when not speculating. + */ + nsCOMPtr<nsITimer> mFlushTimer; + + /** + * Mutex for protecting access to mFlushTimer (but not for the two + * mFlushTimerFoo booleans below). + */ + mozilla::Mutex mFlushTimerMutex; + + /** + * Keeps track whether mFlushTimer has been armed. Unfortunately, + * nsITimer doesn't enable querying this from the timer itself. + */ + bool mFlushTimerArmed; + + /** + * False initially and true after the timer has fired at least once. + */ + bool mFlushTimerEverFired; + + /** + * Whether the parser is doing a normal parse, view source or plain text. + */ + eParserMode mMode; + + /** + * If the associated docshell is being watched by the devtools, this is + * set to the URI associated with the parse. All parse data is sent to the + * devtools, along with this URI. This URI is cleared out after the parse has + * been marked as completed. + */ + nsCOMPtr<nsIURI> mURIToSendToDevtools; + + /** + * If content is being sent to the devtools, an encoded UUID for the parser. + */ + nsString mUUIDForDevtools; +}; + +#endif // nsHtml5StreamParser_h diff --git a/parser/html/nsHtml5StreamParserPtr.h b/parser/html/nsHtml5StreamParserPtr.h new file mode 100644 index 0000000000..09bb2a0ea7 --- /dev/null +++ b/parser/html/nsHtml5StreamParserPtr.h @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef nsHtml5StreamParserPtr_h +#define nsHtml5StreamParserPtr_h + +#include "nsHtml5StreamParser.h" +#include "nsHtml5StreamParserReleaser.h" +#include "nsThreadUtils.h" +#include "mozilla/dom/DocGroup.h" + +/** + * Like nsRefPtr except release is proxied to the main + * thread. Mostly copied from nsRefPtr. + */ +class nsHtml5StreamParserPtr { + private: + void assign_with_AddRef(nsHtml5StreamParser* rawPtr) { + if (rawPtr) rawPtr->AddRef(); + assign_assuming_AddRef(rawPtr); + } + void** begin_assignment() { + assign_assuming_AddRef(0); + return reinterpret_cast<void**>(&mRawPtr); + } + void assign_assuming_AddRef(nsHtml5StreamParser* newPtr) { + nsHtml5StreamParser* oldPtr = mRawPtr; + mRawPtr = newPtr; + if (oldPtr) release(oldPtr); + } + void release(nsHtml5StreamParser* aPtr) { + nsCOMPtr<nsIRunnable> releaser = new nsHtml5StreamParserReleaser(aPtr); + if (NS_FAILED(aPtr->DispatchToMain(releaser.forget()))) { + NS_WARNING("Failed to dispatch releaser event."); + } + } + + private: + nsHtml5StreamParser* mRawPtr; + + public: + ~nsHtml5StreamParserPtr() { + if (mRawPtr) release(mRawPtr); + } + // Constructors + nsHtml5StreamParserPtr() + : mRawPtr(0) + // default constructor + {} + nsHtml5StreamParserPtr(const nsHtml5StreamParserPtr& aSmartPtr) + : mRawPtr(aSmartPtr.mRawPtr) + // copy-constructor + { + if (mRawPtr) mRawPtr->AddRef(); + } + explicit nsHtml5StreamParserPtr(nsHtml5StreamParser* aRawPtr) + : mRawPtr(aRawPtr) + // construct from a raw pointer (of the right type) + { + if (mRawPtr) mRawPtr->AddRef(); + } + // Assignment operators + nsHtml5StreamParserPtr& operator=(const nsHtml5StreamParserPtr& rhs) + // copy assignment operator + { + assign_with_AddRef(rhs.mRawPtr); + return *this; + } + nsHtml5StreamParserPtr& operator=(nsHtml5StreamParser* rhs) + // assign from a raw pointer (of the right type) + { + assign_with_AddRef(rhs); + return *this; + } + // Other pointer operators + void swap(nsHtml5StreamParserPtr& rhs) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + nsHtml5StreamParser* temp = rhs.mRawPtr; + rhs.mRawPtr = mRawPtr; + mRawPtr = temp; + } + void swap(nsHtml5StreamParser*& rhs) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + nsHtml5StreamParser* temp = rhs; + rhs = mRawPtr; + mRawPtr = temp; + } + template <typename I> + void forget(I** rhs) + // Set the target of rhs to the value of mRawPtr and null out mRawPtr. + // Useful to avoid unnecessary AddRef/Release pairs with "out" + // parameters where rhs bay be a T** or an I** where I is a base class + // of T. + { + NS_ASSERTION(rhs, "Null pointer passed to forget!"); + *rhs = mRawPtr; + mRawPtr = 0; + } + nsHtml5StreamParser* get() const + /* + Prefer the implicit conversion provided automatically by |operator + nsHtml5StreamParser*() const|. Use |get()| to resolve ambiguity or to get a + castable pointer. + */ + { + return const_cast<nsHtml5StreamParser*>(mRawPtr); + } + operator nsHtml5StreamParser*() const + /* + ...makes an |nsHtml5StreamParserPtr| act like its underlying raw + pointer type whenever it is used in a context where a raw pointer is + expected. It is this operator that makes an |nsHtml5StreamParserPtr| + substitutable for a raw pointer. Prefer the implicit use of this operator + to calling |get()|, except where necessary to resolve ambiguity. + */ + { + return get(); + } + nsHtml5StreamParser* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { + MOZ_ASSERT(mRawPtr != 0, + "You can't dereference a NULL nsHtml5StreamParserPtr with " + "operator->()."); + return get(); + } + nsHtml5StreamParserPtr* get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + const nsHtml5StreamParserPtr* get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + public: + nsHtml5StreamParser& operator*() const { + MOZ_ASSERT(mRawPtr != 0, + "You can't dereference a NULL nsHtml5StreamParserPtr with " + "operator*()."); + return *get(); + } + nsHtml5StreamParser** StartAssignment() { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return reinterpret_cast<nsHtml5StreamParser**>(begin_assignment()); +#else + assign_assuming_AddRef(0); + return reinterpret_cast<nsHtml5StreamParser**>(&mRawPtr); +#endif + } +}; + +inline nsHtml5StreamParserPtr* address_of(nsHtml5StreamParserPtr& aPtr) { + return aPtr.get_address(); +} + +inline const nsHtml5StreamParserPtr* address_of( + const nsHtml5StreamParserPtr& aPtr) { + return aPtr.get_address(); +} + +class nsHtml5StreamParserPtrGetterAddRefs +/* + ... + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + nsHtml5StreamParserPtr<IFoo> fooP; + ...->GetAddRefedPointer(getter_AddRefs(fooP)) + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| + instead. When initialized with a |nsHtml5StreamParserPtr|, as in the example + above, it returns a |void**|, a |T**|, or an |nsISupports**| as needed, that + the outer call (|GetAddRefedPointer| in this case) can fill in. This type + should be a nested class inside |nsHtml5StreamParserPtr<T>|. + */ +{ + public: + explicit nsHtml5StreamParserPtrGetterAddRefs( + nsHtml5StreamParserPtr& aSmartPtr) + : mTargetSmartPtr(aSmartPtr) { + // nothing else to do + } + operator void**() { + return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment()); + } + operator nsHtml5StreamParser**() { return mTargetSmartPtr.StartAssignment(); } + nsHtml5StreamParser*& operator*() { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsHtml5StreamParserPtr& mTargetSmartPtr; +}; + +inline nsHtml5StreamParserPtrGetterAddRefs getter_AddRefs( + nsHtml5StreamParserPtr& aSmartPtr) +/* + Used around a |nsHtml5StreamParserPtr| when + ...makes the class |nsHtml5StreamParserPtrGetterAddRefs| invisible. + */ +{ + return nsHtml5StreamParserPtrGetterAddRefs(aSmartPtr); +} + +// Comparing an |nsHtml5StreamParserPtr| to |0| + +inline bool operator==(const nsHtml5StreamParserPtr& lhs, decltype(nullptr)) { + return lhs.get() == nullptr; +} + +inline bool operator==(decltype(nullptr), const nsHtml5StreamParserPtr& rhs) { + return nullptr == rhs.get(); +} + +inline bool operator!=(const nsHtml5StreamParserPtr& lhs, decltype(nullptr)) { + return lhs.get() != nullptr; +} + +inline bool operator!=(decltype(nullptr), const nsHtml5StreamParserPtr& rhs) { + return nullptr != rhs.get(); +} + +#endif // !defined(nsHtml5StreamParserPtr_h) diff --git a/parser/html/nsHtml5StreamParserReleaser.h b/parser/html/nsHtml5StreamParserReleaser.h new file mode 100644 index 0000000000..e1273197d9 --- /dev/null +++ b/parser/html/nsHtml5StreamParserReleaser.h @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef nsHtml5StreamParserReleaser_h +#define nsHtml5StreamParserReleaser_h + +#include "nsHtml5StreamParser.h" +#include "nsThreadUtils.h" + +class nsHtml5StreamParserReleaser : public mozilla::Runnable { + private: + nsHtml5StreamParser* mPtr; + + public: + explicit nsHtml5StreamParserReleaser(nsHtml5StreamParser* aPtr) + : mozilla::Runnable("nsHtml5StreamParserReleaser"), mPtr(aPtr) {} + NS_IMETHOD Run() override { + mPtr->Release(); + return NS_OK; + } +}; + +#endif // nsHtml5StreamParserReleaser_h diff --git a/parser/html/nsHtml5String.cpp b/parser/html/nsHtml5String.cpp new file mode 100644 index 0000000000..5f30869cbb --- /dev/null +++ b/parser/html/nsHtml5String.cpp @@ -0,0 +1,188 @@ +/* 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/. */ + +#include "nsHtml5String.h" +#include "nsCharTraits.h" +#include "nsHtml5TreeBuilder.h" +#include "nsUTF8Utils.h" + +void nsHtml5String::ToString(nsAString& aString) { + switch (GetKind()) { + case eStringBuffer: + return AsStringBuffer()->ToString(Length(), aString); + case eAtom: + return AsAtom()->ToString(aString); + case eEmpty: + aString.Truncate(); + return; + default: + aString.Truncate(); + aString.SetIsVoid(true); + return; + } +} + +void nsHtml5String::CopyToBuffer(char16_t* aBuffer) const { + memcpy(aBuffer, AsPtr(), Length() * sizeof(char16_t)); +} + +bool nsHtml5String::LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const { + return !nsCharTraits<char16_t>::compareLowerCaseToASCIINullTerminated( + AsPtr(), Length(), aLowerCaseLiteral); +} + +bool nsHtml5String::EqualsASCII(const char* aLiteral) const { + return !nsCharTraits<char16_t>::compareASCIINullTerminated(AsPtr(), Length(), + aLiteral); +} + +bool nsHtml5String::LowerCaseStartsWithASCII( + const char* aLowerCaseLiteral) const { + const char* litPtr = aLowerCaseLiteral; + const char16_t* strPtr = AsPtr(); + const char16_t* end = strPtr + Length(); + char16_t litChar; + while ((litChar = *litPtr)) { + MOZ_ASSERT(!(litChar >= 'A' && litChar <= 'Z'), + "Literal isn't in lower case."); + if (strPtr == end) { + return false; + } + char16_t strChar = *strPtr; + if (strChar >= 'A' && strChar <= 'Z') { + strChar += 0x20; + } + if (litChar != strChar) { + return false; + } + ++litPtr; + ++strPtr; + } + return true; +} + +bool nsHtml5String::Equals(nsHtml5String aOther) const { + MOZ_ASSERT(operator bool()); + MOZ_ASSERT(aOther); + if (Length() != aOther.Length()) { + return false; + } + return !memcmp(AsPtr(), aOther.AsPtr(), Length() * sizeof(char16_t)); +} + +nsHtml5String nsHtml5String::Clone() { + switch (GetKind()) { + case eStringBuffer: + AsStringBuffer()->AddRef(); + break; + case eAtom: + AsAtom()->AddRef(); + break; + default: + break; + } + return nsHtml5String(mBits); +} + +void nsHtml5String::Release() { + switch (GetKind()) { + case eStringBuffer: + AsStringBuffer()->Release(); + break; + case eAtom: + AsAtom()->Release(); + break; + default: + break; + } + mBits = eNull; +} + +// static +nsHtml5String nsHtml5String::FromBuffer(char16_t* aBuffer, int32_t aLength, + nsHtml5TreeBuilder* aTreeBuilder) { + if (!aLength) { + return nsHtml5String(eEmpty); + } + // Work with nsStringBuffer directly to make sure that storage is actually + // nsStringBuffer and to make sure the allocation strategy matches + // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and + // copy. + RefPtr<nsStringBuffer> buffer( + nsStringBuffer::Alloc((aLength + 1) * sizeof(char16_t))); + if (!buffer) { + if (!aTreeBuilder) { + MOZ_CRASH("Out of memory."); + } + aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + buffer = nsStringBuffer::Alloc(2 * sizeof(char16_t)); + if (!buffer) { + MOZ_CRASH( + "Out of memory so badly that couldn't even allocate placeholder."); + } + char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); + data[0] = 0xFFFD; + data[1] = 0; + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); + } + char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); + memcpy(data, aBuffer, aLength * sizeof(char16_t)); + data[aLength] = 0; + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); +} + +// static +nsHtml5String nsHtml5String::FromLiteral(const char* aLiteral) { + size_t length = std::strlen(aLiteral); + if (!length) { + return nsHtml5String(eEmpty); + } + // Work with nsStringBuffer directly to make sure that storage is actually + // nsStringBuffer and to make sure the allocation strategy matches + // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and + // copy. + RefPtr<nsStringBuffer> buffer( + nsStringBuffer::Alloc((length + 1) * sizeof(char16_t))); + if (!buffer) { + MOZ_CRASH("Out of memory."); + } + char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); + ConvertAsciitoUtf16(mozilla::Span(aLiteral, length), + mozilla::Span(data, length)); + data[length] = 0; + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); +} + +// static +nsHtml5String nsHtml5String::FromString(const nsAString& aString) { + auto length = aString.Length(); + if (!length) { + return nsHtml5String(eEmpty); + } + RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aString); + if (buffer && (length == buffer->StorageSize() / sizeof(char16_t) - 1)) { + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); + } + buffer = nsStringBuffer::Alloc((length + 1) * sizeof(char16_t)); + if (!buffer) { + MOZ_CRASH("Out of memory."); + } + char16_t* data = reinterpret_cast<char16_t*>(buffer->Data()); + memcpy(data, aString.BeginReading(), length * sizeof(char16_t)); + data[length] = 0; + return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | + eStringBuffer); +} + +// static +nsHtml5String nsHtml5String::FromAtom(already_AddRefed<nsAtom> aAtom) { + return nsHtml5String(reinterpret_cast<uintptr_t>(aAtom.take()) | eAtom); +} + +// static +nsHtml5String nsHtml5String::EmptyString() { return nsHtml5String(eEmpty); } diff --git a/parser/html/nsHtml5String.h b/parser/html/nsHtml5String.h new file mode 100644 index 0000000000..f725630f9e --- /dev/null +++ b/parser/html/nsHtml5String.h @@ -0,0 +1,139 @@ +/* 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/. */ + +#ifndef nsHtml5String_h +#define nsHtml5String_h + +#include "nsAtom.h" +#include "nsString.h" +#include "nsStringBuffer.h" + +class nsHtml5TreeBuilder; + +/** + * A pass-by-value type that can represent + * * nullptr + * * empty string + * * Non-empty string as exactly-sized (capacity is length) `nsStringBuffer*` + * * Non-empty string as an nsAtom* + * + * Holding or passing this type is as unsafe as holding or passing + * `nsStringBuffer*`/`nsAtom*`. + */ +class nsHtml5String final { + private: + static const uintptr_t kKindMask = uintptr_t(3); + + static const uintptr_t kPtrMask = ~kKindMask; + + enum Kind : uintptr_t { + eNull = 0, + eEmpty = 1, + eStringBuffer = 2, + eAtom = 3, + }; + + inline Kind GetKind() const { return (Kind)(mBits & kKindMask); } + + inline nsStringBuffer* AsStringBuffer() const { + MOZ_ASSERT(GetKind() == eStringBuffer); + return reinterpret_cast<nsStringBuffer*>(mBits & kPtrMask); + } + + inline nsAtom* AsAtom() const { + MOZ_ASSERT(GetKind() == eAtom); + return reinterpret_cast<nsAtom*>(mBits & kPtrMask); + } + + inline const char16_t* AsPtr() const { + switch (GetKind()) { + case eStringBuffer: + return reinterpret_cast<char16_t*>(AsStringBuffer()->Data()); + case eAtom: + return AsAtom()->GetUTF16String(); + default: + return nsCharTraits<char16_t>::sEmptyBuffer; + } + } + + public: + /** + * Default constructor. + */ + inline nsHtml5String() : nsHtml5String(nullptr) {} + + /** + * Constructor from nullptr. + */ + inline MOZ_IMPLICIT nsHtml5String(decltype(nullptr)) : mBits(eNull) {} + + inline uint32_t Length() const { + switch (GetKind()) { + case eStringBuffer: + return (AsStringBuffer()->StorageSize() / sizeof(char16_t) - 1); + case eAtom: + return AsAtom()->GetLength(); + default: + return 0; + } + } + + /** + * False iff the string is logically null + */ + inline MOZ_IMPLICIT operator bool() const { return mBits; } + + /** + * Get the underlying nsAtom* or nullptr if this nsHtml5String + * does not hold an atom. + */ + inline nsAtom* MaybeAsAtom() { + if (GetKind() == eAtom) { + return AsAtom(); + } + return nullptr; + } + + void ToString(nsAString& aString); + + void CopyToBuffer(char16_t* aBuffer) const; + + bool LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const; + + bool EqualsASCII(const char* aLiteral) const; + + bool LowerCaseStartsWithASCII(const char* aLowerCaseLiteral) const; + + bool Equals(nsHtml5String aOther) const; + + nsHtml5String Clone(); + + void Release(); + + static nsHtml5String FromBuffer(char16_t* aBuffer, int32_t aLength, + nsHtml5TreeBuilder* aTreeBuilder); + + static nsHtml5String FromLiteral(const char* aLiteral); + + static nsHtml5String FromString(const nsAString& aString); + + static nsHtml5String FromAtom(already_AddRefed<nsAtom> aAtom); + + static nsHtml5String EmptyString(); + + private: + /** + * Constructor from raw bits. + */ + explicit nsHtml5String(uintptr_t aBits) : mBits(aBits){}; + + /** + * Zero if null, one if empty, otherwise tagged pointer + * to either nsAtom or nsStringBuffer. The two least-significant + * bits are tag bits. + */ + uintptr_t mBits; +}; + +#endif // nsHtml5String_h diff --git a/parser/html/nsHtml5StringParser.cpp b/parser/html/nsHtml5StringParser.cpp new file mode 100644 index 0000000000..98f643abb4 --- /dev/null +++ b/parser/html/nsHtml5StringParser.cpp @@ -0,0 +1,115 @@ +/* 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/. */ + +#include "nsHtml5StringParser.h" +#include "nsHtml5DependentUTF16Buffer.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5TreeOpExecutor.h" +#include "nsIContent.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/DocumentFragment.h" + +using mozilla::dom::Document; + +NS_IMPL_ISUPPORTS0(nsHtml5StringParser) + +nsHtml5StringParser::nsHtml5StringParser() + : mBuilder(new nsHtml5OplessBuilder()), + mTreeBuilder(new nsHtml5TreeBuilder(mBuilder)), + mTokenizer(new nsHtml5Tokenizer(mTreeBuilder.get(), false)) { + mTokenizer->setInterner(&mAtomTable); +} + +nsHtml5StringParser::~nsHtml5StringParser() {} + +nsresult nsHtml5StringParser::ParseFragment(const nsAString& aSourceBuffer, + nsIContent* aTargetNode, + nsAtom* aContextLocalName, + int32_t aContextNamespace, + bool aQuirks, + bool aPreventScriptExecution) { + NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY); + + Document* doc = aTargetNode->OwnerDoc(); + nsIURI* uri = doc->GetDocumentURI(); + NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE); + + mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace, + aTargetNode, aQuirks); + +#ifdef DEBUG + if (!aPreventScriptExecution) { + NS_ASSERTION(!aTargetNode->IsInUncomposedDoc(), + "If script execution isn't prevented, " + "the target node must not be in doc."); + NS_ASSERTION( + aTargetNode->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE, + "If script execution isn't prevented, must parse to DOM fragment."); + } +#endif + + mTreeBuilder->SetPreventScriptExecution(aPreventScriptExecution); + + return Tokenize(aSourceBuffer, doc, true); +} + +nsresult nsHtml5StringParser::ParseDocument( + const nsAString& aSourceBuffer, Document* aTargetDoc, + bool aScriptingEnabledForNoscriptParsing) { + MOZ_ASSERT(!aTargetDoc->GetFirstChild()); + + NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY); + + mTreeBuilder->setFragmentContext(nullptr, kNameSpaceID_None, nullptr, false); + + mTreeBuilder->SetPreventScriptExecution(true); + + return Tokenize(aSourceBuffer, aTargetDoc, + aScriptingEnabledForNoscriptParsing); +} + +nsresult nsHtml5StringParser::Tokenize( + const nsAString& aSourceBuffer, Document* aDocument, + bool aScriptingEnabledForNoscriptParsing) { + nsIURI* uri = aDocument->GetDocumentURI(); + + mBuilder->Init(aDocument, uri, nullptr, nullptr); + + mBuilder->SetParser(this); + mBuilder->SetNodeInfoManager(aDocument->NodeInfoManager()); + + // Mark the parser as *not* broken by passing NS_OK + nsresult rv = mBuilder->MarkAsBroken(NS_OK); + + mTreeBuilder->setScriptingEnabled(aScriptingEnabledForNoscriptParsing); + mTreeBuilder->setIsSrcdocDocument(aDocument->IsSrcdocDocument()); + mBuilder->Start(); + mTokenizer->start(); + if (!aSourceBuffer.IsEmpty()) { + bool lastWasCR = false; + nsHtml5DependentUTF16Buffer buffer(aSourceBuffer); + while (buffer.hasMore()) { + buffer.adjust(lastWasCR); + lastWasCR = false; + if (buffer.hasMore()) { + if (!mTokenizer->EnsureBufferSpace(buffer.getLength())) { + rv = mBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + break; + } + lastWasCR = mTokenizer->tokenizeBuffer(&buffer); + if (NS_FAILED(rv = mBuilder->IsBroken())) { + break; + } + } + } + } + if (NS_SUCCEEDED(rv)) { + mTokenizer->eof(); + } + mTokenizer->end(); + mBuilder->Finish(); + mAtomTable.Clear(); + return rv; +} diff --git a/parser/html/nsHtml5StringParser.h b/parser/html/nsHtml5StringParser.h new file mode 100644 index 0000000000..098a913748 --- /dev/null +++ b/parser/html/nsHtml5StringParser.h @@ -0,0 +1,87 @@ +/* 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/. */ + +#ifndef nsHtml5StringParser_h +#define nsHtml5StringParser_h + +#include "mozilla/UniquePtr.h" +#include "nsHtml5AtomTable.h" +#include "nsParserBase.h" + +class nsHtml5OplessBuilder; +class nsHtml5TreeBuilder; +class nsHtml5Tokenizer; +class nsIContent; +namespace mozilla { +namespace dom { +class Document; +} +} // namespace mozilla + +class nsHtml5StringParser : public nsParserBase { + public: + NS_DECL_ISUPPORTS + + /** + * Constructor for use ONLY by nsContentUtils. Others, please call the + * nsContentUtils statics that wrap this. + */ + nsHtml5StringParser(); + + /** + * Invoke the fragment parsing algorithm (innerHTML). + * DO NOT CALL from outside nsContentUtils.cpp. + * + * @param aSourceBuffer the string being set as innerHTML + * @param aTargetNode the target container + * @param aContextLocalName local name of context node + * @param aContextNamespace namespace of context node + * @param aQuirks true to make <table> not close <p> + * @param aPreventScriptExecution true to prevent scripts from executing; + * don't set to false when parsing into a target node that has been bound + * to tree. + */ + nsresult ParseFragment(const nsAString& aSourceBuffer, + nsIContent* aTargetNode, nsAtom* aContextLocalName, + int32_t aContextNamespace, bool aQuirks, + bool aPreventScriptExecution); + + /** + * Parse an entire HTML document from a source string. + * DO NOT CALL from outside nsContentUtils.cpp. + * + */ + nsresult ParseDocument(const nsAString& aSourceBuffer, + mozilla::dom::Document* aTargetDoc, + bool aScriptingEnabledForNoscriptParsing); + + private: + virtual ~nsHtml5StringParser(); + + nsresult Tokenize(const nsAString& aSourceBuffer, + mozilla::dom::Document* aDocument, + bool aScriptingEnabledForNoscriptParsing); + + /** + * The tree operation executor + */ + RefPtr<nsHtml5OplessBuilder> mBuilder; + + /** + * The HTML5 tree builder + */ + const mozilla::UniquePtr<nsHtml5TreeBuilder> mTreeBuilder; + + /** + * The HTML5 tokenizer + */ + const mozilla::UniquePtr<nsHtml5Tokenizer> mTokenizer; + + /** + * The scoped atom table + */ + nsHtml5AtomTable mAtomTable; +}; + +#endif // nsHtml5StringParser_h diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp new file mode 100644 index 0000000000..b5de5a9266 --- /dev/null +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -0,0 +1,5153 @@ +/* + * Copyright (c) 2005-2007 Henri Sivonen + * Copyright (c) 2007-2017 Mozilla Foundation + * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla + * Foundation, and Opera Software ASA. + * + * 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit Tokenizer.java instead and regenerate. + */ + +#define nsHtml5Tokenizer_cpp__ + +#include "jArray.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsAtom.h" +#include "nsGkAtoms.h" +#include "nsHtml5ArrayCopy.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5DocumentMode.h" +#include "nsHtml5Highlighter.h" +#include "nsHtml5Macros.h" +#include "nsHtml5NamedCharacters.h" +#include "nsHtml5NamedCharactersAccel.h" +#include "nsHtml5String.h" +#include "nsHtml5TokenizerLoopPolicies.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" + +#include "nsHtml5AttributeName.h" +#include "nsHtml5ElementName.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5Portability.h" + +#include "nsHtml5Tokenizer.h" + +char16_t nsHtml5Tokenizer::LT_GT[] = {'<', '>'}; +char16_t nsHtml5Tokenizer::LT_SOLIDUS[] = {'<', '/'}; +char16_t nsHtml5Tokenizer::RSQB_RSQB[] = {']', ']'}; +char16_t nsHtml5Tokenizer::REPLACEMENT_CHARACTER[] = {0xfffd}; +char16_t nsHtml5Tokenizer::LF[] = {'\n'}; +char16_t nsHtml5Tokenizer::CDATA_LSQB[] = {'C', 'D', 'A', 'T', 'A', '['}; +char16_t nsHtml5Tokenizer::OCTYPE[] = {'o', 'c', 't', 'y', 'p', 'e'}; +char16_t nsHtml5Tokenizer::UBLIC[] = {'u', 'b', 'l', 'i', 'c'}; +char16_t nsHtml5Tokenizer::YSTEM[] = {'y', 's', 't', 'e', 'm'}; +static char16_t const TITLE_ARR_DATA[] = {'t', 'i', 't', 'l', 'e'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::TITLE_ARR = { + TITLE_ARR_DATA, MOZ_ARRAY_LENGTH(TITLE_ARR_DATA)}; +static char16_t const SCRIPT_ARR_DATA[] = {'s', 'c', 'r', 'i', 'p', 't'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::SCRIPT_ARR = { + SCRIPT_ARR_DATA, MOZ_ARRAY_LENGTH(SCRIPT_ARR_DATA)}; +static char16_t const STYLE_ARR_DATA[] = {'s', 't', 'y', 'l', 'e'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::STYLE_ARR = { + STYLE_ARR_DATA, MOZ_ARRAY_LENGTH(STYLE_ARR_DATA)}; +static char16_t const PLAINTEXT_ARR_DATA[] = {'p', 'l', 'a', 'i', 'n', + 't', 'e', 'x', 't'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::PLAINTEXT_ARR = { + PLAINTEXT_ARR_DATA, MOZ_ARRAY_LENGTH(PLAINTEXT_ARR_DATA)}; +static char16_t const XMP_ARR_DATA[] = {'x', 'm', 'p'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::XMP_ARR = { + XMP_ARR_DATA, MOZ_ARRAY_LENGTH(XMP_ARR_DATA)}; +static char16_t const TEXTAREA_ARR_DATA[] = {'t', 'e', 'x', 't', + 'a', 'r', 'e', 'a'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::TEXTAREA_ARR = { + TEXTAREA_ARR_DATA, MOZ_ARRAY_LENGTH(TEXTAREA_ARR_DATA)}; +static char16_t const IFRAME_ARR_DATA[] = {'i', 'f', 'r', 'a', 'm', 'e'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::IFRAME_ARR = { + IFRAME_ARR_DATA, MOZ_ARRAY_LENGTH(IFRAME_ARR_DATA)}; +static char16_t const NOEMBED_ARR_DATA[] = {'n', 'o', 'e', 'm', 'b', 'e', 'd'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOEMBED_ARR = { + NOEMBED_ARR_DATA, MOZ_ARRAY_LENGTH(NOEMBED_ARR_DATA)}; +static char16_t const NOSCRIPT_ARR_DATA[] = {'n', 'o', 's', 'c', + 'r', 'i', 'p', 't'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOSCRIPT_ARR = { + NOSCRIPT_ARR_DATA, MOZ_ARRAY_LENGTH(NOSCRIPT_ARR_DATA)}; +static char16_t const NOFRAMES_ARR_DATA[] = {'n', 'o', 'f', 'r', + 'a', 'm', 'e', 's'}; +staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOFRAMES_ARR = { + NOFRAMES_ARR_DATA, MOZ_ARRAY_LENGTH(NOFRAMES_ARR_DATA)}; + +nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler, + bool viewingXmlSource) + : tokenHandler(tokenHandler), + encodingDeclarationHandler(nullptr), + lastCR(false), + stateSave(0), + returnStateSave(0), + index(0), + forceQuirks(false), + additional('\0'), + entCol(0), + firstCharKey(0), + lo(0), + hi(0), + candidate(0), + charRefBufMark(0), + value(0), + seenDigits(false), + suspendAfterCurrentNonTextToken(false), + cstart(0), + strBufLen(0), + charRefBuf(jArray<char16_t, int32_t>::newJArray(32)), + charRefBufLen(0), + bmpChar(jArray<char16_t, int32_t>::newJArray(1)), + astralChar(jArray<char16_t, int32_t>::newJArray(2)), + endTagExpectation(nullptr), + endTagExpectationAsArray(nullptr), + endTag(false), + containsHyphen(false), + tagName(nullptr), + nonInternedTagName(new nsHtml5ElementName()), + attributeName(nullptr), + nonInternedAttributeName(new nsHtml5AttributeName()), + doctypeName(nullptr), + publicIdentifier(nullptr), + systemIdentifier(nullptr), + attributes(tokenHandler->HasBuilder() ? new nsHtml5HtmlAttributes(0) + : nullptr), + newAttributesEachTime(!tokenHandler->HasBuilder()), + shouldSuspend(false), + confident(false), + line(0), + attributeLine(0), + interner(nullptr), + viewingXmlSource(viewingXmlSource) { + MOZ_COUNT_CTOR(nsHtml5Tokenizer); +} + +void nsHtml5Tokenizer::setInterner(nsHtml5AtomTable* interner) { + this->interner = interner; +} + +void nsHtml5Tokenizer::initLocation(nsHtml5String newPublicId, + nsHtml5String newSystemId) { + this->systemId = newSystemId; + this->publicId = newPublicId; +} + +bool nsHtml5Tokenizer::isViewingXmlSource() { return viewingXmlSource; } + +void nsHtml5Tokenizer::setState(int32_t specialTokenizerState) { + this->stateSave = specialTokenizerState; + this->endTagExpectation = nullptr; + this->endTagExpectationAsArray = nullptr; +} + +void nsHtml5Tokenizer::setStateAndEndTagExpectation( + int32_t specialTokenizerState, nsHtml5ElementName* endTagExpectation) { + this->stateSave = specialTokenizerState; + this->endTagExpectation = endTagExpectation; + endTagExpectationToArray(); +} + +void nsHtml5Tokenizer::endTagExpectationToArray() { + switch (endTagExpectation->getGroup()) { + case nsHtml5TreeBuilder::TITLE: { + endTagExpectationAsArray = TITLE_ARR; + return; + } + case nsHtml5TreeBuilder::SCRIPT: { + endTagExpectationAsArray = SCRIPT_ARR; + return; + } + case nsHtml5TreeBuilder::STYLE: { + endTagExpectationAsArray = STYLE_ARR; + return; + } + case nsHtml5TreeBuilder::PLAINTEXT: { + endTagExpectationAsArray = PLAINTEXT_ARR; + return; + } + case nsHtml5TreeBuilder::XMP: { + endTagExpectationAsArray = XMP_ARR; + return; + } + case nsHtml5TreeBuilder::TEXTAREA: { + endTagExpectationAsArray = TEXTAREA_ARR; + return; + } + case nsHtml5TreeBuilder::IFRAME: { + endTagExpectationAsArray = IFRAME_ARR; + return; + } + case nsHtml5TreeBuilder::NOEMBED: { + endTagExpectationAsArray = NOEMBED_ARR; + return; + } + case nsHtml5TreeBuilder::NOSCRIPT: { + endTagExpectationAsArray = NOSCRIPT_ARR; + return; + } + case nsHtml5TreeBuilder::NOFRAMES: { + endTagExpectationAsArray = NOFRAMES_ARR; + return; + } + default: { + MOZ_ASSERT(false, "Bad end tag expectation."); + return; + } + } +} + +void nsHtml5Tokenizer::setLineNumber(int32_t line) { + this->attributeLine = line; + this->line = line; +} + +nsHtml5HtmlAttributes* nsHtml5Tokenizer::emptyAttributes() { + return nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES; +} + +void nsHtml5Tokenizer::emitOrAppendCharRefBuf(int32_t returnState) { + if ((returnState & DATA_AND_RCDATA_MASK)) { + appendCharRefBufToStrBuf(); + } else { + if (charRefBufLen > 0) { + tokenHandler->characters(charRefBuf, 0, charRefBufLen); + charRefBufLen = 0; + } + } +} + +nsHtml5String nsHtml5Tokenizer::strBufToString() { + nsHtml5String str = nsHtml5Portability::newStringFromBuffer( + strBuf, 0, strBufLen, tokenHandler, + !newAttributesEachTime && + attributeName == nsHtml5AttributeName::ATTR_CLASS); + clearStrBufAfterUse(); + return str; +} + +void nsHtml5Tokenizer::strBufToDoctypeName() { + doctypeName = + nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen, interner); + clearStrBufAfterUse(); +} + +void nsHtml5Tokenizer::emitStrBuf() { + if (strBufLen > 0) { + tokenHandler->characters(strBuf, 0, strBufLen); + clearStrBufAfterUse(); + } +} + +void nsHtml5Tokenizer::appendStrBuf(char16_t* buffer, int32_t offset, + int32_t length) { + int32_t newLen = nsHtml5Portability::checkedAdd(strBufLen, length); + MOZ_ASSERT(newLen <= strBuf.length, "Previous buffer length insufficient."); + if (MOZ_UNLIKELY(strBuf.length < newLen)) { + if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) { + MOZ_CRASH("Unable to recover from buffer reallocation failure"); + } + } + nsHtml5ArrayCopy::arraycopy(buffer, offset, strBuf, strBufLen, length); + strBufLen = newLen; +} + +void nsHtml5Tokenizer::emitComment(int32_t provisionalHyphens, int32_t pos) { + RememberGt(pos); + tokenHandler->comment(strBuf, 0, strBufLen - provisionalHyphens); + clearStrBufAfterUse(); + cstart = pos + 1; + suspendIfRequestedAfterCurrentNonTextToken(); +} + +void nsHtml5Tokenizer::flushChars(char16_t* buf, int32_t pos) { + if (pos > cstart) { + tokenHandler->characters(buf, cstart, pos - cstart); + } + cstart = INT32_MAX; +} + +void nsHtml5Tokenizer::strBufToElementNameString() { + if (containsHyphen) { + nsAtom* annotationName = nsHtml5ElementName::ELT_ANNOTATION_XML->getName(); + if (nsHtml5Portability::localEqualsBuffer(annotationName, strBuf, + strBufLen)) { + tagName = nsHtml5ElementName::ELT_ANNOTATION_XML; + } else { + nonInternedTagName->setNameForNonInterned( + nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen, + interner), + true); + tagName = nonInternedTagName; + } + } else { + tagName = + nsHtml5ElementName::elementNameByBuffer(strBuf, strBufLen, interner); + if (!tagName) { + nonInternedTagName->setNameForNonInterned( + nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen, + interner), + false); + tagName = nonInternedTagName; + } + } + containsHyphen = false; + clearStrBufAfterUse(); +} + +int32_t nsHtml5Tokenizer::emitCurrentTagToken(bool selfClosing, int32_t pos) { + RememberGt(pos); + cstart = pos + 1; + maybeErrSlashInEndTag(selfClosing); + stateSave = nsHtml5Tokenizer::DATA; + nsHtml5HtmlAttributes* attrs = + (!attributes ? nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES : attributes); + if (endTag) { + maybeErrAttributesOnEndTag(attrs); + if (!viewingXmlSource) { + tokenHandler->endTag(tagName); + } + if (newAttributesEachTime) { + delete attributes; + attributes = nullptr; + } + } else { + if (viewingXmlSource) { + MOZ_ASSERT(newAttributesEachTime); + delete attributes; + attributes = nullptr; + } else { + tokenHandler->startTag(tagName, attrs, selfClosing); + } + } + tagName = nullptr; + if (newAttributesEachTime) { + attributes = nullptr; + } else { + attributes->clear(0); + } + suspendIfRequestedAfterCurrentNonTextToken(); + return stateSave; +} + +void nsHtml5Tokenizer::attributeNameComplete() { + attributeName = + nsHtml5AttributeName::nameByBuffer(strBuf, strBufLen, interner); + if (!attributeName) { + nonInternedAttributeName->setNameForNonInterned( + nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen, + interner)); + attributeName = nonInternedAttributeName; + } + clearStrBufAfterUse(); + if (!attributes) { + attributes = new nsHtml5HtmlAttributes(0); + } + if (attributes->contains(attributeName)) { + errDuplicateAttribute(); + attributeName = nullptr; + } +} + +void nsHtml5Tokenizer::addAttributeWithoutValue() { + if (attributeName) { + attributes->addAttribute( + attributeName, nsHtml5Portability::newEmptyString(), attributeLine); + attributeName = nullptr; + } else { + clearStrBufAfterUse(); + } +} + +void nsHtml5Tokenizer::addAttributeWithValue() { + if (attributeName) { + nsHtml5String val = strBufToString(); + if (mViewSource) { + mViewSource->MaybeLinkifyAttributeValue(attributeName, val); + } + attributes->addAttribute(attributeName, val, attributeLine); + attributeName = nullptr; + } else { + clearStrBufAfterUse(); + } +} + +void nsHtml5Tokenizer::start() { + initializeWithoutStarting(); + tokenHandler->startTokenization(this); + line = 0; + col = 1; + nextCharOnNewLine = true; +} + +bool nsHtml5Tokenizer::tokenizeBuffer(nsHtml5UTF16Buffer* buffer) { + int32_t state = stateSave; + int32_t returnState = returnStateSave; + char16_t c = '\0'; + shouldSuspend = false; + lastCR = false; + int32_t start = buffer->getStart(); + int32_t end = buffer->getEnd(); + int32_t pos = start - 1; + switch (state) { + case DATA: + case RCDATA: + case SCRIPT_DATA: + case PLAINTEXT: + case RAWTEXT: + case CDATA_SECTION: + case SCRIPT_DATA_ESCAPED: + case SCRIPT_DATA_ESCAPE_START: + case SCRIPT_DATA_ESCAPE_START_DASH: + case SCRIPT_DATA_ESCAPED_DASH: + case SCRIPT_DATA_ESCAPED_DASH_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPE_START: + case SCRIPT_DATA_DOUBLE_ESCAPED: + case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPE_END: { + cstart = start; + break; + } + default: { + cstart = INT32_MAX; + break; + } + } + if (mViewSource) { + mViewSource->SetBuffer(buffer); + pos = stateLoop<nsHtml5ViewSourcePolicy>(state, c, pos, buffer->getBuffer(), + false, returnState, + buffer->getEnd()); + mViewSource->DropBuffer((pos == buffer->getEnd()) ? pos : pos + 1); + } else { + pos = stateLoop<nsHtml5SilentPolicy>(state, c, pos, buffer->getBuffer(), + false, returnState, buffer->getEnd()); + } + if (pos == end) { + buffer->setStart(pos); + } else { + buffer->setStart(pos + 1); + } + return lastCR; +} + +template <class P> +int32_t nsHtml5Tokenizer::stateLoop(int32_t state, char16_t c, int32_t pos, + char16_t* buf, bool reconsume, + int32_t returnState, int32_t endPos) { + bool reportedConsecutiveHyphens = false; +stateloop: + for (;;) { + switch (state) { + case DATA: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '&': { + flushChars(buf, pos); + MOZ_ASSERT(!charRefBufLen, + "charRefBufLen not reset after previous use!"); + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\0'); + returnState = state; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '<': { + flushChars(buf, pos); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::TAG_OPEN, reconsume, pos); + NS_HTML5_BREAK(dataloop); + } + case '\0': { + maybeEmitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + dataloop_end:; + [[fallthrough]]; + } + case TAG_OPEN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + if (c >= 'A' && c <= 'Z') { + endTag = false; + clearStrBufBeforeUse(); + appendStrBuf((char16_t)(c + 0x20)); + containsHyphen = false; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::TAG_NAME, + reconsume, pos); + NS_HTML5_BREAK(tagopenloop); + } else if (c >= 'a' && c <= 'z') { + endTag = false; + clearStrBufBeforeUse(); + appendStrBuf(c); + containsHyphen = false; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::TAG_NAME, + reconsume, pos); + NS_HTML5_BREAK(tagopenloop); + } + switch (c) { + case '!': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::MARKUP_DECLARATION_OPEN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '/': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::CLOSE_TAG_OPEN, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\?': { + if (viewingXmlSource) { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::PROCESSING_INSTRUCTION, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + if (P::reportErrors) { + errProcessingInstruction(); + } + clearStrBufBeforeUse(); + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errLtGt(); + } + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 2); + cstart = pos + 1; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + default: { + if (P::reportErrors) { + errBadCharAfterLt(c); + } + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + cstart = pos; + reconsume = true; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + tagopenloop_end:; + [[fallthrough]]; + } + case TAG_NAME: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + strBufToElementNameString(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + strBufToElementNameString(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_BREAK(tagnameloop); + } + case '/': { + strBufToElementNameString(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SELF_CLOSING_START_TAG, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + strBufToElementNameString(); + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), reconsume, + pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + if (c >= 'A' && c <= 'Z') { + c += 0x20; + } else if (c == '-') { + containsHyphen = true; + } + appendStrBuf(c); + continue; + } + } + } + tagnameloop_end:; + [[fallthrough]]; + } + case BEFORE_ATTRIBUTE_NAME: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '/': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SELF_CLOSING_START_TAG, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), reconsume, + pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + case '\"': + case '\'': + case '<': + case '=': { + if (P::reportErrors) { + errBadCharBeforeAttributeNameOrNull(c); + } + [[fallthrough]]; + } + default: { + if (c >= 'A' && c <= 'Z') { + c += 0x20; + } + attributeLine = line; + clearStrBufBeforeUse(); + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::ATTRIBUTE_NAME, reconsume, + pos); + NS_HTML5_BREAK(beforeattributenameloop); + } + } + } + beforeattributenameloop_end:; + [[fallthrough]]; + } + case ATTRIBUTE_NAME: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + attributeNameComplete(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + attributeNameComplete(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '/': { + attributeNameComplete(); + addAttributeWithoutValue(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SELF_CLOSING_START_TAG, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '=': { + attributeNameComplete(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE, + reconsume, pos); + NS_HTML5_BREAK(attributenameloop); + } + case '>': { + attributeNameComplete(); + addAttributeWithoutValue(); + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), reconsume, + pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + case '\"': + case '\'': + case '<': { + if (P::reportErrors) { + errQuoteOrLtInAttributeNameOrNull(c); + } + [[fallthrough]]; + } + default: { + if (c >= 'A' && c <= 'Z') { + c += 0x20; + } + appendStrBuf(c); + continue; + } + } + } + attributenameloop_end:; + [[fallthrough]]; + } + case BEFORE_ATTRIBUTE_VALUE: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '\"': { + attributeLine = line; + clearStrBufBeforeUse(); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::ATTRIBUTE_VALUE_DOUBLE_QUOTED, + reconsume, pos); + NS_HTML5_BREAK(beforeattributevalueloop); + } + case '&': { + attributeLine = line; + clearStrBufBeforeUse(); + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED, + reconsume, pos); + + NS_HTML5_CONTINUE(stateloop); + } + case '\'': { + attributeLine = line; + clearStrBufBeforeUse(); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::ATTRIBUTE_VALUE_SINGLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errAttributeValueMissing(); + } + addAttributeWithoutValue(); + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), reconsume, + pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + case '<': + case '=': + case '`': { + if (P::reportErrors) { + errLtOrEqualsOrGraveInUnquotedAttributeOrNull(c); + } + [[fallthrough]]; + } + default: { + attributeLine = line; + clearStrBufBeforeUse(); + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED, + reconsume, pos); + + NS_HTML5_CONTINUE(stateloop); + } + } + } + beforeattributevalueloop_end:; + [[fallthrough]]; + } + case ATTRIBUTE_VALUE_DOUBLE_QUOTED: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\"': { + addAttributeWithValue(); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED, + reconsume, pos); + NS_HTML5_BREAK(attributevaluedoublequotedloop); + } + case '&': { + MOZ_ASSERT(!charRefBufLen, + "charRefBufLen not reset after previous use!"); + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\"'); + returnState = state; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + attributevaluedoublequotedloop_end:; + [[fallthrough]]; + } + case AFTER_ATTRIBUTE_VALUE_QUOTED: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '/': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SELF_CLOSING_START_TAG, + reconsume, pos); + NS_HTML5_BREAK(afterattributevaluequotedloop); + } + case '>': { + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), reconsume, + pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + if (P::reportErrors) { + errNoSpaceBetweenAttributes(); + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + afterattributevaluequotedloop_end:; + [[fallthrough]]; + } + case SELF_CLOSING_START_TAG: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '>': { + state = + P::transition(mViewSource.get(), emitCurrentTagToken(true, pos), + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + if (P::reportErrors) { + errSlashNotFollowedByGt(); + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + case ATTRIBUTE_VALUE_UNQUOTED: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\r': { + silentCarriageReturn(); + addAttributeWithValue(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + addAttributeWithValue(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '&': { + MOZ_ASSERT(!charRefBufLen, + "charRefBufLen not reset after previous use!"); + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('>'); + returnState = state; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + addAttributeWithValue(); + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), reconsume, + pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + case '<': + case '\"': + case '\'': + case '=': + case '`': { + if (P::reportErrors) { + errUnquotedAttributeValOrNull(c); + } + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + } + case AFTER_ATTRIBUTE_NAME: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '/': { + addAttributeWithoutValue(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SELF_CLOSING_START_TAG, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '=': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + addAttributeWithoutValue(); + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), reconsume, + pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + case '\"': + case '\'': + case '<': { + if (P::reportErrors) { + errQuoteOrLtInAttributeNameOrNull(c); + } + [[fallthrough]]; + } + default: { + addAttributeWithoutValue(); + if (c >= 'A' && c <= 'Z') { + c += 0x20; + } + clearStrBufBeforeUse(); + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::ATTRIBUTE_NAME, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + case MARKUP_DECLARATION_OPEN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + clearStrBufBeforeUse(); + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::MARKUP_DECLARATION_HYPHEN, + reconsume, pos); + NS_HTML5_BREAK(markupdeclarationopenloop); + } + case 'd': + case 'D': { + clearStrBufBeforeUse(); + appendStrBuf(c); + index = 0; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::MARKUP_DECLARATION_OCTYPE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '[': { + if (tokenHandler->cdataSectionAllowed()) { + clearStrBufBeforeUse(); + appendStrBuf(c); + index = 0; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::CDATA_START, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + [[fallthrough]]; + } + default: { + if (P::reportErrors) { + errBogusComment(); + } + clearStrBufBeforeUse(); + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + markupdeclarationopenloop_end:; + [[fallthrough]]; + } + case MARKUP_DECLARATION_HYPHEN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + clearStrBufAfterOneHyphen(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_START, reconsume, + pos); + NS_HTML5_BREAK(markupdeclarationhyphenloop); + } + default: { + if (P::reportErrors) { + errBogusComment(); + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + markupdeclarationhyphenloop_end:; + [[fallthrough]]; + } + case COMMENT_START: { + reportedConsecutiveHyphens = false; + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_START_DASH, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errPrematureEndOfComment(); + } + emitComment(0, pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '<': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(commentstartloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(commentstartloop); + } + } + } + commentstartloop_end:; + [[fallthrough]]; + } + case COMMENT: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_END_DASH, + reconsume, pos); + NS_HTML5_BREAK(commentloop); + } + case '<': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + commentloop_end:; + [[fallthrough]]; + } + case COMMENT_END_DASH: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + appendStrBuf(c); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_END, reconsume, pos); + NS_HTML5_BREAK(commentenddashloop); + } + case '<': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + commentenddashloop_end:; + [[fallthrough]]; + } + case COMMENT_END: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '>': { + emitComment(2, pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '-': { + adjustDoubleHyphenAndAppendToStrBufAndErr( + c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + continue; + } + case '<': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + adjustDoubleHyphenAndAppendToStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + adjustDoubleHyphenAndAppendToStrBufLineFeed(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '!': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_END_BANG, + reconsume, pos); + NS_HTML5_BREAK(commentendloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + adjustDoubleHyphenAndAppendToStrBufAndErr( + c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + commentendloop_end:; + [[fallthrough]]; + } + case COMMENT_END_BANG: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '>': { + emitComment(3, pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '-': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_END_DASH, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + case COMMENT_LESSTHAN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '!': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG, + reconsume, pos); + NS_HTML5_BREAK(commentlessthanloop); + } + case '<': { + appendStrBuf(c); + continue; + } + case '-': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_END_DASH, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + commentlessthanloop_end:; + [[fallthrough]]; + } + case COMMENT_LESSTHAN_BANG: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + appendStrBuf(c); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG_DASH, reconsume, pos); + NS_HTML5_BREAK(commentlessthanbangloop); + } + case '<': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + commentlessthanbangloop_end:; + [[fallthrough]]; + } + case COMMENT_LESSTHAN_BANG_DASH: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + appendStrBuf(c); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG_DASH_DASH, + reconsume, pos); + break; + } + case '<': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + [[fallthrough]]; + } + case COMMENT_LESSTHAN_BANG_DASH_DASH: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '>': { + appendStrBuf(c); + emitComment(3, pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '-': { + if (P::reportErrors) { + errNestedComment(); + } + adjustDoubleHyphenAndAppendToStrBufAndErr( + c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = + P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT_END, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + c = '\n'; + silentCarriageReturn(); + if (P::reportErrors) { + errNestedComment(); + } + adjustDoubleHyphenAndAppendToStrBufAndErr( + c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + if (P::reportErrors) { + errNestedComment(); + } + adjustDoubleHyphenAndAppendToStrBufAndErr( + c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '!': { + if (P::reportErrors) { + errNestedComment(); + } + adjustDoubleHyphenAndAppendToStrBufAndErr( + c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_END_BANG, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + if (P::reportErrors) { + errNestedComment(); + } + adjustDoubleHyphenAndAppendToStrBufAndErr( + c, reportedConsecutiveHyphens); + reportedConsecutiveHyphens = true; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + case COMMENT_START_DASH: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + appendStrBuf(c); + state = + P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT_END, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errPrematureEndOfComment(); + } + emitComment(1, pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '<': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::COMMENT_LESSTHAN, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + case CDATA_START: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + if (index < 6) { + if (c == nsHtml5Tokenizer::CDATA_LSQB[index]) { + appendStrBuf(c); + } else { + if (P::reportErrors) { + errBogusComment(); + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + index++; + continue; + } else { + clearStrBufAfterUse(); + cstart = pos; + reconsume = true; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CDATA_SECTION, reconsume, pos); + break; + } + } + [[fallthrough]]; + } + case CDATA_SECTION: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case ']': { + flushChars(buf, pos); + state = + P::transition(mViewSource.get(), nsHtml5Tokenizer::CDATA_RSQB, + reconsume, pos); + NS_HTML5_BREAK(cdatasectionloop); + } + case '\0': { + maybeEmitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + cdatasectionloop_end:; + [[fallthrough]]; + } + case CDATA_RSQB: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case ']': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::CDATA_RSQB_RSQB, reconsume, + pos); + break; + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1); + cstart = pos; + reconsume = true; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CDATA_SECTION, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + [[fallthrough]]; + } + case CDATA_RSQB_RSQB: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case ']': { + tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1); + continue; + } + case '>': { + cstart = pos + 1; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + suspendIfRequestedAfterCurrentNonTextToken(); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 2); + cstart = pos; + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::CDATA_SECTION, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + case ATTRIBUTE_VALUE_SINGLE_QUOTED: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\'': { + addAttributeWithValue(); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '&': { + MOZ_ASSERT(!charRefBufLen, + "charRefBufLen not reset after previous use!"); + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\''); + returnState = state; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE, + reconsume, pos); + NS_HTML5_BREAK(attributevaluesinglequotedloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + attributevaluesinglequotedloop_end:; + [[fallthrough]]; + } + case CONSUME_CHARACTER_REFERENCE: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': + case '<': + case '&': + case '\0': + case ';': { + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '#': { + appendCharRefBuf('#'); + state = + P::transition(mViewSource.get(), nsHtml5Tokenizer::CONSUME_NCR, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + default: { + if (c == additional) { + emitOrAppendCharRefBuf(returnState); + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + if (c >= 'a' && c <= 'z') { + firstCharKey = c - 'a' + 26; + } else if (c >= 'A' && c <= 'Z') { + firstCharKey = c - 'A'; + } else { + if (c == ';') { + if (P::reportErrors) { + errNoNamedCharacterMatch(); + } + } + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + appendCharRefBuf(c); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CHARACTER_REFERENCE_HILO_LOOKUP, + reconsume, pos); + break; + } + } + [[fallthrough]]; + } + case CHARACTER_REFERENCE_HILO_LOOKUP: { + { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + int32_t hilo = 0; + if (c <= 'z') { + const int32_t* row = nsHtml5NamedCharactersAccel::HILO_ACCEL[c]; + if (row) { + hilo = row[firstCharKey]; + } + } + if (!hilo) { + if (c == ';') { + if (P::reportErrors) { + errNoNamedCharacterMatch(); + } + } + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + appendCharRefBuf(c); + lo = hilo & 0xFFFF; + hi = hilo >> 16; + entCol = -1; + candidate = -1; + charRefBufMark = 0; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::CHARACTER_REFERENCE_TAIL, + reconsume, pos); + } + [[fallthrough]]; + } + case CHARACTER_REFERENCE_TAIL: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + entCol++; + for (;;) { + if (hi < lo) { + NS_HTML5_BREAK(outer); + } + if (entCol == nsHtml5NamedCharacters::NAMES[lo].length()) { + candidate = lo; + charRefBufMark = charRefBufLen; + lo++; + } else if (entCol > nsHtml5NamedCharacters::NAMES[lo].length()) { + NS_HTML5_BREAK(outer); + } else if (c > nsHtml5NamedCharacters::NAMES[lo].charAt(entCol)) { + lo++; + } else { + NS_HTML5_BREAK(loloop); + } + } + loloop_end:; + for (;;) { + if (hi < lo) { + NS_HTML5_BREAK(outer); + } + if (entCol == nsHtml5NamedCharacters::NAMES[hi].length()) { + NS_HTML5_BREAK(hiloop); + } + if (entCol > nsHtml5NamedCharacters::NAMES[hi].length()) { + NS_HTML5_BREAK(outer); + } else if (c < nsHtml5NamedCharacters::NAMES[hi].charAt(entCol)) { + hi--; + } else { + NS_HTML5_BREAK(hiloop); + } + } + hiloop_end:; + if (c == ';') { + if (entCol + 1 == nsHtml5NamedCharacters::NAMES[lo].length()) { + candidate = lo; + charRefBufMark = charRefBufLen; + } + NS_HTML5_BREAK(outer); + } + if (hi < lo) { + NS_HTML5_BREAK(outer); + } + appendCharRefBuf(c); + continue; + } + outer_end:; + if (candidate == -1) { + if (c == ';') { + if (P::reportErrors) { + errNoNamedCharacterMatch(); + } + } + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } else { + const nsHtml5CharacterName& candidateName = + nsHtml5NamedCharacters::NAMES[candidate]; + if (!candidateName.length() || + candidateName.charAt(candidateName.length() - 1) != ';') { + if ((returnState & DATA_AND_RCDATA_MASK)) { + char16_t ch; + if (charRefBufMark == charRefBufLen) { + ch = c; + } else { + ch = charRefBuf[charRefBufMark]; + } + if (ch == '=' || (ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { + if (c == ';') { + if (P::reportErrors) { + errNoNamedCharacterMatch(); + } + } + appendCharRefBufToStrBuf(); + reconsume = true; + state = P::transition(mViewSource.get(), returnState, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + if ((returnState & DATA_AND_RCDATA_MASK)) { + if (P::reportErrors) { + errUnescapedAmpersandInterpretedAsCharacterReference(); + } + } else { + if (P::reportErrors) { + errNotSemicolonTerminated(); + } + } + } + P::completedNamedCharacterReference(mViewSource.get()); + const char16_t* val = nsHtml5NamedCharacters::VALUES[candidate]; + if (!val[1]) { + emitOrAppendOne(val, returnState); + } else { + emitOrAppendTwo(val, returnState); + } + if (charRefBufMark < charRefBufLen) { + if ((returnState & DATA_AND_RCDATA_MASK)) { + appendStrBuf(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } else { + tokenHandler->characters(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } + } + bool earlyBreak = (c == ';' && charRefBufMark == charRefBufLen); + charRefBufLen = 0; + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = earlyBreak ? pos + 1 : pos; + } + reconsume = !earlyBreak; + state = P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + case CONSUME_NCR: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + value = 0; + seenDigits = false; + switch (c) { + case 'x': + case 'X': { + appendCharRefBuf(c); + state = + P::transition(mViewSource.get(), nsHtml5Tokenizer::HEX_NCR_LOOP, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + default: { + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::DECIMAL_NRC_LOOP, reconsume, + pos); + break; + } + } + [[fallthrough]]; + } + case DECIMAL_NRC_LOOP: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + MOZ_ASSERT(value >= 0, "value must not become negative."); + if (c >= '0' && c <= '9') { + seenDigits = true; + if (value <= 0x10FFFF) { + value *= 10; + value += c - '0'; + } + continue; + } else if (c == ';') { + if (seenDigits) { + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos + 1; + } + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::HANDLE_NCR_VALUE, + reconsume, pos); + NS_HTML5_BREAK(decimalloop); + } else { + if (P::reportErrors) { + errNoDigitsInNCR(); + } + appendCharRefBuf(';'); + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos + 1; + } + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } else { + if (!seenDigits) { + if (P::reportErrors) { + errNoDigitsInNCR(); + } + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } else { + if (P::reportErrors) { + errCharRefLacksSemicolon(); + } + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::HANDLE_NCR_VALUE, + reconsume, pos); + NS_HTML5_BREAK(decimalloop); + } + } + } + decimalloop_end:; + [[fallthrough]]; + } + case HANDLE_NCR_VALUE: { + charRefBufLen = 0; + handleNcrValue(returnState); + state = P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case HEX_NCR_LOOP: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + MOZ_ASSERT(value >= 0, "value must not become negative."); + if (c >= '0' && c <= '9') { + seenDigits = true; + if (value <= 0x10FFFF) { + value *= 16; + value += c - '0'; + } + continue; + } else if (c >= 'A' && c <= 'F') { + seenDigits = true; + if (value <= 0x10FFFF) { + value *= 16; + value += c - 'A' + 10; + } + continue; + } else if (c >= 'a' && c <= 'f') { + seenDigits = true; + if (value <= 0x10FFFF) { + value *= 16; + value += c - 'a' + 10; + } + continue; + } else if (c == ';') { + if (seenDigits) { + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos + 1; + } + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::HANDLE_NCR_VALUE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } else { + if (P::reportErrors) { + errNoDigitsInNCR(); + } + appendCharRefBuf(';'); + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos + 1; + } + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } else { + if (!seenDigits) { + if (P::reportErrors) { + errNoDigitsInNCR(); + } + emitOrAppendCharRefBuf(returnState); + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } else { + if (P::reportErrors) { + errCharRefLacksSemicolon(); + } + if (!(returnState & DATA_AND_RCDATA_MASK)) { + cstart = pos; + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::HANDLE_NCR_VALUE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + case PLAINTEXT: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\0': { + emitPlaintextReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + } + case CLOSE_TAG_OPEN: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '>': { + if (P::reportErrors) { + errLtSlashGt(); + } + cstart = pos + 1; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + silentCarriageReturn(); + if (P::reportErrors) { + errGarbageAfterLtSlash(); + } + clearStrBufBeforeUse(); + appendStrBuf('\n'); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + if (P::reportErrors) { + errGarbageAfterLtSlash(); + } + clearStrBufBeforeUse(); + appendStrBuf(c); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + if (c >= 'A' && c <= 'Z') { + c += 0x20; + } + if (c >= 'a' && c <= 'z') { + endTag = true; + clearStrBufBeforeUse(); + appendStrBuf(c); + containsHyphen = false; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::TAG_NAME, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } else { + if (P::reportErrors) { + errGarbageAfterLtSlash(); + } + clearStrBufBeforeUse(); + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + case RCDATA: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '&': { + flushChars(buf, pos); + MOZ_ASSERT(!charRefBufLen, + "charRefBufLen not reset after previous use!"); + appendCharRefBuf(c); + setAdditionalAndRememberAmpersandLocation('\0'); + returnState = state; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '<': { + flushChars(buf, pos); + returnState = state; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + } + case RAWTEXT: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '<': { + flushChars(buf, pos); + returnState = state; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_BREAK(rawtextloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + rawtextloop_end:; + [[fallthrough]]; + } + case RAWTEXT_RCDATA_LESS_THAN_SIGN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '/': { + index = 0; + clearStrBufBeforeUse(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::NON_DATA_END_TAG_NAME, + reconsume, pos); + NS_HTML5_BREAK(rawtextrcdatalessthansignloop); + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + cstart = pos; + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + rawtextrcdatalessthansignloop_end:; + [[fallthrough]]; + } + case NON_DATA_END_TAG_NAME: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + if (!endTagExpectationAsArray) { + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + cstart = pos; + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } else if (index < endTagExpectationAsArray.length) { + char16_t e = endTagExpectationAsArray[index]; + char16_t folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != e) { + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + emitStrBuf(); + cstart = pos; + reconsume = true; + state = + P::transition(mViewSource.get(), returnState, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + appendStrBuf(c); + index++; + continue; + } else { + endTag = true; + tagName = endTagExpectation; + switch (c) { + case '\r': { + silentCarriageReturn(); + clearStrBufAfterUse(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + clearStrBufAfterUse(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '/': { + clearStrBufAfterUse(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SELF_CLOSING_START_TAG, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + clearStrBufAfterUse(); + state = P::transition(mViewSource.get(), + emitCurrentTagToken(false, pos), + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + emitStrBuf(); + cstart = pos; + reconsume = true; + state = P::transition(mViewSource.get(), returnState, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + } + case BOGUS_COMMENT: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '>': { + emitComment(0, pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '-': { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT_HYPHEN, + reconsume, pos); + NS_HTML5_BREAK(boguscommentloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + boguscommentloop_end:; + [[fallthrough]]; + } + case BOGUS_COMMENT_HYPHEN: { + boguscommenthyphenloop: + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '>': { + emitComment(0, pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '-': { + appendSecondHyphenToBogusComment(); + NS_HTML5_CONTINUE(boguscommenthyphenloop); + } + case '\r': { + appendStrBufCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + case SCRIPT_DATA: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '<': { + flushChars(buf, pos); + returnState = state; + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_LESS_THAN_SIGN, reconsume, pos); + NS_HTML5_BREAK(scriptdataloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + scriptdataloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_LESS_THAN_SIGN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '/': { + index = 0; + clearStrBufBeforeUse(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::NON_DATA_END_TAG_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '!': { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + cstart = pos; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPE_START, + reconsume, pos); + NS_HTML5_BREAK(scriptdatalessthansignloop); + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + cstart = pos; + reconsume = true; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdatalessthansignloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_ESCAPE_START: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPE_START_DASH, + reconsume, pos); + NS_HTML5_BREAK(scriptdataescapestartloop); + } + default: { + reconsume = true; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdataescapestartloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_ESCAPE_START_DASH: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH, + reconsume, pos); + NS_HTML5_BREAK(scriptdataescapestartdashloop); + } + default: { + reconsume = true; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdataescapestartdashloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_ESCAPED_DASH_DASH: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + continue; + } + case '<': { + flushChars(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_BREAK(scriptdataescapeddashdashloop); + } + case '\r': { + emitCarriageReturn(buf, pos); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_BREAK(scriptdataescapeddashdashloop); + } + } + } + scriptdataescapeddashdashloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_ESCAPED: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '-': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH, + reconsume, pos); + NS_HTML5_BREAK(scriptdataescapedloop); + } + case '<': { + flushChars(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + scriptdataescapedloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_ESCAPED_DASH: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '<': { + flushChars(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_BREAK(scriptdataescapeddashloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + emitCarriageReturn(buf, pos); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdataescapeddashloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '/': { + index = 0; + clearStrBufBeforeUse(); + returnState = nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::NON_DATA_END_TAG_NAME, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case 'S': + case 's': { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + cstart = pos; + index = 1; + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPE_START, reconsume, + pos); + NS_HTML5_BREAK(scriptdataescapedlessthanloop); + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + cstart = pos; + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdataescapedlessthanloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_DOUBLE_ESCAPE_START: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + MOZ_ASSERT(index > 0); + if (index < 6) { + char16_t folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != nsHtml5Tokenizer::SCRIPT_ARR[index]) { + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + index++; + continue; + } + switch (c) { + case '\r': { + emitCarriageReturn(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': + case '/': + case '>': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_BREAK(scriptdatadoubleescapestartloop); + } + default: { + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdatadoubleescapestartloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_DOUBLE_ESCAPED: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '-': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_DASH, reconsume, + pos); + NS_HTML5_BREAK(scriptdatadoubleescapedloop); + } + case '<': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + scriptdatadoubleescapedloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH, + reconsume, pos); + NS_HTML5_BREAK(scriptdatadoubleescapeddashloop); + } + case '<': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + emitCarriageReturn(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdatadoubleescapeddashloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '-': { + continue; + } + case '<': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, + reconsume, pos); + NS_HTML5_BREAK(scriptdatadoubleescapeddashdashloop); + } + case '>': { + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + emitReplacementCharacter(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + emitCarriageReturn(buf, pos); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdatadoubleescapeddashdashloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '/': { + index = 0; + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPE_END, + reconsume, pos); + NS_HTML5_BREAK(scriptdatadoubleescapedlessthanloop); + } + default: { + reconsume = true; + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + scriptdatadoubleescapedlessthanloop_end:; + [[fallthrough]]; + } + case SCRIPT_DATA_DOUBLE_ESCAPE_END: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + if (index < 6) { + char16_t folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != nsHtml5Tokenizer::SCRIPT_ARR[index]) { + reconsume = true; + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + index++; + continue; + } + switch (c) { + case '\r': { + emitCarriageReturn(buf, pos); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': + case '/': + case '>': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + default: { + reconsume = true; + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + case MARKUP_DECLARATION_OCTYPE: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + if (index < 6) { + char16_t folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded == nsHtml5Tokenizer::OCTYPE[index]) { + appendStrBuf(c); + } else { + if (P::reportErrors) { + errBogusComment(); + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + index++; + continue; + } else { + reconsume = true; + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DOCTYPE, + reconsume, pos); + NS_HTML5_BREAK(markupdeclarationdoctypeloop); + } + } + markupdeclarationdoctypeloop_end:; + [[fallthrough]]; + } + case DOCTYPE: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + initDoctypeFields(); + switch (c) { + case '\r': { + silentCarriageReturn(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME, + reconsume, pos); + NS_HTML5_BREAK(doctypeloop); + } + default: { + if (P::reportErrors) { + errMissingSpaceBeforeDoctypeName(); + } + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME, + reconsume, pos); + NS_HTML5_BREAK(doctypeloop); + } + } + } + doctypeloop_end:; + [[fallthrough]]; + } + case BEFORE_DOCTYPE_NAME: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '>': { + if (P::reportErrors) { + errNamelessDoctype(); + } + forceQuirks = true; + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + if (c >= 'A' && c <= 'Z') { + c += 0x20; + } + clearStrBufBeforeUse(); + appendStrBuf(c); + state = + P::transition(mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_NAME, reconsume, pos); + NS_HTML5_BREAK(beforedoctypenameloop); + } + } + } + beforedoctypenameloop_end:; + [[fallthrough]]; + } + case DOCTYPE_NAME: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + strBufToDoctypeName(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_NAME, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + strBufToDoctypeName(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_NAME, + reconsume, pos); + NS_HTML5_BREAK(doctypenameloop); + } + case '>': { + strBufToDoctypeName(); + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + if (c >= 'A' && c <= 'Z') { + c += 0x0020; + } + appendStrBuf(c); + continue; + } + } + } + doctypenameloop_end:; + [[fallthrough]]; + } + case AFTER_DOCTYPE_NAME: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '>': { + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case 'p': + case 'P': { + index = 0; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_UBLIC, reconsume, + pos); + NS_HTML5_BREAK(afterdoctypenameloop); + } + case 's': + case 'S': { + index = 0; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_YSTEM, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctype(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + afterdoctypenameloop_end:; + [[fallthrough]]; + } + case DOCTYPE_UBLIC: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + if (index < 5) { + char16_t folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != nsHtml5Tokenizer::UBLIC[index]) { + bogusDoctype(); + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + index++; + continue; + } else { + reconsume = true; + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_KEYWORD, reconsume, pos); + NS_HTML5_BREAK(doctypeublicloop); + } + } + doctypeublicloop_end:; + [[fallthrough]]; + } + case AFTER_DOCTYPE_PUBLIC_KEYWORD: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\r': { + silentCarriageReturn(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, + pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, + pos); + NS_HTML5_BREAK(afterdoctypepublickeywordloop); + } + case '\"': { + if (P::reportErrors) { + errNoSpaceBetweenDoctypePublicKeywordAndQuote(); + } + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\'': { + if (P::reportErrors) { + errNoSpaceBetweenDoctypePublicKeywordAndQuote(); + } + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errExpectedPublicId(); + } + forceQuirks = true; + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctype(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + afterdoctypepublickeywordloop_end:; + [[fallthrough]]; + } + case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '\"': { + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, + reconsume, pos); + NS_HTML5_BREAK(beforedoctypepublicidentifierloop); + } + case '\'': { + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errExpectedPublicId(); + } + forceQuirks = true; + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctype(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + beforedoctypepublicidentifierloop_end:; + [[fallthrough]]; + } + case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\"': { + publicIdentifier = strBufToString(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, + pos); + NS_HTML5_BREAK(doctypepublicidentifierdoublequotedloop); + } + case '>': { + if (P::reportErrors) { + errGtInPublicId(); + } + forceQuirks = true; + publicIdentifier = strBufToString(); + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + doctypepublicidentifierdoublequotedloop_end:; + [[fallthrough]]; + } + case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer:: + BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS, + reconsume, pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer:: + BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS, + reconsume, pos); + NS_HTML5_BREAK(afterdoctypepublicidentifierloop); + } + case '>': { + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\"': { + if (P::reportErrors) { + errNoSpaceBetweenPublicAndSystemIds(); + } + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\'': { + if (P::reportErrors) { + errNoSpaceBetweenPublicAndSystemIds(); + } + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctype(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + afterdoctypepublicidentifierloop_end:; + [[fallthrough]]; + } + case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '>': { + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\"': { + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, + reconsume, pos); + NS_HTML5_BREAK(betweendoctypepublicandsystemidentifiersloop); + } + case '\'': { + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctype(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + betweendoctypepublicandsystemidentifiersloop_end:; + [[fallthrough]]; + } + case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\"': { + systemIdentifier = strBufToString(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, + pos); + NS_HTML5_BREAK(doctypesystemidentifierdoublequotedloop); + } + case '>': { + if (P::reportErrors) { + errGtInSystemId(); + } + forceQuirks = true; + systemIdentifier = strBufToString(); + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + doctypesystemidentifierdoublequotedloop_end:; + [[fallthrough]]; + } + case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '>': { + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctypeWithoutQuirks(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_BREAK(afterdoctypesystemidentifierloop); + } + } + } + afterdoctypesystemidentifierloop_end:; + [[fallthrough]]; + } + case BOGUS_DOCTYPE: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '>': { + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + default: { + continue; + } + } + } + } + case DOCTYPE_YSTEM: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + if (index < 5) { + char16_t folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != nsHtml5Tokenizer::YSTEM[index]) { + bogusDoctype(); + reconsume = true; + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + index++; + NS_HTML5_CONTINUE(stateloop); + } else { + reconsume = true; + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_KEYWORD, reconsume, pos); + NS_HTML5_BREAK(doctypeystemloop); + } + } + doctypeystemloop_end:; + [[fallthrough]]; + } + case AFTER_DOCTYPE_SYSTEM_KEYWORD: { + for (;;) { + if (reconsume) { + reconsume = false; + } else { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + } + switch (c) { + case '\r': { + silentCarriageReturn(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, + pos); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, + pos); + NS_HTML5_BREAK(afterdoctypesystemkeywordloop); + } + case '\"': { + if (P::reportErrors) { + errNoSpaceBetweenDoctypeSystemKeywordAndQuote(); + } + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\'': { + if (P::reportErrors) { + errNoSpaceBetweenDoctypeSystemKeywordAndQuote(); + } + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errExpectedPublicId(); + } + forceQuirks = true; + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctype(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + afterdoctypesystemkeywordloop_end:; + [[fallthrough]]; + } + case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\r': { + silentCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + silentLineFeed(); + [[fallthrough]]; + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '\"': { + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + case '\'': { + clearStrBufBeforeUse(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, + reconsume, pos); + NS_HTML5_BREAK(beforedoctypesystemidentifierloop); + } + case '>': { + if (P::reportErrors) { + errExpectedSystemId(); + } + forceQuirks = true; + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + bogusDoctype(); + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + beforedoctypesystemidentifierloop_end:; + [[fallthrough]]; + } + case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\'': { + systemIdentifier = strBufToString(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errGtInSystemId(); + } + forceQuirks = true; + systemIdentifier = strBufToString(); + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + } + case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\'': { + publicIdentifier = strBufToString(); + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, + pos); + NS_HTML5_CONTINUE(stateloop); + } + case '>': { + if (P::reportErrors) { + errGtInPublicId(); + } + forceQuirks = true; + publicIdentifier = strBufToString(); + emitDoctypeToken(pos); + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + case '\r': { + appendStrBufCarriageReturn(); + NS_HTML5_BREAK(stateloop); + } + case '\n': { + appendStrBufLineFeed(); + continue; + } + case '\0': { + c = 0xfffd; + [[fallthrough]]; + } + default: { + appendStrBuf(c); + continue; + } + } + } + } + case PROCESSING_INSTRUCTION: { + for (;;) { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '\?': { + state = P::transition( + mViewSource.get(), + nsHtml5Tokenizer::PROCESSING_INSTRUCTION_QUESTION_MARK, + reconsume, pos); + NS_HTML5_BREAK(processinginstructionloop); + } + default: { + continue; + } + } + } + processinginstructionloop_end:; + [[fallthrough]]; + } + case PROCESSING_INSTRUCTION_QUESTION_MARK: { + if (++pos == endPos) { + NS_HTML5_BREAK(stateloop); + } + c = checkChar(buf, pos); + switch (c) { + case '>': { + state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA, + reconsume, pos); + suspendIfRequestedAfterCurrentNonTextToken(); + if (shouldSuspend) { + NS_HTML5_BREAK(stateloop); + } + NS_HTML5_CONTINUE(stateloop); + } + default: { + state = P::transition(mViewSource.get(), + nsHtml5Tokenizer::PROCESSING_INSTRUCTION, + reconsume, pos); + NS_HTML5_CONTINUE(stateloop); + } + } + } + } + } +stateloop_end:; + flushChars(buf, pos); + stateSave = state; + returnStateSave = returnState; + return pos; +} + +void nsHtml5Tokenizer::initDoctypeFields() { + clearStrBufAfterUse(); + doctypeName = nullptr; + if (systemIdentifier) { + systemIdentifier.Release(); + systemIdentifier = nullptr; + } + if (publicIdentifier) { + publicIdentifier.Release(); + publicIdentifier = nullptr; + } + forceQuirks = false; +} + +void nsHtml5Tokenizer::emitCarriageReturn(char16_t* buf, int32_t pos) { + silentCarriageReturn(); + flushChars(buf, pos); + tokenHandler->characters(nsHtml5Tokenizer::LF, 0, 1); + cstart = INT32_MAX; +} + +void nsHtml5Tokenizer::emitReplacementCharacter(char16_t* buf, int32_t pos) { + flushChars(buf, pos); + tokenHandler->zeroOriginatingReplacementCharacter(); + cstart = pos + 1; +} + +void nsHtml5Tokenizer::maybeEmitReplacementCharacter(char16_t* buf, + int32_t pos) { + flushChars(buf, pos); + tokenHandler->zeroOrReplacementCharacter(); + cstart = pos + 1; +} + +void nsHtml5Tokenizer::emitPlaintextReplacementCharacter(char16_t* buf, + int32_t pos) { + flushChars(buf, pos); + tokenHandler->characters(REPLACEMENT_CHARACTER, 0, 1); + cstart = pos + 1; +} + +void nsHtml5Tokenizer::setAdditionalAndRememberAmpersandLocation(char16_t add) { + additional = add; +} + +void nsHtml5Tokenizer::bogusDoctype() { + errBogusDoctype(); + forceQuirks = true; +} + +void nsHtml5Tokenizer::bogusDoctypeWithoutQuirks() { + errBogusDoctype(); + forceQuirks = false; +} + +void nsHtml5Tokenizer::handleNcrValue(int32_t returnState) { + if (value <= 0xFFFF) { + if (value >= 0x80 && value <= 0x9f) { + errNcrInC1Range(); + char16_t* val = nsHtml5NamedCharacters::WINDOWS_1252[value - 0x80]; + emitOrAppendOne(val, returnState); + } else if (value == 0x0) { + errNcrZero(); + emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState); + } else if ((value & 0xF800) == 0xD800) { + errNcrSurrogate(); + emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState); + } else { + char16_t ch = (char16_t)value; + bmpChar[0] = ch; + emitOrAppendOne(bmpChar, returnState); + } + } else if (value <= 0x10FFFF) { + astralChar[0] = (char16_t)(nsHtml5Tokenizer::LEAD_OFFSET + (value >> 10)); + astralChar[1] = (char16_t)(0xDC00 + (value & 0x3FF)); + emitOrAppendTwo(astralChar, returnState); + } else { + errNcrOutOfRange(); + emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState); + } +} + +void nsHtml5Tokenizer::eof() { + int32_t state = stateSave; + int32_t returnState = returnStateSave; +eofloop: + for (;;) { + switch (state) { + case SCRIPT_DATA_LESS_THAN_SIGN: + case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + NS_HTML5_BREAK(eofloop); + } + case TAG_OPEN: { + errEofAfterLt(); + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + NS_HTML5_BREAK(eofloop); + } + case RAWTEXT_RCDATA_LESS_THAN_SIGN: { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + NS_HTML5_BREAK(eofloop); + } + case NON_DATA_END_TAG_NAME: { + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + emitStrBuf(); + NS_HTML5_BREAK(eofloop); + } + case CLOSE_TAG_OPEN: { + errEofAfterLt(); + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + NS_HTML5_BREAK(eofloop); + } + case TAG_NAME: { + errEofInTagName(); + NS_HTML5_BREAK(eofloop); + } + case BEFORE_ATTRIBUTE_NAME: + case AFTER_ATTRIBUTE_VALUE_QUOTED: + case SELF_CLOSING_START_TAG: { + errEofWithoutGt(); + NS_HTML5_BREAK(eofloop); + } + case ATTRIBUTE_NAME: { + errEofInAttributeName(); + NS_HTML5_BREAK(eofloop); + } + case AFTER_ATTRIBUTE_NAME: + case BEFORE_ATTRIBUTE_VALUE: { + errEofWithoutGt(); + NS_HTML5_BREAK(eofloop); + } + case ATTRIBUTE_VALUE_DOUBLE_QUOTED: + case ATTRIBUTE_VALUE_SINGLE_QUOTED: + case ATTRIBUTE_VALUE_UNQUOTED: { + errEofInAttributeValue(); + NS_HTML5_BREAK(eofloop); + } + case BOGUS_COMMENT: { + emitComment(0, 0); + NS_HTML5_BREAK(eofloop); + } + case BOGUS_COMMENT_HYPHEN: { + emitComment(0, 0); + NS_HTML5_BREAK(eofloop); + } + case MARKUP_DECLARATION_OPEN: { + errBogusComment(); + emitComment(0, 0); + NS_HTML5_BREAK(eofloop); + } + case MARKUP_DECLARATION_HYPHEN: { + errBogusComment(); + emitComment(0, 0); + NS_HTML5_BREAK(eofloop); + } + case MARKUP_DECLARATION_OCTYPE: { + if (index < 6) { + errBogusComment(); + emitComment(0, 0); + } else { + errEofInDoctype(); + doctypeName = nullptr; + if (systemIdentifier) { + systemIdentifier.Release(); + systemIdentifier = nullptr; + } + if (publicIdentifier) { + publicIdentifier.Release(); + publicIdentifier = nullptr; + } + forceQuirks = true; + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + NS_HTML5_BREAK(eofloop); + } + case COMMENT_START: + case COMMENT: + case COMMENT_LESSTHAN: + case COMMENT_LESSTHAN_BANG: { + errEofInComment(); + emitComment(0, 0); + NS_HTML5_BREAK(eofloop); + } + case COMMENT_END: + case COMMENT_LESSTHAN_BANG_DASH_DASH: { + errEofInComment(); + emitComment(2, 0); + NS_HTML5_BREAK(eofloop); + } + case COMMENT_END_DASH: + case COMMENT_START_DASH: + case COMMENT_LESSTHAN_BANG_DASH: { + errEofInComment(); + emitComment(1, 0); + NS_HTML5_BREAK(eofloop); + } + case COMMENT_END_BANG: { + errEofInComment(); + emitComment(3, 0); + NS_HTML5_BREAK(eofloop); + } + case DOCTYPE: + case BEFORE_DOCTYPE_NAME: { + errEofInDoctype(); + forceQuirks = true; + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case DOCTYPE_NAME: { + errEofInDoctype(); + strBufToDoctypeName(); + forceQuirks = true; + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case DOCTYPE_UBLIC: + case DOCTYPE_YSTEM: + case AFTER_DOCTYPE_NAME: + case AFTER_DOCTYPE_PUBLIC_KEYWORD: + case AFTER_DOCTYPE_SYSTEM_KEYWORD: + case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: { + errEofInDoctype(); + forceQuirks = true; + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: { + errEofInPublicId(); + forceQuirks = true; + publicIdentifier = strBufToString(); + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: + case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: { + errEofInDoctype(); + forceQuirks = true; + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: { + errEofInSystemId(); + forceQuirks = true; + systemIdentifier = strBufToString(); + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: { + errEofInDoctype(); + forceQuirks = true; + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case BOGUS_DOCTYPE: { + emitDoctypeToken(0); + NS_HTML5_BREAK(eofloop); + } + case CONSUME_CHARACTER_REFERENCE: { + emitOrAppendCharRefBuf(returnState); + state = returnState; + continue; + } + case CHARACTER_REFERENCE_HILO_LOOKUP: { + emitOrAppendCharRefBuf(returnState); + state = returnState; + continue; + } + case CHARACTER_REFERENCE_TAIL: { + for (;;) { + char16_t c = '\0'; + entCol++; + for (;;) { + if (hi == -1) { + NS_HTML5_BREAK(hiloop); + } + if (entCol == nsHtml5NamedCharacters::NAMES[hi].length()) { + NS_HTML5_BREAK(hiloop); + } + if (entCol > nsHtml5NamedCharacters::NAMES[hi].length()) { + NS_HTML5_BREAK(outer); + } else if (c < nsHtml5NamedCharacters::NAMES[hi].charAt(entCol)) { + hi--; + } else { + NS_HTML5_BREAK(hiloop); + } + } + hiloop_end:; + for (;;) { + if (hi < lo) { + NS_HTML5_BREAK(outer); + } + if (entCol == nsHtml5NamedCharacters::NAMES[lo].length()) { + candidate = lo; + charRefBufMark = charRefBufLen; + lo++; + } else if (entCol > nsHtml5NamedCharacters::NAMES[lo].length()) { + NS_HTML5_BREAK(outer); + } else if (c > nsHtml5NamedCharacters::NAMES[lo].charAt(entCol)) { + lo++; + } else { + NS_HTML5_BREAK(loloop); + } + } + loloop_end:; + if (hi < lo) { + NS_HTML5_BREAK(outer); + } + continue; + } + outer_end:; + if (candidate == -1) { + emitOrAppendCharRefBuf(returnState); + state = returnState; + NS_HTML5_CONTINUE(eofloop); + } else { + const nsHtml5CharacterName& candidateName = + nsHtml5NamedCharacters::NAMES[candidate]; + if (!candidateName.length() || + candidateName.charAt(candidateName.length() - 1) != ';') { + if ((returnState & DATA_AND_RCDATA_MASK)) { + char16_t ch; + if (charRefBufMark == charRefBufLen) { + ch = '\0'; + } else { + ch = charRefBuf[charRefBufMark]; + } + if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || + (ch >= 'a' && ch <= 'z')) { + appendCharRefBufToStrBuf(); + state = returnState; + NS_HTML5_CONTINUE(eofloop); + } + } + if ((returnState & DATA_AND_RCDATA_MASK)) { + errUnescapedAmpersandInterpretedAsCharacterReference(); + } else { + errNotSemicolonTerminated(); + } + } + const char16_t* val = nsHtml5NamedCharacters::VALUES[candidate]; + if (!val[1]) { + emitOrAppendOne(val, returnState); + } else { + emitOrAppendTwo(val, returnState); + } + if (charRefBufMark < charRefBufLen) { + if ((returnState & DATA_AND_RCDATA_MASK)) { + appendStrBuf(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } else { + tokenHandler->characters(charRefBuf, charRefBufMark, + charRefBufLen - charRefBufMark); + } + } + charRefBufLen = 0; + state = returnState; + NS_HTML5_CONTINUE(eofloop); + } + } + case CONSUME_NCR: + case DECIMAL_NRC_LOOP: + case HEX_NCR_LOOP: { + if (!seenDigits) { + errNoDigitsInNCR(); + emitOrAppendCharRefBuf(returnState); + state = returnState; + continue; + } else { + errCharRefLacksSemicolon(); + } + handleNcrValue(returnState); + state = returnState; + continue; + } + case CDATA_RSQB: { + tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1); + NS_HTML5_BREAK(eofloop); + } + case CDATA_RSQB_RSQB: { + tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 2); + NS_HTML5_BREAK(eofloop); + } + case DATA: + default: { + NS_HTML5_BREAK(eofloop); + } + } + } +eofloop_end:; + tokenHandler->eof(); + return; +} + +void nsHtml5Tokenizer::emitDoctypeToken(int32_t pos) { + RememberGt(pos); + cstart = pos + 1; + tokenHandler->doctype(doctypeName, publicIdentifier, systemIdentifier, + forceQuirks); + doctypeName = nullptr; + publicIdentifier.Release(); + publicIdentifier = nullptr; + systemIdentifier.Release(); + systemIdentifier = nullptr; + suspendIfRequestedAfterCurrentNonTextToken(); +} + +void nsHtml5Tokenizer::suspendIfRequestedAfterCurrentNonTextToken() { + if (suspendAfterCurrentNonTextToken) { + suspendAfterCurrentNonTextToken = false; + shouldSuspend = true; + } +} + +void nsHtml5Tokenizer::suspendAfterCurrentTokenIfNotInText() { + switch (stateSave) { + case DATA: + case RCDATA: + case SCRIPT_DATA: + case RAWTEXT: + case SCRIPT_DATA_ESCAPED: + case PLAINTEXT: + case NON_DATA_END_TAG_NAME: + case SCRIPT_DATA_LESS_THAN_SIGN: + case SCRIPT_DATA_ESCAPE_START: + case SCRIPT_DATA_ESCAPE_START_DASH: + case SCRIPT_DATA_ESCAPED_DASH: + case SCRIPT_DATA_ESCAPED_DASH_DASH: + case RAWTEXT_RCDATA_LESS_THAN_SIGN: + case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: + case SCRIPT_DATA_DOUBLE_ESCAPE_START: + case SCRIPT_DATA_DOUBLE_ESCAPED: + case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: + case SCRIPT_DATA_DOUBLE_ESCAPE_END: { + return; + } + case TAG_NAME: + case BEFORE_ATTRIBUTE_NAME: + case ATTRIBUTE_NAME: + case AFTER_ATTRIBUTE_NAME: + case BEFORE_ATTRIBUTE_VALUE: + case AFTER_ATTRIBUTE_VALUE_QUOTED: + case BOGUS_COMMENT: + case MARKUP_DECLARATION_OPEN: + case DOCTYPE: + case BEFORE_DOCTYPE_NAME: + case DOCTYPE_NAME: + case AFTER_DOCTYPE_NAME: + case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: + case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: + case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: + case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: + case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: + case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: + case BOGUS_DOCTYPE: + case COMMENT_START: + case COMMENT_START_DASH: + case COMMENT: + case COMMENT_END_DASH: + case COMMENT_END: + case COMMENT_END_BANG: + case TAG_OPEN: + case CLOSE_TAG_OPEN: + case MARKUP_DECLARATION_HYPHEN: + case MARKUP_DECLARATION_OCTYPE: + case DOCTYPE_UBLIC: + case DOCTYPE_YSTEM: + case AFTER_DOCTYPE_PUBLIC_KEYWORD: + case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: + case AFTER_DOCTYPE_SYSTEM_KEYWORD: + case SELF_CLOSING_START_TAG: + case ATTRIBUTE_VALUE_DOUBLE_QUOTED: + case ATTRIBUTE_VALUE_SINGLE_QUOTED: + case ATTRIBUTE_VALUE_UNQUOTED: + case BOGUS_COMMENT_HYPHEN: + case COMMENT_LESSTHAN: + case COMMENT_LESSTHAN_BANG: + case COMMENT_LESSTHAN_BANG_DASH: + case COMMENT_LESSTHAN_BANG_DASH_DASH: + case CDATA_START: + case CDATA_SECTION: + case CDATA_RSQB: + case CDATA_RSQB_RSQB: + case PROCESSING_INSTRUCTION: + case PROCESSING_INSTRUCTION_QUESTION_MARK: { + break; + } + case CONSUME_CHARACTER_REFERENCE: + case CONSUME_NCR: + case CHARACTER_REFERENCE_TAIL: + case HEX_NCR_LOOP: + case DECIMAL_NRC_LOOP: + case HANDLE_NCR_VALUE: + case HANDLE_NCR_VALUE_RECONSUME: + case CHARACTER_REFERENCE_HILO_LOOKUP: { + if (returnStateSave == DATA || returnStateSave == RCDATA) { + return; + } + break; + } + default: { + MOZ_ASSERT(false, "Incomplete switch"); + return; + } + } + suspendAfterCurrentNonTextToken = true; +} + +bool nsHtml5Tokenizer::suspensionAfterCurrentNonTextTokenPending() { + return suspendAfterCurrentNonTextToken; +} + +bool nsHtml5Tokenizer::internalEncodingDeclaration( + nsHtml5String internalCharset) { + if (encodingDeclarationHandler) { + return encodingDeclarationHandler->internalEncodingDeclaration( + internalCharset); + } + return false; +} + +void nsHtml5Tokenizer::emitOrAppendTwo(const char16_t* val, + int32_t returnState) { + if ((returnState & DATA_AND_RCDATA_MASK)) { + appendStrBuf(val[0]); + appendStrBuf(val[1]); + } else { + tokenHandler->characters(val, 0, 2); + } +} + +void nsHtml5Tokenizer::emitOrAppendOne(const char16_t* val, + int32_t returnState) { + if ((returnState & DATA_AND_RCDATA_MASK)) { + appendStrBuf(val[0]); + } else { + tokenHandler->characters(val, 0, 1); + } +} + +void nsHtml5Tokenizer::end() { + strBuf = nullptr; + doctypeName = nullptr; + if (systemIdentifier) { + systemIdentifier.Release(); + systemIdentifier = nullptr; + } + if (publicIdentifier) { + publicIdentifier.Release(); + publicIdentifier = nullptr; + } + tagName = nullptr; + nonInternedTagName->setNameForNonInterned(nullptr, false); + attributeName = nullptr; + nonInternedAttributeName->setNameForNonInterned(nullptr); + tokenHandler->endTokenization(); + if (attributes) { + attributes->clear(0); + } +} + +void nsHtml5Tokenizer::requestSuspension() { shouldSuspend = true; } + +bool nsHtml5Tokenizer::isInDataState() { return (stateSave == DATA); } + +void nsHtml5Tokenizer::resetToDataState() { + clearStrBufAfterUse(); + charRefBufLen = 0; + stateSave = nsHtml5Tokenizer::DATA; + lastCR = false; + index = 0; + forceQuirks = false; + additional = '\0'; + entCol = -1; + firstCharKey = -1; + lo = 0; + hi = 0; + candidate = -1; + charRefBufMark = 0; + value = 0; + seenDigits = false; + suspendAfterCurrentNonTextToken = false; + endTag = false; + shouldSuspend = false; + initDoctypeFields(); + containsHyphen = false; + tagName = nullptr; + attributeName = nullptr; + if (newAttributesEachTime) { + if (attributes) { + delete attributes; + attributes = nullptr; + } + } +} + +void nsHtml5Tokenizer::loadState(nsHtml5Tokenizer* other) { + strBufLen = other->strBufLen; + if (strBufLen > strBuf.length) { + strBuf = jArray<char16_t, int32_t>::newJArray(strBufLen); + } + nsHtml5ArrayCopy::arraycopy(other->strBuf, strBuf, strBufLen); + charRefBufLen = other->charRefBufLen; + nsHtml5ArrayCopy::arraycopy(other->charRefBuf, charRefBuf, charRefBufLen); + stateSave = other->stateSave; + returnStateSave = other->returnStateSave; + endTagExpectation = other->endTagExpectation; + endTagExpectationAsArray = other->endTagExpectationAsArray; + lastCR = other->lastCR; + index = other->index; + forceQuirks = other->forceQuirks; + additional = other->additional; + entCol = other->entCol; + firstCharKey = other->firstCharKey; + lo = other->lo; + hi = other->hi; + candidate = other->candidate; + charRefBufMark = other->charRefBufMark; + value = other->value; + seenDigits = other->seenDigits; + endTag = other->endTag; + shouldSuspend = false; + suspendAfterCurrentNonTextToken = false; + doctypeName = other->doctypeName; + systemIdentifier.Release(); + if (!other->systemIdentifier) { + systemIdentifier = nullptr; + } else { + systemIdentifier = + nsHtml5Portability::newStringFromString(other->systemIdentifier); + } + publicIdentifier.Release(); + if (!other->publicIdentifier) { + publicIdentifier = nullptr; + } else { + publicIdentifier = + nsHtml5Portability::newStringFromString(other->publicIdentifier); + } + containsHyphen = other->containsHyphen; + if (!other->tagName) { + tagName = nullptr; + } else if (other->tagName->isInterned()) { + tagName = other->tagName; + } else { + nonInternedTagName->setNameForNonInterned(other->tagName->getName(), + other->tagName->isCustom()); + tagName = nonInternedTagName; + } + if (!other->attributeName) { + attributeName = nullptr; + } else if (other->attributeName->isInterned()) { + attributeName = other->attributeName; + } else { + nonInternedAttributeName->setNameForNonInterned( + other->attributeName->getLocal(nsHtml5AttributeName::HTML)); + attributeName = nonInternedAttributeName; + } + delete attributes; + if (!other->attributes) { + attributes = nullptr; + } else { + attributes = other->attributes->cloneAttributes(); + } +} + +void nsHtml5Tokenizer::initializeWithoutStarting() { + confident = false; + strBuf = nullptr; + line = 1; + attributeLine = 1; + resetToDataState(); +} + +void nsHtml5Tokenizer::setEncodingDeclarationHandler( + nsHtml5StreamParser* encodingDeclarationHandler) { + this->encodingDeclarationHandler = encodingDeclarationHandler; +} + +nsHtml5Tokenizer::~nsHtml5Tokenizer() { + MOZ_COUNT_DTOR(nsHtml5Tokenizer); + delete nonInternedTagName; + nonInternedTagName = nullptr; + delete nonInternedAttributeName; + nonInternedAttributeName = nullptr; + delete attributes; + attributes = nullptr; +} + +void nsHtml5Tokenizer::initializeStatics() {} + +void nsHtml5Tokenizer::releaseStatics() {} + +#include "nsHtml5TokenizerCppSupplement.h" diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h new file mode 100644 index 0000000000..7397bb8c03 --- /dev/null +++ b/parser/html/nsHtml5Tokenizer.h @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2005-2007 Henri Sivonen + * Copyright (c) 2007-2017 Mozilla Foundation + * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla + * Foundation, and Opera Software ASA. + * + * 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit Tokenizer.java instead and regenerate. + */ + +#ifndef nsHtml5Tokenizer_h +#define nsHtml5Tokenizer_h + +#include "jArray.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsAtom.h" +#include "nsGkAtoms.h" +#include "nsHtml5ArrayCopy.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5DocumentMode.h" +#include "nsHtml5Highlighter.h" +#include "nsHtml5Macros.h" +#include "nsHtml5NamedCharacters.h" +#include "nsHtml5NamedCharactersAccel.h" +#include "nsHtml5String.h" +#include "nsHtml5TokenizerLoopPolicies.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" + +class nsHtml5StreamParser; + +class nsHtml5AttributeName; +class nsHtml5ElementName; +class nsHtml5TreeBuilder; +class nsHtml5UTF16Buffer; +class nsHtml5StateSnapshot; +class nsHtml5Portability; + +class nsHtml5Tokenizer { + private: + static const int32_t DATA_AND_RCDATA_MASK = ~1; + + public: + static const int32_t DATA = 0; + + static const int32_t RCDATA = 1; + + static const int32_t SCRIPT_DATA = 2; + + static const int32_t RAWTEXT = 3; + + static const int32_t SCRIPT_DATA_ESCAPED = 4; + + static const int32_t ATTRIBUTE_VALUE_DOUBLE_QUOTED = 5; + + static const int32_t ATTRIBUTE_VALUE_SINGLE_QUOTED = 6; + + static const int32_t ATTRIBUTE_VALUE_UNQUOTED = 7; + + static const int32_t PLAINTEXT = 8; + + static const int32_t TAG_OPEN = 9; + + static const int32_t CLOSE_TAG_OPEN = 10; + + static const int32_t TAG_NAME = 11; + + static const int32_t BEFORE_ATTRIBUTE_NAME = 12; + + static const int32_t ATTRIBUTE_NAME = 13; + + static const int32_t AFTER_ATTRIBUTE_NAME = 14; + + static const int32_t BEFORE_ATTRIBUTE_VALUE = 15; + + static const int32_t AFTER_ATTRIBUTE_VALUE_QUOTED = 16; + + static const int32_t BOGUS_COMMENT = 17; + + static const int32_t MARKUP_DECLARATION_OPEN = 18; + + static const int32_t DOCTYPE = 19; + + static const int32_t BEFORE_DOCTYPE_NAME = 20; + + static const int32_t DOCTYPE_NAME = 21; + + static const int32_t AFTER_DOCTYPE_NAME = 22; + + static const int32_t BEFORE_DOCTYPE_PUBLIC_IDENTIFIER = 23; + + static const int32_t DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED = 24; + + static const int32_t DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED = 25; + + static const int32_t AFTER_DOCTYPE_PUBLIC_IDENTIFIER = 26; + + static const int32_t BEFORE_DOCTYPE_SYSTEM_IDENTIFIER = 27; + + static const int32_t DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED = 28; + + static const int32_t DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED = 29; + + static const int32_t AFTER_DOCTYPE_SYSTEM_IDENTIFIER = 30; + + static const int32_t BOGUS_DOCTYPE = 31; + + static const int32_t COMMENT_START = 32; + + static const int32_t COMMENT_START_DASH = 33; + + static const int32_t COMMENT = 34; + + static const int32_t COMMENT_END_DASH = 35; + + static const int32_t COMMENT_END = 36; + + static const int32_t COMMENT_END_BANG = 37; + + static const int32_t NON_DATA_END_TAG_NAME = 38; + + static const int32_t MARKUP_DECLARATION_HYPHEN = 39; + + static const int32_t MARKUP_DECLARATION_OCTYPE = 40; + + static const int32_t DOCTYPE_UBLIC = 41; + + static const int32_t DOCTYPE_YSTEM = 42; + + static const int32_t AFTER_DOCTYPE_PUBLIC_KEYWORD = 43; + + static const int32_t BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS = 44; + + static const int32_t AFTER_DOCTYPE_SYSTEM_KEYWORD = 45; + + static const int32_t CONSUME_CHARACTER_REFERENCE = 46; + + static const int32_t CONSUME_NCR = 47; + + static const int32_t CHARACTER_REFERENCE_TAIL = 48; + + static const int32_t HEX_NCR_LOOP = 49; + + static const int32_t DECIMAL_NRC_LOOP = 50; + + static const int32_t HANDLE_NCR_VALUE = 51; + + static const int32_t HANDLE_NCR_VALUE_RECONSUME = 52; + + static const int32_t CHARACTER_REFERENCE_HILO_LOOKUP = 53; + + static const int32_t SELF_CLOSING_START_TAG = 54; + + static const int32_t CDATA_START = 55; + + static const int32_t CDATA_SECTION = 56; + + static const int32_t CDATA_RSQB = 57; + + static const int32_t CDATA_RSQB_RSQB = 58; + + static const int32_t SCRIPT_DATA_LESS_THAN_SIGN = 59; + + static const int32_t SCRIPT_DATA_ESCAPE_START = 60; + + static const int32_t SCRIPT_DATA_ESCAPE_START_DASH = 61; + + static const int32_t SCRIPT_DATA_ESCAPED_DASH = 62; + + static const int32_t SCRIPT_DATA_ESCAPED_DASH_DASH = 63; + + static const int32_t BOGUS_COMMENT_HYPHEN = 64; + + static const int32_t RAWTEXT_RCDATA_LESS_THAN_SIGN = 65; + + static const int32_t SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN = 66; + + static const int32_t SCRIPT_DATA_DOUBLE_ESCAPE_START = 67; + + static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED = 68; + + static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN = 69; + + static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED_DASH = 70; + + static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH = 71; + + static const int32_t SCRIPT_DATA_DOUBLE_ESCAPE_END = 72; + + static const int32_t PROCESSING_INSTRUCTION = 73; + + static const int32_t PROCESSING_INSTRUCTION_QUESTION_MARK = 74; + + static const int32_t COMMENT_LESSTHAN = 76; + + static const int32_t COMMENT_LESSTHAN_BANG = 77; + + static const int32_t COMMENT_LESSTHAN_BANG_DASH = 78; + + static const int32_t COMMENT_LESSTHAN_BANG_DASH_DASH = 79; + + private: + static const int32_t LEAD_OFFSET = (0xD800 - (0x10000 >> 10)); + + static char16_t LT_GT[]; + static char16_t LT_SOLIDUS[]; + static char16_t RSQB_RSQB[]; + static char16_t REPLACEMENT_CHARACTER[]; + static char16_t LF[]; + static char16_t CDATA_LSQB[]; + static char16_t OCTYPE[]; + static char16_t UBLIC[]; + static char16_t YSTEM[]; + static staticJArray<char16_t, int32_t> TITLE_ARR; + static staticJArray<char16_t, int32_t> SCRIPT_ARR; + static staticJArray<char16_t, int32_t> STYLE_ARR; + static staticJArray<char16_t, int32_t> PLAINTEXT_ARR; + static staticJArray<char16_t, int32_t> XMP_ARR; + static staticJArray<char16_t, int32_t> TEXTAREA_ARR; + static staticJArray<char16_t, int32_t> IFRAME_ARR; + static staticJArray<char16_t, int32_t> NOEMBED_ARR; + static staticJArray<char16_t, int32_t> NOSCRIPT_ARR; + static staticJArray<char16_t, int32_t> NOFRAMES_ARR; + + protected: + nsHtml5TreeBuilder* tokenHandler; + nsHtml5StreamParser* encodingDeclarationHandler; + bool lastCR; + int32_t stateSave; + + private: + int32_t returnStateSave; + + protected: + int32_t index; + + private: + bool forceQuirks; + char16_t additional; + int32_t entCol; + int32_t firstCharKey; + int32_t lo; + int32_t hi; + int32_t candidate; + int32_t charRefBufMark; + + protected: + int32_t value; + + private: + bool seenDigits; + bool suspendAfterCurrentNonTextToken; + + protected: + int32_t cstart; + + private: + nsHtml5String publicId; + nsHtml5String systemId; + autoJArray<char16_t, int32_t> strBuf; + int32_t strBufLen; + autoJArray<char16_t, int32_t> charRefBuf; + int32_t charRefBufLen; + autoJArray<char16_t, int32_t> bmpChar; + autoJArray<char16_t, int32_t> astralChar; + + protected: + nsHtml5ElementName* endTagExpectation; + + private: + jArray<char16_t, int32_t> endTagExpectationAsArray; + + protected: + bool endTag; + + private: + bool containsHyphen; + nsHtml5ElementName* tagName; + nsHtml5ElementName* nonInternedTagName; + + protected: + nsHtml5AttributeName* attributeName; + + private: + nsHtml5AttributeName* nonInternedAttributeName; + RefPtr<nsAtom> doctypeName; + nsHtml5String publicIdentifier; + nsHtml5String systemIdentifier; + nsHtml5HtmlAttributes* attributes; + bool newAttributesEachTime; + bool shouldSuspend; + + protected: + bool confident; + + private: + int32_t line; + int32_t attributeLine; + nsHtml5AtomTable* interner; + bool viewingXmlSource; + + public: + nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler, bool viewingXmlSource); + void setInterner(nsHtml5AtomTable* interner); + void initLocation(nsHtml5String newPublicId, nsHtml5String newSystemId); + bool isViewingXmlSource(); + void setState(int32_t specialTokenizerState); + void setStateAndEndTagExpectation(int32_t specialTokenizerState, + nsHtml5ElementName* endTagExpectation); + + private: + void endTagExpectationToArray(); + + public: + void setLineNumber(int32_t line); + inline int32_t getLineNumber() { return line; } + + nsHtml5HtmlAttributes* emptyAttributes(); + + private: + inline void appendCharRefBuf(char16_t c) { + MOZ_RELEASE_ASSERT(charRefBufLen < charRefBuf.length, + "Attempted to overrun charRefBuf!"); + charRefBuf[charRefBufLen++] = c; + } + + void emitOrAppendCharRefBuf(int32_t returnState); + inline void clearStrBufAfterUse() { strBufLen = 0; } + + inline void clearStrBufBeforeUse() { + MOZ_ASSERT(!strBufLen, "strBufLen not reset after previous use!"); + strBufLen = 0; + } + + inline void clearStrBufAfterOneHyphen() { + MOZ_ASSERT(strBufLen == 1, "strBufLen length not one!"); + MOZ_ASSERT(strBuf[0] == '-', "strBuf does not start with a hyphen!"); + strBufLen = 0; + } + + inline void appendStrBuf(char16_t c) { + MOZ_ASSERT(strBufLen < strBuf.length, + "Previous buffer length insufficient."); + if (MOZ_UNLIKELY(strBufLen == strBuf.length)) { + if (MOZ_UNLIKELY(!EnsureBufferSpace(1))) { + MOZ_CRASH("Unable to recover from buffer reallocation failure"); + } + } + strBuf[strBufLen++] = c; + } + + protected: + nsHtml5String strBufToString(); + + private: + void strBufToDoctypeName(); + void emitStrBuf(); + inline void appendSecondHyphenToBogusComment() { appendStrBuf('-'); } + + inline void adjustDoubleHyphenAndAppendToStrBufAndErr( + char16_t c, bool reportedConsecutiveHyphens) { + appendStrBuf(c); + } + + void appendStrBuf(char16_t* buffer, int32_t offset, int32_t length); + inline void appendCharRefBufToStrBuf() { + appendStrBuf(charRefBuf, 0, charRefBufLen); + charRefBufLen = 0; + } + + void emitComment(int32_t provisionalHyphens, int32_t pos); + + protected: + void flushChars(char16_t* buf, int32_t pos); + + private: + void strBufToElementNameString(); + int32_t emitCurrentTagToken(bool selfClosing, int32_t pos); + void attributeNameComplete(); + void addAttributeWithoutValue(); + void addAttributeWithValue(); + + public: + void start(); + bool tokenizeBuffer(nsHtml5UTF16Buffer* buffer); + + private: + template <class P> + int32_t stateLoop(int32_t state, char16_t c, int32_t pos, char16_t* buf, + bool reconsume, int32_t returnState, int32_t endPos); + void initDoctypeFields(); + inline void adjustDoubleHyphenAndAppendToStrBufCarriageReturn() { + silentCarriageReturn(); + adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false); + } + + inline void adjustDoubleHyphenAndAppendToStrBufLineFeed() { + silentLineFeed(); + adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false); + } + + inline void appendStrBufLineFeed() { + silentLineFeed(); + appendStrBuf('\n'); + } + + inline void appendStrBufCarriageReturn() { + silentCarriageReturn(); + appendStrBuf('\n'); + } + + void emitCarriageReturn(char16_t* buf, int32_t pos); + void emitReplacementCharacter(char16_t* buf, int32_t pos); + void maybeEmitReplacementCharacter(char16_t* buf, int32_t pos); + void emitPlaintextReplacementCharacter(char16_t* buf, int32_t pos); + void setAdditionalAndRememberAmpersandLocation(char16_t add); + void bogusDoctype(); + void bogusDoctypeWithoutQuirks(); + void handleNcrValue(int32_t returnState); + + public: + void eof(); + + private: + void emitDoctypeToken(int32_t pos); + void suspendIfRequestedAfterCurrentNonTextToken(); + void suspendAfterCurrentTokenIfNotInText(); + bool suspensionAfterCurrentNonTextTokenPending(); + + public: + bool internalEncodingDeclaration(nsHtml5String internalCharset); + + private: + void emitOrAppendTwo(const char16_t* val, int32_t returnState); + void emitOrAppendOne(const char16_t* val, int32_t returnState); + + public: + void end(); + void requestSuspension(); + bool isInDataState(); + void resetToDataState(); + void loadState(nsHtml5Tokenizer* other); + void initializeWithoutStarting(); + void setEncodingDeclarationHandler( + nsHtml5StreamParser* encodingDeclarationHandler); + ~nsHtml5Tokenizer(); + static void initializeStatics(); + static void releaseStatics(); + +#include "nsHtml5TokenizerHSupplement.h" +}; + +#endif diff --git a/parser/html/nsHtml5TokenizerCppSupplement.h b/parser/html/nsHtml5TokenizerCppSupplement.h new file mode 100644 index 0000000000..b5bb2aec6b --- /dev/null +++ b/parser/html/nsHtml5TokenizerCppSupplement.h @@ -0,0 +1,494 @@ +/* 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/. */ + +#include "mozilla/CheckedInt.h" +#include "mozilla/Likely.h" + +// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits +// is 2^30. Note that this is counting char16_t units. The underlying +// bytes will be twice that, but they fit even in 32-bit size_t even +// if a contiguous chunk of memory of that size is pretty unlikely to +// be available on a 32-bit system. +#define MAX_POWER_OF_TWO_IN_INT32 0x40000000 + +bool nsHtml5Tokenizer::EnsureBufferSpace(int32_t aLength) { + MOZ_RELEASE_ASSERT(aLength >= 0, "Negative length."); + if (aLength > MAX_POWER_OF_TWO_IN_INT32) { + // Can't happen when loading from network. + return false; + } + mozilla::CheckedInt<int32_t> worstCase(strBufLen); + worstCase += aLength; + worstCase += charRefBufLen; + // Add 2 to account for emissions of LT_GT, LT_SOLIDUS and RSQB_RSQB. + // Adding to the general worst case instead of only the + // TreeBuilder-exposed worst case to avoid re-introducing a bug when + // unifying the tokenizer and tree builder buffers in the future. + worstCase += 2; + if (!worstCase.isValid()) { + return false; + } + if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) { + return false; + } + // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer + // so that the call below becomes unnecessary. + if (!tokenHandler->EnsureBufferSpace(worstCase.value())) { + return false; + } + if (!strBuf) { + if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) { + // Add one to round to the next power of two to avoid immediate + // reallocation once there are a few characters in the buffer. + worstCase += 1; + } + strBuf = jArray<char16_t, int32_t>::newFallibleJArray( + mozilla::RoundUpPow2(worstCase.value())); + if (!strBuf) { + return false; + } + } else if (worstCase.value() > strBuf.length) { + jArray<char16_t, int32_t> newBuf = + jArray<char16_t, int32_t>::newFallibleJArray( + mozilla::RoundUpPow2(worstCase.value())); + if (!newBuf) { + return false; + } + memcpy(newBuf, strBuf, sizeof(char16_t) * size_t(strBufLen)); + strBuf = newBuf; + } + return true; +} + +bool nsHtml5Tokenizer::TemplatePushedOrHeadPopped() { + if (encodingDeclarationHandler) { + return encodingDeclarationHandler->TemplatePushedOrHeadPopped(); + } + return false; +} + +void nsHtml5Tokenizer::RememberGt(int32_t aPos) { + if (encodingDeclarationHandler) { + return encodingDeclarationHandler->RememberGt(aPos); + } +} + +void nsHtml5Tokenizer::StartPlainText() { + stateSave = nsHtml5Tokenizer::PLAINTEXT; +} + +void nsHtml5Tokenizer::EnableViewSource(nsHtml5Highlighter* aHighlighter) { + mViewSource = mozilla::WrapUnique(aHighlighter); +} + +bool nsHtml5Tokenizer::ShouldFlushViewSource() { + return mViewSource->ShouldFlushOps(); +} + +mozilla::Result<bool, nsresult> nsHtml5Tokenizer::FlushViewSource() { + return mViewSource->FlushOps(); +} + +void nsHtml5Tokenizer::StartViewSource(const nsAutoString& aTitle) { + mViewSource->Start(aTitle); +} + +void nsHtml5Tokenizer::StartViewSourceCharacters() { + mViewSource->StartCharacters(); +} + +[[nodiscard]] bool nsHtml5Tokenizer::EndViewSource() { + return mViewSource->End(); +} + +void nsHtml5Tokenizer::SetViewSourceOpSink(nsAHtml5TreeOpSink* aOpSink) { + mViewSource->SetOpSink(aOpSink); +} + +void nsHtml5Tokenizer::RewindViewSource() { mViewSource->Rewind(); } + +void nsHtml5Tokenizer::errWarnLtSlashInRcdata() {} + +// The null checks below annotated MOZ_LIKELY are not actually necessary. + +void nsHtml5Tokenizer::errUnquotedAttributeValOrNull(char16_t c) { + if (MOZ_LIKELY(mViewSource)) { + switch (c) { + case '<': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeLt"); + return; + case '`': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeGrave"); + return; + case '\'': + case '"': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeQuote"); + return; + case '=': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeEquals"); + return; + } + } +} + +void nsHtml5Tokenizer::errLtOrEqualsOrGraveInUnquotedAttributeOrNull( + char16_t c) { + if (MOZ_LIKELY(mViewSource)) { + switch (c) { + case '=': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartEquals"); + return; + case '<': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartLt"); + return; + case '`': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartGrave"); + return; + } + } +} + +void nsHtml5Tokenizer::errBadCharBeforeAttributeNameOrNull(char16_t c) { + if (MOZ_LIKELY(mViewSource)) { + if (c == '<') { + mViewSource->AddErrorToCurrentNode("errBadCharBeforeAttributeNameLt"); + } else if (c == '=') { + errEqualsSignBeforeAttributeName(); + } else if (c != 0xFFFD) { + errQuoteBeforeAttributeName(c); + } + } +} + +void nsHtml5Tokenizer::errBadCharAfterLt(char16_t c) { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errBadCharAfterLt"); + } +} + +void nsHtml5Tokenizer::errQuoteOrLtInAttributeNameOrNull(char16_t c) { + if (MOZ_LIKELY(mViewSource)) { + if (c == '<') { + mViewSource->AddErrorToCurrentNode("errLtInAttributeName"); + } else if (c != 0xFFFD) { + mViewSource->AddErrorToCurrentNode("errQuoteInAttributeName"); + } + } +} + +void nsHtml5Tokenizer::maybeErrAttributesOnEndTag( + nsHtml5HtmlAttributes* attrs) { + if (mViewSource && attrs->getLength() != 0) { + /* + * When an end tag token is emitted with attributes, that is a parse + * error. + */ + mViewSource->AddErrorToCurrentRun("maybeErrAttributesOnEndTag"); + } +} + +void nsHtml5Tokenizer::maybeErrSlashInEndTag(bool selfClosing) { + if (mViewSource && selfClosing && endTag) { + mViewSource->AddErrorToCurrentSlash("maybeErrSlashInEndTag"); + } +} + +char16_t nsHtml5Tokenizer::errNcrNonCharacter(char16_t ch) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrNonCharacter"); + } + return ch; +} + +void nsHtml5Tokenizer::errAstralNonCharacter(int32_t ch) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrNonCharacter"); + } +} + +char16_t nsHtml5Tokenizer::errNcrControlChar(char16_t ch) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrControlChar"); + } + return ch; +} + +void nsHtml5Tokenizer::errGarbageAfterLtSlash() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errGarbageAfterLtSlash"); + } +} + +void nsHtml5Tokenizer::errLtSlashGt() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errLtSlashGt"); + } +} + +void nsHtml5Tokenizer::errCharRefLacksSemicolon() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errCharRefLacksSemicolon"); + } +} + +void nsHtml5Tokenizer::errNoDigitsInNCR() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNoDigitsInNCR"); + } +} + +void nsHtml5Tokenizer::errGtInSystemId() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errGtInSystemId"); + } +} + +void nsHtml5Tokenizer::errGtInPublicId() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errGtInPublicId"); + } +} + +void nsHtml5Tokenizer::errNamelessDoctype() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNamelessDoctype"); + } +} + +void nsHtml5Tokenizer::errConsecutiveHyphens() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errConsecutiveHyphens"); + } +} + +void nsHtml5Tokenizer::errPrematureEndOfComment() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errPrematureEndOfComment"); + } +} + +void nsHtml5Tokenizer::errBogusComment() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errBogusComment"); + } +} + +void nsHtml5Tokenizer::errSlashNotFollowedByGt() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentSlash("errSlashNotFollowedByGt"); + } +} + +void nsHtml5Tokenizer::errNoSpaceBetweenAttributes() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenAttributes"); + } +} + +void nsHtml5Tokenizer::errAttributeValueMissing() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errAttributeValueMissing"); + } +} + +void nsHtml5Tokenizer::errEqualsSignBeforeAttributeName() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errEqualsSignBeforeAttributeName"); + } +} + +void nsHtml5Tokenizer::errLtGt() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errLtGt"); + } +} + +void nsHtml5Tokenizer::errProcessingInstruction() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errProcessingInstruction"); + } +} + +void nsHtml5Tokenizer::errUnescapedAmpersandInterpretedAsCharacterReference() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentAmpersand( + "errUnescapedAmpersandInterpretedAsCharacterReference"); + } +} + +void nsHtml5Tokenizer::errNotSemicolonTerminated() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNotSemicolonTerminated"); + } +} + +void nsHtml5Tokenizer::errNoNamedCharacterMatch() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentAmpersand("errNoNamedCharacterMatch"); + } +} + +void nsHtml5Tokenizer::errQuoteBeforeAttributeName(char16_t c) { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errQuoteBeforeAttributeName"); + } +} + +void nsHtml5Tokenizer::errExpectedPublicId() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errExpectedPublicId"); + } +} + +void nsHtml5Tokenizer::errBogusDoctype() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errBogusDoctype"); + } +} + +void nsHtml5Tokenizer::errNcrSurrogate() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrSurrogate"); + } +} + +void nsHtml5Tokenizer::errNcrCr() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrCr"); + } +} + +void nsHtml5Tokenizer::errNcrInC1Range() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrInC1Range"); + } +} + +void nsHtml5Tokenizer::errEofInPublicId() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInPublicId"); + } +} + +void nsHtml5Tokenizer::errEofInComment() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInComment"); + } +} + +void nsHtml5Tokenizer::errEofInDoctype() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInDoctype"); + } +} + +void nsHtml5Tokenizer::errEofInAttributeValue() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInAttributeValue"); + } +} + +void nsHtml5Tokenizer::errEofInAttributeName() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInAttributeName"); + } +} + +void nsHtml5Tokenizer::errEofWithoutGt() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofWithoutGt"); + } +} + +void nsHtml5Tokenizer::errEofInTagName() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInTagName"); + } +} + +void nsHtml5Tokenizer::errEofInEndTag() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInEndTag"); + } +} + +void nsHtml5Tokenizer::errEofAfterLt() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofAfterLt"); + } +} + +void nsHtml5Tokenizer::errNcrOutOfRange() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrOutOfRange"); + } +} + +void nsHtml5Tokenizer::errNcrUnassigned() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrUnassigned"); + } +} + +void nsHtml5Tokenizer::errDuplicateAttribute() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errDuplicateAttribute"); + } +} + +void nsHtml5Tokenizer::errEofInSystemId() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEofInSystemId"); + } +} + +void nsHtml5Tokenizer::errExpectedSystemId() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errExpectedSystemId"); + } +} + +void nsHtml5Tokenizer::errMissingSpaceBeforeDoctypeName() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errMissingSpaceBeforeDoctypeName"); + } +} + +void nsHtml5Tokenizer::errNestedComment() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNestedComment"); + } +} + +void nsHtml5Tokenizer::errNcrControlChar() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrControlChar"); + } +} + +void nsHtml5Tokenizer::errNcrZero() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNcrZero"); + } +} + +void nsHtml5Tokenizer::errNoSpaceBetweenDoctypeSystemKeywordAndQuote() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode( + "errNoSpaceBetweenDoctypeSystemKeywordAndQuote"); + } +} + +void nsHtml5Tokenizer::errNoSpaceBetweenPublicAndSystemIds() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenPublicAndSystemIds"); + } +} + +void nsHtml5Tokenizer::errNoSpaceBetweenDoctypePublicKeywordAndQuote() { + if (MOZ_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode( + "errNoSpaceBetweenDoctypePublicKeywordAndQuote"); + } +} diff --git a/parser/html/nsHtml5TokenizerHSupplement.h b/parser/html/nsHtml5TokenizerHSupplement.h new file mode 100644 index 0000000000..0e1930b93e --- /dev/null +++ b/parser/html/nsHtml5TokenizerHSupplement.h @@ -0,0 +1,220 @@ +/* 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/. */ + +private: +inline void silentCarriageReturn() { + nextCharOnNewLine = true; + lastCR = true; +} + +inline void silentLineFeed() { nextCharOnNewLine = true; } + +inline char16_t checkChar(char16_t* buf, int32_t pos) { + // The name of this method comes from the validator. + // We aren't checking a char here. We read the next + // UTF-16 code unit and, before returning it, adjust + // the line and column numbers. + char16_t c = buf[pos]; + if (MOZ_UNLIKELY(nextCharOnNewLine)) { + // By changing the line and column here instead + // of doing so eagerly when seeing the line break + // causes the line break itself to be considered + // column-wise at the end of a line. + line++; + col = 1; + nextCharOnNewLine = false; + } else if (MOZ_LIKELY(!NS_IS_LOW_SURROGATE(c))) { + // SpiderMonkey wants to count scalar values + // instead of UTF-16 code units. We omit low + // surrogates from the count so that only the + // high surrogate increments the count for + // two-code-unit scalar values. + // + // It's somewhat questionable from the performance + // perspective to make the human-perceivable column + // count correct for non-BMP characters in the case + // where there is a single scalar value per extended + // grapheme cluster when even on the BMP there are + // various cases where the scalar count doesn't make + // much sense as a human-perceived "column count" due + // to extended grapheme clusters consisting of more + // than one scalar value. + col++; + } + return c; +} + +int32_t col; +bool nextCharOnNewLine; + +public: +inline int32_t getColumnNumber() { return col; } + +inline void setColumnNumberAndResetNextLine(int32_t aCol) { + col = aCol; + // The restored position only ever points to the position of + // script tag's > character, so we can unconditionally use + // `false` below. + nextCharOnNewLine = false; +} + +inline nsHtml5HtmlAttributes* GetAttributes() { return attributes; } + +/** + * Makes sure the buffers are large enough to be able to tokenize aLength + * UTF-16 code units before having to make the buffers larger. + * + * @param aLength the number of UTF-16 code units to be tokenized before the + * next call to this method. + * @return true if successful; false if out of memory + */ +bool EnsureBufferSpace(int32_t aLength); + +bool TemplatePushedOrHeadPopped(); + +void RememberGt(int32_t aPos); + +void AtKilobyteBoundary() { suspendAfterCurrentTokenIfNotInText(); } + +bool IsInTokenStartedAtKilobyteBoundary() { + return suspensionAfterCurrentNonTextTokenPending(); +} + +mozilla::UniquePtr<nsHtml5Highlighter> mViewSource; + +/** + * Starts handling text/plain. This is a one-way initialization. There is + * no corresponding EndPlainText() call. + */ +void StartPlainText(); + +void EnableViewSource(nsHtml5Highlighter* aHighlighter); + +bool ShouldFlushViewSource(); + +mozilla::Result<bool, nsresult> FlushViewSource(); + +void StartViewSource(const nsAutoString& aTitle); + +void StartViewSourceCharacters(); + +[[nodiscard]] bool EndViewSource(); + +void RewindViewSource(); + +void SetViewSourceOpSink(nsAHtml5TreeOpSink* aOpSink); + +void errGarbageAfterLtSlash(); + +void errLtSlashGt(); + +void errWarnLtSlashInRcdata(); + +void errCharRefLacksSemicolon(); + +void errNoDigitsInNCR(); + +void errGtInSystemId(); + +void errGtInPublicId(); + +void errNamelessDoctype(); + +void errConsecutiveHyphens(); + +void errPrematureEndOfComment(); + +void errBogusComment(); + +void errUnquotedAttributeValOrNull(char16_t c); + +void errSlashNotFollowedByGt(); + +void errNoSpaceBetweenAttributes(); + +void errLtOrEqualsOrGraveInUnquotedAttributeOrNull(char16_t c); + +void errAttributeValueMissing(); + +void errBadCharBeforeAttributeNameOrNull(char16_t c); + +void errEqualsSignBeforeAttributeName(); + +void errBadCharAfterLt(char16_t c); + +void errLtGt(); + +void errProcessingInstruction(); + +void errUnescapedAmpersandInterpretedAsCharacterReference(); + +void errNotSemicolonTerminated(); + +void errNoNamedCharacterMatch(); + +void errQuoteBeforeAttributeName(char16_t c); + +void errQuoteOrLtInAttributeNameOrNull(char16_t c); + +void errExpectedPublicId(); + +void errBogusDoctype(); + +void maybeErrAttributesOnEndTag(nsHtml5HtmlAttributes* attrs); + +void maybeErrSlashInEndTag(bool selfClosing); + +char16_t errNcrNonCharacter(char16_t ch); + +void errAstralNonCharacter(int32_t ch); + +void errNcrSurrogate(); + +char16_t errNcrControlChar(char16_t ch); + +void errNcrCr(); + +void errNcrInC1Range(); + +void errEofInPublicId(); + +void errEofInComment(); + +void errEofInDoctype(); + +void errEofInAttributeValue(); + +void errEofInAttributeName(); + +void errEofWithoutGt(); + +void errEofInTagName(); + +void errEofInEndTag(); + +void errEofAfterLt(); + +void errNcrOutOfRange(); + +void errNcrUnassigned(); + +void errDuplicateAttribute(); + +void errEofInSystemId(); + +void errExpectedSystemId(); + +void errMissingSpaceBeforeDoctypeName(); + +void errNestedComment(); + +void errNcrControlChar(); + +void errNcrZero(); + +void errNoSpaceBetweenDoctypeSystemKeywordAndQuote(); + +void errNoSpaceBetweenPublicAndSystemIds(); + +void errNoSpaceBetweenDoctypePublicKeywordAndQuote(); diff --git a/parser/html/nsHtml5TokenizerLoopPolicies.h b/parser/html/nsHtml5TokenizerLoopPolicies.h new file mode 100644 index 0000000000..f1e547ca25 --- /dev/null +++ b/parser/html/nsHtml5TokenizerLoopPolicies.h @@ -0,0 +1,38 @@ +/* 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/. */ + +#ifndef nsHtml5TokenizerLoopPolicies_h +#define nsHtml5TokenizerLoopPolicies_h + +/** + * This policy does not report tokenizer transitions anywhere. To be used + * when _not_ viewing source. + */ +struct nsHtml5SilentPolicy { + static const bool reportErrors = false; + static int32_t transition(nsHtml5Highlighter* aHighlighter, int32_t aState, + bool aReconsume, int32_t aPos) { + return aState; + } + static void completedNamedCharacterReference( + nsHtml5Highlighter* aHighlighter) {} +}; + +/** + * This policy reports the tokenizer transitions to a highlighter. To be used + * when viewing source. + */ +struct nsHtml5ViewSourcePolicy { + static const bool reportErrors = true; + static int32_t transition(nsHtml5Highlighter* aHighlighter, int32_t aState, + bool aReconsume, int32_t aPos) { + return aHighlighter->Transition(aState, aReconsume, aPos); + } + static void completedNamedCharacterReference( + nsHtml5Highlighter* aHighlighter) { + aHighlighter->CompletedNamedCharacterReference(); + } +}; + +#endif // nsHtml5TokenizerLoopPolicies_h diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp new file mode 100644 index 0000000000..3c98c221ed --- /dev/null +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -0,0 +1,4744 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2007-2017 Mozilla Foundation + * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla + * Foundation, and Opera Software ASA. + * + * 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit TreeBuilder.java instead and regenerate. + */ + +#define nsHtml5TreeBuilder_cpp__ + +#include "jArray.h" +#include "mozilla/ImportScanner.h" +#include "mozilla/Likely.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsAtom.h" +#include "nsContentUtils.h" +#include "nsGkAtoms.h" +#include "nsHtml5ArrayCopy.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5DocumentMode.h" +#include "nsHtml5Highlighter.h" +#include "nsHtml5OplessBuilder.h" +#include "nsHtml5Parser.h" +#include "nsHtml5PlainTextUtils.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5StreamParser.h" +#include "nsHtml5String.h" +#include "nsHtml5TreeOperation.h" +#include "nsHtml5TreeOpExecutor.h" +#include "nsHtml5ViewSourceUtils.h" +#include "nsIContent.h" +#include "nsIContentHandle.h" +#include "nsNameSpaceManager.h" +#include "nsTraceRefcnt.h" + +#include "nsHtml5AttributeName.h" +#include "nsHtml5ElementName.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5UTF16Buffer.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5Portability.h" + +#include "nsHtml5TreeBuilder.h" + +char16_t nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = {0xfffd}; +static const char* const QUIRKY_PUBLIC_IDS_DATA[] = { + "+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html " + "4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//"}; +staticJArray<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = { + QUIRKY_PUBLIC_IDS_DATA, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA)}; +void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) { + tokenizer = self; + stackNodes = jArray<nsHtml5StackNode*, int32_t>::newJArray(64); + stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(64); + templateModeStack = jArray<int32_t, int32_t>::newJArray(64); + listOfActiveFormattingElements = + jArray<nsHtml5StackNode*, int32_t>::newJArray(64); + needToDropLF = false; + originalMode = INITIAL; + templateModePtr = -1; + stackNodesIdx = 0; + numStackNodes = 0; + currentPtr = -1; + listPtr = -1; + formPointer = nullptr; + headPointer = nullptr; + start(fragment); + charBufferLen = 0; + charBuffer = nullptr; + framesetOk = true; + if (fragment) { + nsIContentHandle* elt; + if (contextNode) { + elt = contextNode; + } else { + elt = createHtmlElementSetAsRoot(tokenizer->emptyAttributes()); + } + if (contextNamespace == kNameSpaceID_SVG) { + nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_SVG; + if (nsGkAtoms::title == contextName || nsGkAtoms::desc == contextName || + nsGkAtoms::foreignObject == contextName) { + elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT; + } + nsHtml5StackNode* node = + createStackNode(elementName, elementName->getCamelCaseName(), elt); + currentPtr++; + stack[currentPtr] = node; + tokenizer->setState(nsHtml5Tokenizer::DATA); + mode = FRAMESET_OK; + } else if (contextNamespace == kNameSpaceID_MathML) { + nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH; + if (nsGkAtoms::mi_ == contextName || nsGkAtoms::mo_ == contextName || + nsGkAtoms::mn_ == contextName || nsGkAtoms::ms_ == contextName || + nsGkAtoms::mtext_ == contextName) { + elementName = nsHtml5ElementName::ELT_MTEXT; + } else if (nsGkAtoms::annotation_xml_ == contextName) { + elementName = nsHtml5ElementName::ELT_ANNOTATION_XML; + } + nsHtml5StackNode* node = + createStackNode(elementName, elt, elementName->getName(), false); + currentPtr++; + stack[currentPtr] = node; + tokenizer->setState(nsHtml5Tokenizer::DATA); + mode = FRAMESET_OK; + } else { + nsHtml5StackNode* node = + createStackNode(nsHtml5ElementName::ELT_HTML, elt); + currentPtr++; + stack[currentPtr] = node; + if (nsGkAtoms::_template == contextName) { + pushTemplateMode(IN_TEMPLATE); + } + resetTheInsertionMode(); + formPointer = getFormPointerForContext(contextNode); + if (nsGkAtoms::title == contextName || + nsGkAtoms::textarea == contextName) { + tokenizer->setState(nsHtml5Tokenizer::RCDATA); + } else if (nsGkAtoms::style == contextName || + nsGkAtoms::xmp == contextName || + nsGkAtoms::iframe == contextName || + nsGkAtoms::noembed == contextName || + nsGkAtoms::noframes == contextName || + (scriptingEnabled && nsGkAtoms::noscript == contextName)) { + tokenizer->setState(nsHtml5Tokenizer::RAWTEXT); + } else if (nsGkAtoms::plaintext == contextName) { + tokenizer->setState(nsHtml5Tokenizer::PLAINTEXT); + } else if (nsGkAtoms::script == contextName) { + tokenizer->setState(nsHtml5Tokenizer::SCRIPT_DATA); + } else { + tokenizer->setState(nsHtml5Tokenizer::DATA); + } + } + } else { + mode = INITIAL; + if (tokenizer->isViewingXmlSource()) { + nsIContentHandle* elt = createElement( + kNameSpaceID_SVG, nsGkAtoms::svg, tokenizer->emptyAttributes(), + nullptr, svgCreator(NS_NewSVGSVGElement)); + nsHtml5StackNode* node = + createStackNode(nsHtml5ElementName::ELT_SVG, nsGkAtoms::svg, elt); + currentPtr++; + stack[currentPtr] = node; + } + } +} + +void nsHtml5TreeBuilder::doctype(nsAtom* name, nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool forceQuirks) { + needToDropLF = false; + if (!isInForeign() && mode == INITIAL) { + nsHtml5String emptyString = nsHtml5Portability::newEmptyString(); + appendDoctypeToDocument(!name ? nsGkAtoms::_empty : name, + !publicIdentifier ? emptyString : publicIdentifier, + !systemIdentifier ? emptyString : systemIdentifier); + emptyString.Release(); + if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) { + errQuirkyDoctype(); + documentModeInternal(QUIRKS_MODE, publicIdentifier, systemIdentifier); + } else if (isAlmostStandards(publicIdentifier, systemIdentifier)) { + errAlmostStandardsDoctype(); + documentModeInternal(ALMOST_STANDARDS_MODE, publicIdentifier, + systemIdentifier); + } else { + documentModeInternal(STANDARDS_MODE, publicIdentifier, systemIdentifier); + } + mode = BEFORE_HTML; + return; + } + errStrayDoctype(); + return; +} + +void nsHtml5TreeBuilder::comment(char16_t* buf, int32_t start, int32_t length) { + needToDropLF = false; + if (!isInForeign()) { + switch (mode) { + case INITIAL: + case BEFORE_HTML: + case AFTER_AFTER_BODY: + case AFTER_AFTER_FRAMESET: { + appendCommentToDocument(buf, start, length); + return; + } + case AFTER_BODY: { + flushCharacters(); + appendComment(stack[0]->node, buf, start, length); + return; + } + default: { + break; + } + } + } + flushCharacters(); + appendComment(stack[currentPtr]->node, buf, start, length); + return; +} + +void nsHtml5TreeBuilder::characters(const char16_t* buf, int32_t start, + int32_t length) { + if (tokenizer->isViewingXmlSource()) { + return; + } + if (needToDropLF) { + needToDropLF = false; + if (buf[start] == '\n') { + start++; + length--; + if (!length) { + return; + } + } + } + switch (mode) { + case IN_BODY: + case IN_CELL: + case IN_CAPTION: { + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { + reconstructTheActiveFormattingElements(); + } + [[fallthrough]]; + } + case TEXT: { + accumulateCharacters(buf, start, length); + return; + } + case IN_TABLE: + case IN_TABLE_BODY: + case IN_ROW: { + accumulateCharactersForced(buf, start, length); + return; + } + default: { + int32_t end = start + length; + for (int32_t i = start; i < end; i++) { + switch (buf[i]) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': { + switch (mode) { + case INITIAL: + case BEFORE_HTML: + case BEFORE_HEAD: { + start = i + 1; + continue; + } + case IN_HEAD: + case IN_HEAD_NOSCRIPT: + case AFTER_HEAD: + case IN_COLUMN_GROUP: + case IN_FRAMESET: + case AFTER_FRAMESET: { + continue; + } + case FRAMESET_OK: + case IN_TEMPLATE: + case IN_BODY: + case IN_CELL: + case IN_CAPTION: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { + flushCharacters(); + reconstructTheActiveFormattingElements(); + } + NS_HTML5_BREAK(charactersloop); + } + case IN_SELECT: + case IN_SELECT_IN_TABLE: { + NS_HTML5_BREAK(charactersloop); + } + case IN_TABLE: + case IN_TABLE_BODY: + case IN_ROW: { + accumulateCharactersForced(buf, i, 1); + start = i + 1; + continue; + } + case AFTER_BODY: + case AFTER_AFTER_BODY: + case AFTER_AFTER_FRAMESET: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + flushCharacters(); + reconstructTheActiveFormattingElements(); + continue; + } + } + MOZ_FALLTHROUGH_ASSERT(); + } + default: { + switch (mode) { + case INITIAL: { + documentModeInternal(QUIRKS_MODE, nullptr, nullptr); + mode = BEFORE_HTML; + i--; + continue; + } + case BEFORE_HTML: { + appendHtmlElementToDocumentAndPush(); + mode = BEFORE_HEAD; + i--; + continue; + } + case BEFORE_HEAD: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + flushCharacters(); + appendToCurrentNodeAndPushHeadElement( + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + mode = IN_HEAD; + i--; + continue; + } + case IN_HEAD: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + flushCharacters(); + pop(); + mode = AFTER_HEAD; + i--; + continue; + } + case IN_HEAD_NOSCRIPT: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + errNonSpaceInNoscriptInHead(); + flushCharacters(); + pop(); + mode = IN_HEAD; + i--; + continue; + } + case AFTER_HEAD: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + flushCharacters(); + appendToCurrentNodeAndPushBodyElement(); + mode = FRAMESET_OK; + i--; + continue; + } + case FRAMESET_OK: { + framesetOk = false; + mode = IN_BODY; + i--; + continue; + } + case IN_TEMPLATE: + case IN_BODY: + case IN_CELL: + case IN_CAPTION: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { + flushCharacters(); + reconstructTheActiveFormattingElements(); + } + NS_HTML5_BREAK(charactersloop); + } + case IN_TABLE: + case IN_TABLE_BODY: + case IN_ROW: { + accumulateCharactersForced(buf, i, 1); + start = i + 1; + continue; + } + case IN_COLUMN_GROUP: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + start = i; + } + if (!currentPtr || stack[currentPtr]->getGroup() == + nsHtml5TreeBuilder::TEMPLATE) { + errNonSpaceInColgroupInFragment(); + start = i + 1; + continue; + } + flushCharacters(); + pop(); + mode = IN_TABLE; + i--; + continue; + } + case IN_SELECT: + case IN_SELECT_IN_TABLE: { + NS_HTML5_BREAK(charactersloop); + } + case AFTER_BODY: { + errNonSpaceAfterBody(); + + mode = framesetOk ? FRAMESET_OK : IN_BODY; + i--; + continue; + } + case IN_FRAMESET: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + } + errNonSpaceInFrameset(); + start = i + 1; + continue; + } + case AFTER_FRAMESET: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + } + errNonSpaceAfterFrameset(); + start = i + 1; + continue; + } + case AFTER_AFTER_BODY: { + errNonSpaceInTrailer(); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + i--; + continue; + } + case AFTER_AFTER_FRAMESET: { + if (start < i) { + accumulateCharacters(buf, start, i - start); + } + errNonSpaceInTrailer(); + start = i + 1; + continue; + } + } + } + } + } + charactersloop_end:; + if (start < end) { + accumulateCharacters(buf, start, end - start); + } + } + } +} + +void nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter() { + if (mode == TEXT) { + accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1); + return; + } + if (currentPtr >= 0) { + if (isSpecialParentInForeign(stack[currentPtr])) { + return; + } + accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1); + } +} + +void nsHtml5TreeBuilder::zeroOrReplacementCharacter() { + zeroOriginatingReplacementCharacter(); +} + +void nsHtml5TreeBuilder::eof() { + flushCharacters(); + for (;;) { + switch (mode) { + case INITIAL: { + documentModeInternal(QUIRKS_MODE, nullptr, nullptr); + mode = BEFORE_HTML; + continue; + } + case BEFORE_HTML: { + appendHtmlElementToDocumentAndPush(); + mode = BEFORE_HEAD; + continue; + } + case BEFORE_HEAD: { + appendToCurrentNodeAndPushHeadElement( + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + mode = IN_HEAD; + continue; + } + case IN_HEAD: { + while (currentPtr > 0) { + popOnEof(); + } + mode = AFTER_HEAD; + continue; + } + case IN_HEAD_NOSCRIPT: { + while (currentPtr > 1) { + popOnEof(); + } + mode = IN_HEAD; + continue; + } + case AFTER_HEAD: { + appendToCurrentNodeAndPushBodyElement(); + mode = IN_BODY; + continue; + } + case IN_TABLE_BODY: + case IN_ROW: + case IN_TABLE: + case IN_SELECT_IN_TABLE: + case IN_SELECT: + case IN_COLUMN_GROUP: + case FRAMESET_OK: + case IN_CAPTION: + case IN_CELL: + case IN_BODY: { + if (isTemplateModeStackEmpty()) { + NS_HTML5_BREAK(eofloop); + } + [[fallthrough]]; + } + case IN_TEMPLATE: { + int32_t eltPos = findLast(nsGkAtoms::_template); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment); + NS_HTML5_BREAK(eofloop); + } + if (MOZ_UNLIKELY(mViewSource)) { + errListUnclosedStartTags(0); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + popTemplateMode(); + resetTheInsertionMode(); + continue; + } + case TEXT: { + if (originalMode == AFTER_HEAD) { + popOnEof(); + } + popOnEof(); + mode = originalMode; + continue; + } + case IN_FRAMESET: { + NS_HTML5_BREAK(eofloop); + } + case AFTER_BODY: + case AFTER_FRAMESET: + case AFTER_AFTER_BODY: + case AFTER_AFTER_FRAMESET: + default: { + NS_HTML5_BREAK(eofloop); + } + } + } +eofloop_end:; + while (currentPtr > 0) { + popOnEof(); + } + if (!fragment) { + popOnEof(); + } +} + +void nsHtml5TreeBuilder::endTokenization() { + formPointer = nullptr; + headPointer = nullptr; + contextName = nullptr; + contextNode = nullptr; + templateModeStack = nullptr; + if (stack) { + while (currentPtr > -1) { + stack[currentPtr]->release(this); + currentPtr--; + } + stack = nullptr; + } + if (listOfActiveFormattingElements) { + while (listPtr > -1) { + if (listOfActiveFormattingElements[listPtr]) { + listOfActiveFormattingElements[listPtr]->release(this); + } + listPtr--; + } + listOfActiveFormattingElements = nullptr; + } + if (stackNodes) { + for (int32_t i = 0; i < numStackNodes; i++) { + MOZ_ASSERT(stackNodes[i]->isUnused()); + delete stackNodes[i]; + } + numStackNodes = 0; + stackNodesIdx = 0; + stackNodes = nullptr; + } + charBuffer = nullptr; + end(); +} + +void nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes, + bool selfClosing) { + flushCharacters(); + int32_t eltPos; + needToDropLF = false; +starttagloop: + for (;;) { + int32_t group = elementName->getGroup(); + nsAtom* name = elementName->getName(); + if (isInForeign()) { + nsHtml5StackNode* currentNode = stack[currentPtr]; + int32_t currNs = currentNode->ns; + if (!(currentNode->isHtmlIntegrationPoint() || + (currNs == kNameSpaceID_MathML && + ((currentNode->getGroup() == MI_MO_MN_MS_MTEXT && + group != MGLYPH_OR_MALIGNMARK) || + (currentNode->getGroup() == ANNOTATION_XML && group == SVG))))) { + switch (group) { + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: + case BODY: + case BR: + case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR: + case DD_OR_DT: + case UL_OR_OL_OR_DL: + case EMBED: + case IMG: + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: + case HEAD: + case HR: + case LI: + case META: + case NOBR: + case P: + case PRE_OR_LISTING: + case TABLE: + case FONT: { + if (!(group == FONT && + !(attributes->contains(nsHtml5AttributeName::ATTR_COLOR) || + attributes->contains(nsHtml5AttributeName::ATTR_FACE) || + attributes->contains(nsHtml5AttributeName::ATTR_SIZE)))) { + errHtmlStartTagInForeignContext(name); + if (!fragment) { + while (!isSpecialParentInForeign(stack[currentPtr])) { + popForeign(-1, -1); + } + NS_HTML5_CONTINUE(starttagloop); + } + } + [[fallthrough]]; + } + default: { + if (kNameSpaceID_SVG == currNs) { + attributes->adjustForSvg(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterSVG(elementName, attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterSVG(elementName, + attributes); + } + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } else { + attributes->adjustForMath(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterMathML(elementName, + attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterMathML(elementName, + attributes); + } + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + } + } + } + } + switch (mode) { + case IN_TEMPLATE: { + switch (group) { + case COL: { + popTemplateMode(); + pushTemplateMode(IN_COLUMN_GROUP); + mode = IN_COLUMN_GROUP; + continue; + } + case CAPTION: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: { + popTemplateMode(); + pushTemplateMode(IN_TABLE); + mode = IN_TABLE; + continue; + } + case TR: { + popTemplateMode(); + pushTemplateMode(IN_TABLE_BODY); + mode = IN_TABLE_BODY; + continue; + } + case TD_OR_TH: { + popTemplateMode(); + pushTemplateMode(IN_ROW); + mode = IN_ROW; + continue; + } + case META: { + checkMetaCharset(attributes); + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TITLE: { + startTagTitleInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: { + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case SCRIPT: { + startTagScriptInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case NOFRAMES: + case STYLE: { + startTagGenericRawText(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TEMPLATE: { + startTagTemplateInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + popTemplateMode(); + pushTemplateMode(IN_BODY); + mode = IN_BODY; + continue; + } + } + } + case IN_ROW: { + switch (group) { + case TD_OR_TH: { + clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR)); + appendToCurrentNodeAndPushElement(elementName, attributes); + mode = IN_CELL; + insertMarker(); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: { + eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR); + if (!eltPos) { + MOZ_ASSERT(fragment || isTemplateContents()); + errNoTableRowToClose(); + NS_HTML5_BREAK(starttagloop); + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + continue; + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_TABLE_BODY: { + switch (group) { + case TR: { + clearStackBackTo( + findLastInTableScopeOrRootTemplateTbodyTheadTfoot()); + appendToCurrentNodeAndPushElement(elementName, attributes); + mode = IN_ROW; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TD_OR_TH: { + errStartTagInTableBody(name); + clearStackBackTo( + findLastInTableScopeOrRootTemplateTbodyTheadTfoot()); + appendToCurrentNodeAndPushElement( + nsHtml5ElementName::ELT_TR, + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + mode = IN_ROW; + continue; + } + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: { + eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot(); + if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } else { + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE; + continue; + } + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_TABLE: { + for (;;) { + switch (group) { + case CAPTION: { + clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE)); + insertMarker(); + appendToCurrentNodeAndPushElement(elementName, attributes); + mode = IN_CAPTION; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case COLGROUP: { + clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE)); + appendToCurrentNodeAndPushElement(elementName, attributes); + mode = IN_COLUMN_GROUP; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case COL: { + clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE)); + appendToCurrentNodeAndPushElement( + nsHtml5ElementName::ELT_COLGROUP, + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + mode = IN_COLUMN_GROUP; + NS_HTML5_CONTINUE(starttagloop); + } + case TBODY_OR_THEAD_OR_TFOOT: { + clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE)); + appendToCurrentNodeAndPushElement(elementName, attributes); + mode = IN_TABLE_BODY; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TR: + case TD_OR_TH: { + clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE)); + appendToCurrentNodeAndPushElement( + nsHtml5ElementName::ELT_TBODY, + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + mode = IN_TABLE_BODY; + NS_HTML5_CONTINUE(starttagloop); + } + case TEMPLATE: { + NS_HTML5_BREAK(intableloop); + } + case TABLE: { + errTableSeenWhileTableOpen(); + eltPos = findLastInTableScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment || isTemplateContents()); + NS_HTML5_BREAK(starttagloop); + } + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::table)) { + errNoCheckUnclosedElementsOnStack(); + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + NS_HTML5_CONTINUE(starttagloop); + } + case SCRIPT: { + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation( + nsHtml5Tokenizer::SCRIPT_DATA, elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case STYLE: { + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT, + elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case INPUT: { + errStartTagInTable(name); + if (!nsHtml5Portability:: + lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "hidden", attributes->getValue( + nsHtml5AttributeName::ATTR_TYPE))) { + NS_HTML5_BREAK(intableloop); + } + appendVoidInputToCurrent(attributes, formPointer); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case FORM: { + if (!!formPointer || isTemplateContents()) { + errFormWhenFormOpen(); + NS_HTML5_BREAK(starttagloop); + } else { + errStartTagInTable(name); + appendVoidFormToCurrent(attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + } + default: { + errStartTagInTable(name); + NS_HTML5_BREAK(intableloop); + } + } + } + intableloop_end:; + [[fallthrough]]; + } + case IN_CAPTION: { + switch (group) { + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: { + eltPos = findLastInTableScope(nsGkAtoms::caption); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) { + errNoCheckUnclosedElementsOnStack(); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_TABLE; + continue; + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_CELL: { + switch (group) { + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: { + eltPos = findLastInTableScopeTdTh(); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errNoCellToClose(); + NS_HTML5_BREAK(starttagloop); + } else { + closeTheCell(eltPos); + continue; + } + } + default:; // fall through + } + [[fallthrough]]; + } + case FRAMESET_OK: { + switch (group) { + case FRAMESET: { + if (mode == FRAMESET_OK) { + if (!currentPtr || stack[1]->getGroup() != BODY) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } else { + errFramesetStart(); + detachFromParent(stack[1]->node); + while (currentPtr > 0) { + pop(); + } + appendToCurrentNodeAndPushElement(elementName, attributes); + mode = IN_FRAMESET; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + } else { + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + } + case PRE_OR_LISTING: + case LI: + case DD_OR_DT: + case BUTTON: + case MARQUEE_OR_APPLET: + case OBJECT: + case TABLE: + case AREA_OR_WBR: + case KEYGEN: + case BR: + case EMBED: + case IMG: + case INPUT: + case HR: + case TEXTAREA: + case XMP: + case IFRAME: + case SELECT: { + if (mode == FRAMESET_OK && + !(group == INPUT && + nsHtml5Portability:: + lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "hidden", attributes->getValue( + nsHtml5AttributeName::ATTR_TYPE)))) { + framesetOk = false; + mode = IN_BODY; + } + [[fallthrough]]; + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_BODY: { + for (;;) { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: + case META: + case STYLE: + case SCRIPT: + case TITLE: + case TEMPLATE: { + NS_HTML5_BREAK(inbodyloop); + } + case BODY: { + if (!currentPtr || stack[1]->getGroup() != BODY || + isTemplateContents()) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + errFooSeenWhenFooOpen(name); + framesetOk = false; + if (mode == FRAMESET_OK) { + mode = IN_BODY; + } + if (addAttributesToBody(attributes)) { + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case P: + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: + case UL_OR_OL_OR_DL: + case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: { + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: { + implicitlyCloseP(); + if (stack[currentPtr]->getGroup() == + H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) { + errHeadingWhenHeadingOpen(); + pop(); + } + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case FIELDSET: { + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, attributes, formPointer); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case PRE_OR_LISTING: { + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + needToDropLF = true; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case FORM: { + if (!!formPointer && !isTemplateContents()) { + errFormWhenFormOpen(); + NS_HTML5_BREAK(starttagloop); + } else { + implicitlyCloseP(); + appendToCurrentNodeAndPushFormElementMayFoster(attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + } + case LI: + case DD_OR_DT: { + eltPos = currentPtr; + for (;;) { + nsHtml5StackNode* node = stack[eltPos]; + if (node->getGroup() == group) { + generateImpliedEndTagsExceptFor(node->name); + if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) { + errUnclosedElementsImplied(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + break; + } else if (!eltPos || (node->isSpecial() && + (node->ns != kNameSpaceID_XHTML || + (node->name != nsGkAtoms::p && + node->name != nsGkAtoms::address && + node->name != nsGkAtoms::div)))) { + break; + } + eltPos--; + } + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case PLAINTEXT: { + implicitlyCloseP(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + tokenizer->setStateAndEndTagExpectation( + nsHtml5Tokenizer::PLAINTEXT, elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case A: { + int32_t activeAPos = + findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker( + nsGkAtoms::a); + if (activeAPos != -1) { + errFooSeenWhenFooOpen(name); + nsHtml5StackNode* activeA = + listOfActiveFormattingElements[activeAPos]; + activeA->retain(); + adoptionAgencyEndTag(nsGkAtoms::a); + removeFromStack(activeA); + activeAPos = findInListOfActiveFormattingElements(activeA); + if (activeAPos != -1) { + removeFromListOfActiveFormattingElements(activeAPos); + } + activeA->release(this); + } + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: + case FONT: { + reconstructTheActiveFormattingElements(); + maybeForgetEarlierDuplicateFormattingElement( + elementName->getName(), attributes); + appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case NOBR: { + reconstructTheActiveFormattingElements(); + if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK != + findLastInScope(nsGkAtoms::nobr)) { + errFooSeenWhenFooOpen(name); + adoptionAgencyEndTag(nsGkAtoms::nobr); + reconstructTheActiveFormattingElements(); + } + appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case BUTTON: { + eltPos = findLastInScope(name); + if (eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errFooSeenWhenFooOpen(name); + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElementsImplied(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + NS_HTML5_CONTINUE(starttagloop); + } else { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, attributes, formPointer); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + } + case OBJECT: { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, attributes, formPointer); + insertMarker(); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case MARQUEE_OR_APPLET: { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + insertMarker(); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TABLE: { + if (!quirks) { + implicitlyCloseP(); + } + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + mode = IN_TABLE; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case BR: + case EMBED: + case AREA_OR_WBR: + case KEYGEN: { + reconstructTheActiveFormattingElements(); + [[fallthrough]]; + } + case PARAM_OR_SOURCE_OR_TRACK: { + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case HR: { + implicitlyCloseP(); + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case IMAGE: { + errImage(); + elementName = nsHtml5ElementName::ELT_IMG; + NS_HTML5_CONTINUE(starttagloop); + } + case IMG: + case INPUT: { + reconstructTheActiveFormattingElements(); + appendVoidElementToCurrentMayFoster(elementName, attributes, + formPointer); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TEXTAREA: { + appendToCurrentNodeAndPushElementMayFoster( + elementName, attributes, formPointer); + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA, + elementName); + originalMode = mode; + mode = TEXT; + needToDropLF = true; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case XMP: { + implicitlyCloseP(); + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT, + elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case NOSCRIPT: { + if (!scriptingEnabled) { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + [[fallthrough]]; + } + case NOFRAMES: + case IFRAME: + case NOEMBED: { + startTagGenericRawText(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case SELECT: { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, attributes, formPointer); + switch (mode) { + case IN_TABLE: + case IN_CAPTION: + case IN_COLUMN_GROUP: + case IN_TABLE_BODY: + case IN_ROW: + case IN_CELL: { + mode = IN_SELECT_IN_TABLE; + break; + } + default: { + mode = IN_SELECT; + break; + } + } + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case OPTGROUP: + case OPTION: { + if (isCurrent(nsGkAtoms::option)) { + pop(); + } + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case RB_OR_RTC: { + eltPos = findLastInScope(nsGkAtoms::ruby); + if (eltPos != NOT_FOUND_ON_STACK) { + generateImpliedEndTags(); + } + if (eltPos != currentPtr) { + if (eltPos == NOT_FOUND_ON_STACK) { + errStartTagSeenWithoutRuby(name); + } else { + errUnclosedChildrenInRuby(); + } + } + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case RT_OR_RP: { + eltPos = findLastInScope(nsGkAtoms::ruby); + if (eltPos != NOT_FOUND_ON_STACK) { + generateImpliedEndTagsExceptFor(nsGkAtoms::rtc); + } + if (eltPos != currentPtr) { + if (!isCurrent(nsGkAtoms::rtc)) { + if (eltPos == NOT_FOUND_ON_STACK) { + errStartTagSeenWithoutRuby(name); + } else { + errUnclosedChildrenInRuby(); + } + } + } + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case MATH: { + reconstructTheActiveFormattingElements(); + attributes->adjustForMath(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterMathML(elementName, + attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterMathML(elementName, + attributes); + } + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case SVG: { + reconstructTheActiveFormattingElements(); + attributes->adjustForSvg(); + if (selfClosing) { + appendVoidElementToCurrentMayFosterSVG(elementName, attributes); + selfClosing = false; + } else { + appendToCurrentNodeAndPushElementMayFosterSVG(elementName, + attributes); + } + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case CAPTION: + case COL: + case COLGROUP: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: + case FRAME: + case FRAMESET: + case HEAD: { + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + case OUTPUT: { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster( + elementName, attributes, formPointer); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + } + } + inbodyloop_end:; + [[fallthrough]]; + } + case IN_HEAD: { + for (;;) { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: { + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case META: { + NS_HTML5_BREAK(inheadloop); + } + case TITLE: { + startTagTitleInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case NOSCRIPT: { + if (scriptingEnabled) { + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation( + nsHtml5Tokenizer::RAWTEXT, elementName); + } else { + appendToCurrentNodeAndPushElementMayFoster(elementName, + attributes); + mode = IN_HEAD_NOSCRIPT; + } + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case SCRIPT: { + startTagScriptInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case STYLE: + case NOFRAMES: { + startTagGenericRawText(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case HEAD: { + errFooSeenWhenFooOpen(name); + NS_HTML5_BREAK(starttagloop); + } + case TEMPLATE: { + startTagTemplateInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + pop(); + mode = AFTER_HEAD; + NS_HTML5_CONTINUE(starttagloop); + } + } + } + inheadloop_end:; + [[fallthrough]]; + } + case IN_HEAD_NOSCRIPT: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case LINK_OR_BASEFONT_OR_BGSOUND: { + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case META: { + checkMetaCharset(attributes); + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case STYLE: + case NOFRAMES: { + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT, + elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case HEAD: { + errFooSeenWhenFooOpen(name); + NS_HTML5_BREAK(starttagloop); + } + case NOSCRIPT: { + errFooSeenWhenFooOpen(name); + NS_HTML5_BREAK(starttagloop); + } + default: { + errBadStartTagInNoscriptInHead(name); + pop(); + mode = IN_HEAD; + continue; + } + } + } + case IN_COLUMN_GROUP: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case COL: { + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TEMPLATE: { + startTagTemplateInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + if (!currentPtr || stack[currentPtr]->getGroup() == TEMPLATE) { + MOZ_ASSERT(fragment || isTemplateContents()); + errGarbageInColgroup(); + NS_HTML5_BREAK(starttagloop); + } + pop(); + mode = IN_TABLE; + continue; + } + } + } + case IN_SELECT_IN_TABLE: { + switch (group) { + case CAPTION: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: + case TABLE: { + errStartTagWithSelectOpen(name); + eltPos = findLastInTableScope(nsGkAtoms::select); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment); + NS_HTML5_BREAK(starttagloop); + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + continue; + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_SELECT: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case OPTION: { + if (isCurrent(nsGkAtoms::option)) { + pop(); + } + appendToCurrentNodeAndPushElement(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case OPTGROUP: { + if (isCurrent(nsGkAtoms::option)) { + pop(); + } + if (isCurrent(nsGkAtoms::optgroup)) { + pop(); + } + appendToCurrentNodeAndPushElement(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case SELECT: { + errStartSelectWhereEndSelectExpected(); + eltPos = findLastInTableScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment); + errNoSelectInTableScope(); + NS_HTML5_BREAK(starttagloop); + } else { + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + NS_HTML5_BREAK(starttagloop); + } + } + case INPUT: + case TEXTAREA: { + errStartTagWithSelectOpen(name); + eltPos = findLastInTableScope(nsGkAtoms::select); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment); + NS_HTML5_BREAK(starttagloop); + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + continue; + } + case SCRIPT: { + startTagScriptInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TEMPLATE: { + startTagTemplateInHead(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + } + } + case AFTER_BODY: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + default: { + errStrayStartTag(name); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + } + } + } + case IN_FRAMESET: { + switch (group) { + case FRAMESET: { + appendToCurrentNodeAndPushElement(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case FRAME: { + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default:; // fall through + } + [[fallthrough]]; + } + case AFTER_FRAMESET: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case NOFRAMES: { + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT, + elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + } + } + case INITIAL: { + errStartTagWithoutDoctype(); + documentModeInternal(QUIRKS_MODE, nullptr, nullptr); + mode = BEFORE_HTML; + continue; + } + case BEFORE_HTML: { + switch (group) { + case HTML: { + if (attributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + appendHtmlElementToDocumentAndPush(); + } else { + appendHtmlElementToDocumentAndPush(attributes); + } + mode = BEFORE_HEAD; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + appendHtmlElementToDocumentAndPush(); + mode = BEFORE_HEAD; + continue; + } + } + } + case BEFORE_HEAD: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case HEAD: { + appendToCurrentNodeAndPushHeadElement(attributes); + mode = IN_HEAD; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + appendToCurrentNodeAndPushHeadElement( + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + mode = IN_HEAD; + continue; + } + } + } + case AFTER_HEAD: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case BODY: { + if (!attributes->getLength()) { + appendToCurrentNodeAndPushBodyElement(); + } else { + appendToCurrentNodeAndPushBodyElement(attributes); + } + framesetOk = false; + mode = IN_BODY; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case FRAMESET: { + appendToCurrentNodeAndPushElement(elementName, attributes); + mode = IN_FRAMESET; + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TEMPLATE: { + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + nsHtml5StackNode* headOnStack = stack[currentPtr]; + startTagTemplateInHead(elementName, attributes); + removeFromStack(headOnStack); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case BASE: + case LINK_OR_BASEFONT_OR_BGSOUND: { + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + pop(); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case META: { + errFooBetweenHeadAndBody(name); + checkMetaCharset(attributes); + pushHeadPointerOntoStack(); + appendVoidElementToCurrentMayFoster(elementName, attributes); + selfClosing = false; + pop(); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case SCRIPT: { + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation( + nsHtml5Tokenizer::SCRIPT_DATA, elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case STYLE: + case NOFRAMES: { + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT, + elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case TITLE: { + errFooBetweenHeadAndBody(name); + pushHeadPointerOntoStack(); + appendToCurrentNodeAndPushElement(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA, + elementName); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + case HEAD: { + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + default: { + appendToCurrentNodeAndPushBodyElement(); + mode = FRAMESET_OK; + continue; + } + } + } + case AFTER_AFTER_BODY: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + default: { + errStrayStartTag(name); + + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + } + } + } + case AFTER_AFTER_FRAMESET: { + switch (group) { + case HTML: { + errStrayStartTag(name); + if (!fragment && !isTemplateContents()) { + addAttributesToHtml(attributes); + attributes = nullptr; + } + NS_HTML5_BREAK(starttagloop); + } + case NOFRAMES: { + startTagGenericRawText(elementName, attributes); + attributes = nullptr; + NS_HTML5_BREAK(starttagloop); + } + default: { + errStrayStartTag(name); + NS_HTML5_BREAK(starttagloop); + } + } + } + case TEXT: { + MOZ_ASSERT(false); + NS_HTML5_BREAK(starttagloop); + } + } + } +starttagloop_end:; + if (selfClosing) { + errSelfClosing(); + } + if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + delete attributes; + } +} + +void nsHtml5TreeBuilder::startTagTitleInHead( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA, + elementName); +} + +void nsHtml5TreeBuilder::startTagGenericRawText( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT, + elementName); +} + +void nsHtml5TreeBuilder::startTagScriptInHead( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); + originalMode = mode; + mode = TEXT; + tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA, + elementName); +} + +void nsHtml5TreeBuilder::startTagTemplateInHead( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + appendToCurrentNodeAndPushElement(elementName, attributes); + insertMarker(); + framesetOk = false; + originalMode = mode; + mode = IN_TEMPLATE; + pushTemplateMode(IN_TEMPLATE); +} + +bool nsHtml5TreeBuilder::isTemplateContents() { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK != + findLast(nsGkAtoms::_template); +} + +bool nsHtml5TreeBuilder::isTemplateModeStackEmpty() { + return templateModePtr == -1; +} + +bool nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode) { + int32_t ns = stackNode->ns; + return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) || + ((kNameSpaceID_MathML == ns) && + (stackNode->getGroup() == MI_MO_MN_MS_MTEXT)); +} + +nsHtml5String nsHtml5TreeBuilder::extractCharsetFromContent( + nsHtml5String attributeValue, nsHtml5TreeBuilder* tb) { + int32_t charsetState = CHARSET_INITIAL; + int32_t start = -1; + int32_t end = -1; + autoJArray<char16_t, int32_t> buffer = + nsHtml5Portability::newCharArrayFromString(attributeValue); + for (int32_t i = 0; i < buffer.length; i++) { + char16_t c = buffer[i]; + switch (charsetState) { + case CHARSET_INITIAL: { + switch (c) { + case 'c': + case 'C': { + charsetState = CHARSET_C; + continue; + } + default: { + continue; + } + } + } + case CHARSET_C: { + switch (c) { + case 'h': + case 'H': { + charsetState = CHARSET_H; + continue; + } + default: { + charsetState = CHARSET_INITIAL; + continue; + } + } + } + case CHARSET_H: { + switch (c) { + case 'a': + case 'A': { + charsetState = CHARSET_A; + continue; + } + default: { + charsetState = CHARSET_INITIAL; + continue; + } + } + } + case CHARSET_A: { + switch (c) { + case 'r': + case 'R': { + charsetState = CHARSET_R; + continue; + } + default: { + charsetState = CHARSET_INITIAL; + continue; + } + } + } + case CHARSET_R: { + switch (c) { + case 's': + case 'S': { + charsetState = CHARSET_S; + continue; + } + default: { + charsetState = CHARSET_INITIAL; + continue; + } + } + } + case CHARSET_S: { + switch (c) { + case 'e': + case 'E': { + charsetState = CHARSET_E; + continue; + } + default: { + charsetState = CHARSET_INITIAL; + continue; + } + } + } + case CHARSET_E: { + switch (c) { + case 't': + case 'T': { + charsetState = CHARSET_T; + continue; + } + default: { + charsetState = CHARSET_INITIAL; + continue; + } + } + } + case CHARSET_T: { + switch (c) { + case '\t': + case '\n': + case '\f': + case '\r': + case ' ': { + continue; + } + case '=': { + charsetState = CHARSET_EQUALS; + continue; + } + default: { + return nullptr; + } + } + } + case CHARSET_EQUALS: { + switch (c) { + case '\t': + case '\n': + case '\f': + case '\r': + case ' ': { + continue; + } + case '\'': { + start = i + 1; + charsetState = CHARSET_SINGLE_QUOTED; + continue; + } + case '\"': { + start = i + 1; + charsetState = CHARSET_DOUBLE_QUOTED; + continue; + } + default: { + start = i; + charsetState = CHARSET_UNQUOTED; + continue; + } + } + } + case CHARSET_SINGLE_QUOTED: { + switch (c) { + case '\'': { + end = i; + NS_HTML5_BREAK(charsetloop); + } + default: { + continue; + } + } + } + case CHARSET_DOUBLE_QUOTED: { + switch (c) { + case '\"': { + end = i; + NS_HTML5_BREAK(charsetloop); + } + default: { + continue; + } + } + } + case CHARSET_UNQUOTED: { + switch (c) { + case '\t': + case '\n': + case '\f': + case '\r': + case ' ': + case ';': { + end = i; + NS_HTML5_BREAK(charsetloop); + } + default: { + continue; + } + } + } + } + } +charsetloop_end:; + if (start != -1) { + if (end == -1) { + if (charsetState == CHARSET_UNQUOTED) { + end = buffer.length; + } else { + return nullptr; + } + } + return nsHtml5Portability::newStringFromBuffer(buffer, start, end - start, + tb, false); + } + return nullptr; +} + +void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes) { + nsHtml5String charset = + attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + if (charset) { + if (tokenizer->internalEncodingDeclaration(charset)) { + requestSuspension(); + return; + } + return; + } + if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "content-type", + attributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) { + return; + } + nsHtml5String content = + attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); + if (content) { + nsHtml5String extract = + nsHtml5TreeBuilder::extractCharsetFromContent(content, this); + if (extract) { + if (tokenizer->internalEncodingDeclaration(extract)) { + requestSuspension(); + } + } + extract.Release(); + } +} + +void nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) { + flushCharacters(); + needToDropLF = false; + int32_t eltPos; + int32_t group = elementName->getGroup(); + nsAtom* name = elementName->getName(); + for (;;) { + if (isInForeign()) { + if (stack[currentPtr]->name != name) { + if (!currentPtr) { + errStrayEndTag(name); + } else { + errEndTagDidNotMatchCurrentOpenElement(name, + stack[currentPtr]->popName); + } + } + eltPos = currentPtr; + int32_t origPos = currentPtr; + for (;;) { + if (!eltPos) { + MOZ_ASSERT(fragment, + "We can get this close to the root of the stack in " + "foreign content only in the fragment case."); + NS_HTML5_BREAK(endtagloop); + } + if (stack[eltPos]->name == name) { + while (currentPtr >= eltPos) { + popForeign(origPos, eltPos); + } + NS_HTML5_BREAK(endtagloop); + } + if (stack[--eltPos]->ns == kNameSpaceID_XHTML) { + break; + } + } + } + switch (mode) { + case IN_TEMPLATE: { + switch (group) { + case TEMPLATE: { + break; + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + [[fallthrough]]; + } + case IN_ROW: { + switch (group) { + case TR: { + eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR); + if (!eltPos) { + MOZ_ASSERT(fragment || isTemplateContents()); + errNoTableRowToClose(); + NS_HTML5_BREAK(endtagloop); + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + NS_HTML5_BREAK(endtagloop); + } + case TABLE: { + eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR); + if (!eltPos) { + MOZ_ASSERT(fragment || isTemplateContents()); + errNoTableRowToClose(); + NS_HTML5_BREAK(endtagloop); + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + continue; + } + case TBODY_OR_THEAD_OR_TFOOT: { + if (findLastInTableScope(name) == + nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR); + if (!eltPos) { + MOZ_ASSERT(fragment || isTemplateContents()); + errNoTableRowToClose(); + NS_HTML5_BREAK(endtagloop); + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE_BODY; + continue; + } + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: + case TD_OR_TH: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_TABLE_BODY: { + switch (group) { + case TBODY_OR_THEAD_OR_TFOOT: { + eltPos = findLastOrRoot(name); + if (!eltPos) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE; + NS_HTML5_BREAK(endtagloop); + } + case TABLE: { + eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot(); + if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + clearStackBackTo(eltPos); + pop(); + mode = IN_TABLE; + continue; + } + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: + case TD_OR_TH: + case TR: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_TABLE: { + switch (group) { + case TABLE: { + eltPos = findLast(nsGkAtoms::table); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + NS_HTML5_BREAK(endtagloop); + } + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case TR: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + case TEMPLATE: { + break; + } + default: { + errStrayEndTag(name); + } + } + [[fallthrough]]; + } + case IN_CAPTION: { + switch (group) { + case CAPTION: { + eltPos = findLastInTableScope(nsGkAtoms::caption); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + NS_HTML5_BREAK(endtagloop); + } + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_TABLE; + NS_HTML5_BREAK(endtagloop); + } + case TABLE: { + eltPos = findLastInTableScope(nsGkAtoms::caption); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_TABLE; + continue; + } + case BODY: + case COL: + case COLGROUP: + case HTML: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case TR: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_CELL: { + switch (group) { + case TD_OR_TH: { + eltPos = findLastInTableScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_ROW; + NS_HTML5_BREAK(endtagloop); + } + case TABLE: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: { + if (findLastInTableScope(name) == + nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(name == nsGkAtoms::tbody || name == nsGkAtoms::tfoot || + name == nsGkAtoms::thead || fragment || + isTemplateContents()); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + closeTheCell(findLastInTableScopeTdTh()); + continue; + } + case BODY: + case CAPTION: + case COL: + case COLGROUP: + case HTML: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + default:; // fall through + } + [[fallthrough]]; + } + case FRAMESET_OK: + case IN_BODY: { + switch (group) { + case BODY: { + if (!isSecondOnStackBody()) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + MOZ_ASSERT(currentPtr >= 1); + if (MOZ_UNLIKELY(mViewSource)) { + for (int32_t i = 2; i <= currentPtr; i++) { + switch (stack[i]->getGroup()) { + case DD_OR_DT: + case LI: + case OPTGROUP: + case OPTION: + case P: + case RB_OR_RTC: + case RT_OR_RP: + case TD_OR_TH: + case TBODY_OR_THEAD_OR_TFOOT: { + break; + } + default: { + errEndWithUnclosedElements(name); + NS_HTML5_BREAK(uncloseloop1); + } + } + } + uncloseloop1_end:; + } + mode = AFTER_BODY; + NS_HTML5_BREAK(endtagloop); + } + case HTML: { + if (!isSecondOnStackBody()) { + MOZ_ASSERT(fragment || isTemplateContents()); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + if (MOZ_UNLIKELY(mViewSource)) { + for (int32_t i = 0; i <= currentPtr; i++) { + switch (stack[i]->getGroup()) { + case DD_OR_DT: + case LI: + case P: + case RB_OR_RTC: + case RT_OR_RP: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case BODY: + case HTML: { + break; + } + default: { + errEndWithUnclosedElements(name); + NS_HTML5_BREAK(uncloseloop2); + } + } + } + uncloseloop2_end:; + } + mode = AFTER_BODY; + continue; + } + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: + case UL_OR_OL_OR_DL: + case PRE_OR_LISTING: + case FIELDSET: + case BUTTON: + case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: { + eltPos = findLastInScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + } else { + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + NS_HTML5_BREAK(endtagloop); + } + case FORM: { + if (!isTemplateContents()) { + if (!formPointer) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + formPointer = nullptr; + eltPos = findLastInScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + removeFromStack(eltPos); + NS_HTML5_BREAK(endtagloop); + } else { + eltPos = findLastInScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + NS_HTML5_BREAK(endtagloop); + } + } + case P: { + eltPos = findLastInButtonScope(nsGkAtoms::p); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errNoElementToCloseButEndTagSeen(nsGkAtoms::p); + if (isInForeign()) { + errHtmlStartTagInForeignContext(name); + while (currentPtr >= 0 && + stack[currentPtr]->ns != kNameSpaceID_XHTML) { + pop(); + } + } + appendVoidElementToCurrentMayFoster( + elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + NS_HTML5_BREAK(endtagloop); + } + generateImpliedEndTagsExceptFor(nsGkAtoms::p); + MOZ_ASSERT(eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK); + if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + NS_HTML5_BREAK(endtagloop); + } + case LI: { + eltPos = findLastInListScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errNoElementToCloseButEndTagSeen(name); + } else { + generateImpliedEndTagsExceptFor(name); + if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + NS_HTML5_BREAK(endtagloop); + } + case DD_OR_DT: { + eltPos = findLastInScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errNoElementToCloseButEndTagSeen(name); + } else { + generateImpliedEndTagsExceptFor(name); + if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + NS_HTML5_BREAK(endtagloop); + } + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: { + eltPos = findLastInScopeHn(); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + } else { + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + } + NS_HTML5_BREAK(endtagloop); + } + case OBJECT: + case MARQUEE_OR_APPLET: { + eltPos = findLastInScope(name); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(name); + } else { + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + } + NS_HTML5_BREAK(endtagloop); + } + case BR: { + errEndTagBr(); + if (isInForeign()) { + errHtmlStartTagInForeignContext(name); + while (currentPtr >= 0 && + stack[currentPtr]->ns != kNameSpaceID_XHTML) { + pop(); + } + } + reconstructTheActiveFormattingElements(); + appendVoidElementToCurrentMayFoster( + elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + NS_HTML5_BREAK(endtagloop); + } + case TEMPLATE: { + break; + } + case AREA_OR_WBR: + case KEYGEN: + case PARAM_OR_SOURCE_OR_TRACK: + case EMBED: + case IMG: + case IMAGE: + case INPUT: + case HR: + case IFRAME: + case NOEMBED: + case NOFRAMES: + case SELECT: + case TABLE: + case TEXTAREA: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + case NOSCRIPT: { + if (scriptingEnabled) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + [[fallthrough]]; + } + case A: + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: + case FONT: + case NOBR: { + if (adoptionAgencyEndTag(name)) { + NS_HTML5_BREAK(endtagloop); + } + [[fallthrough]]; + } + default: { + if (isCurrent(name)) { + pop(); + NS_HTML5_BREAK(endtagloop); + } + eltPos = currentPtr; + for (;;) { + nsHtml5StackNode* node = stack[eltPos]; + if (node->ns == kNameSpaceID_XHTML && node->name == name) { + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) { + errUnclosedElements(eltPos, name); + } + while (currentPtr >= eltPos) { + pop(); + } + NS_HTML5_BREAK(endtagloop); + } else if (!eltPos || node->isSpecial()) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + eltPos--; + } + } + } + [[fallthrough]]; + } + case IN_HEAD: { + switch (group) { + case HEAD: { + pop(); + mode = AFTER_HEAD; + NS_HTML5_BREAK(endtagloop); + } + case BR: + case HTML: + case BODY: { + pop(); + mode = AFTER_HEAD; + continue; + } + case TEMPLATE: { + endTagTemplateInHead(); + NS_HTML5_BREAK(endtagloop); + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case IN_HEAD_NOSCRIPT: { + switch (group) { + case NOSCRIPT: { + pop(); + mode = IN_HEAD; + NS_HTML5_BREAK(endtagloop); + } + case BR: { + errStrayEndTag(name); + pop(); + mode = IN_HEAD; + continue; + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case IN_COLUMN_GROUP: { + switch (group) { + case COLGROUP: { + if (!currentPtr || + stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) { + MOZ_ASSERT(fragment || isTemplateContents()); + errGarbageInColgroup(); + NS_HTML5_BREAK(endtagloop); + } + pop(); + mode = IN_TABLE; + NS_HTML5_BREAK(endtagloop); + } + case COL: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + case TEMPLATE: { + endTagTemplateInHead(); + NS_HTML5_BREAK(endtagloop); + } + default: { + if (!currentPtr || + stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) { + MOZ_ASSERT(fragment || isTemplateContents()); + errGarbageInColgroup(); + NS_HTML5_BREAK(endtagloop); + } + pop(); + mode = IN_TABLE; + continue; + } + } + } + case IN_SELECT_IN_TABLE: { + switch (group) { + case CAPTION: + case TABLE: + case TBODY_OR_THEAD_OR_TFOOT: + case TR: + case TD_OR_TH: { + errEndTagSeenWithSelectOpen(name); + if (findLastInTableScope(name) != + nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + eltPos = findLastInTableScope(nsGkAtoms::select); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment); + NS_HTML5_BREAK(endtagloop); + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + continue; + } else { + NS_HTML5_BREAK(endtagloop); + } + } + default:; // fall through + } + [[fallthrough]]; + } + case IN_SELECT: { + switch (group) { + case OPTION: { + if (isCurrent(nsGkAtoms::option)) { + pop(); + NS_HTML5_BREAK(endtagloop); + } else { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + case OPTGROUP: { + if (isCurrent(nsGkAtoms::option) && + nsGkAtoms::optgroup == stack[currentPtr - 1]->name) { + pop(); + } + if (isCurrent(nsGkAtoms::optgroup)) { + pop(); + } else { + errStrayEndTag(name); + } + NS_HTML5_BREAK(endtagloop); + } + case SELECT: { + eltPos = findLastInTableScope(nsGkAtoms::select); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + MOZ_ASSERT(fragment); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); + NS_HTML5_BREAK(endtagloop); + } + case TEMPLATE: { + endTagTemplateInHead(); + NS_HTML5_BREAK(endtagloop); + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case AFTER_BODY: { + switch (group) { + case HTML: { + if (fragment) { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } else { + mode = AFTER_AFTER_BODY; + NS_HTML5_BREAK(endtagloop); + } + } + default: { + errEndTagAfterBody(); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + } + } + } + case IN_FRAMESET: { + switch (group) { + case FRAMESET: { + if (!currentPtr) { + MOZ_ASSERT(fragment); + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + pop(); + if ((!fragment) && !isCurrent(nsGkAtoms::frameset)) { + mode = AFTER_FRAMESET; + } + NS_HTML5_BREAK(endtagloop); + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case AFTER_FRAMESET: { + switch (group) { + case HTML: { + mode = AFTER_AFTER_FRAMESET; + NS_HTML5_BREAK(endtagloop); + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case INITIAL: { + errEndTagSeenWithoutDoctype(); + documentModeInternal(QUIRKS_MODE, nullptr, nullptr); + mode = BEFORE_HTML; + continue; + } + case BEFORE_HTML: { + switch (group) { + case HEAD: + case BR: + case HTML: + case BODY: { + appendHtmlElementToDocumentAndPush(); + mode = BEFORE_HEAD; + continue; + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case BEFORE_HEAD: { + switch (group) { + case HEAD: + case BR: + case HTML: + case BODY: { + appendToCurrentNodeAndPushHeadElement( + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); + mode = IN_HEAD; + continue; + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case AFTER_HEAD: { + switch (group) { + case TEMPLATE: { + endTagTemplateInHead(); + NS_HTML5_BREAK(endtagloop); + } + case HTML: + case BODY: + case BR: { + appendToCurrentNodeAndPushBodyElement(); + mode = FRAMESET_OK; + continue; + } + default: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + } + } + case AFTER_AFTER_BODY: { + errStrayEndTag(name); + mode = framesetOk ? FRAMESET_OK : IN_BODY; + continue; + } + case AFTER_AFTER_FRAMESET: { + errStrayEndTag(name); + NS_HTML5_BREAK(endtagloop); + } + case TEXT: { + pop(); + if (originalMode == AFTER_HEAD) { + silentPop(); + } + mode = originalMode; + NS_HTML5_BREAK(endtagloop); + } + } + } +endtagloop_end:; +} + +void nsHtml5TreeBuilder::endTagTemplateInHead() { + int32_t eltPos = findLast(nsGkAtoms::_template); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + errStrayEndTag(nsGkAtoms::_template); + return; + } + generateImpliedEndTagsThoroughly(); + if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::_template)) { + errUnclosedElements(eltPos, nsGkAtoms::_template); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + popTemplateMode(); + resetTheInsertionMode(); +} + +int32_t +nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot() { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML && + (stack[i]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT || + stack[i]->getGroup() == nsHtml5TreeBuilder::TEMPLATE)) { + return i; + } + } + return 0; +} + +int32_t nsHtml5TreeBuilder::findLast(nsAtom* name) { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) { + return i; + } + } + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; +} + +int32_t nsHtml5TreeBuilder::findLastInTableScope(nsAtom* name) { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML) { + if (stack[i]->name == name) { + return i; + } else if (stack[i]->name == nsGkAtoms::table || + stack[i]->name == nsGkAtoms::_template) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + } + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; +} + +int32_t nsHtml5TreeBuilder::findLastInButtonScope(nsAtom* name) { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML) { + if (stack[i]->name == name) { + return i; + } else if (stack[i]->name == nsGkAtoms::button) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + if (stack[i]->isScoping()) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; +} + +int32_t nsHtml5TreeBuilder::findLastInScope(nsAtom* name) { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) { + return i; + } else if (stack[i]->isScoping()) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; +} + +int32_t nsHtml5TreeBuilder::findLastInListScope(nsAtom* name) { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML) { + if (stack[i]->name == name) { + return i; + } else if (stack[i]->name == nsGkAtoms::ul || + stack[i]->name == nsGkAtoms::ol) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + if (stack[i]->isScoping()) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; +} + +int32_t nsHtml5TreeBuilder::findLastInScopeHn() { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->getGroup() == + nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) { + return i; + } else if (stack[i]->isScoping()) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; +} + +void nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom* name) { + for (;;) { + nsHtml5StackNode* node = stack[currentPtr]; + switch (node->getGroup()) { + case P: + case LI: + case DD_OR_DT: + case OPTION: + case OPTGROUP: + case RB_OR_RTC: + case RT_OR_RP: { + if (node->ns == kNameSpaceID_XHTML && node->name == name) { + return; + } + pop(); + continue; + } + default: { + return; + } + } + } +} + +void nsHtml5TreeBuilder::generateImpliedEndTags() { + for (;;) { + switch (stack[currentPtr]->getGroup()) { + case P: + case LI: + case DD_OR_DT: + case OPTION: + case OPTGROUP: + case RB_OR_RTC: + case RT_OR_RP: { + pop(); + continue; + } + default: { + return; + } + } + } +} + +void nsHtml5TreeBuilder::generateImpliedEndTagsThoroughly() { + for (;;) { + switch (stack[currentPtr]->getGroup()) { + case CAPTION: + case COLGROUP: + case DD_OR_DT: + case LI: + case OPTGROUP: + case OPTION: + case P: + case RB_OR_RTC: + case RT_OR_RP: + case TBODY_OR_THEAD_OR_TFOOT: + case TD_OR_TH: + case TR: { + pop(); + continue; + } + default: { + return; + } + } + } +} + +bool nsHtml5TreeBuilder::isSecondOnStackBody() { + return currentPtr >= 1 && stack[1]->getGroup() == nsHtml5TreeBuilder::BODY; +} + +void nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier) { + if (forceNoQuirks) { + quirks = false; + this->documentMode(STANDARDS_MODE); + return; + } + quirks = (m == QUIRKS_MODE); + this->documentMode(m); +} + +bool nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier) { + if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier)) { + return true; + } + if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier)) { + return true; + } + if (systemIdentifier) { + if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) { + return true; + } + if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) { + return true; + } + } + return false; +} + +bool nsHtml5TreeBuilder::isQuirky(nsAtom* name, nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool forceQuirks) { + if (forceQuirks) { + return true; + } + if (name != nsGkAtoms::html) { + return true; + } + if (publicIdentifier) { + for (int32_t i = 0; i < nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS.length; i++) { + if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS[i], publicIdentifier)) { + return true; + } + } + if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) || + nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "-/w3c/dtd html 4.0 transitional/en", publicIdentifier) || + nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "html", publicIdentifier)) { + return true; + } + } + if (!systemIdentifier) { + if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) { + return true; + } else if (nsHtml5Portability:: + lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) { + return true; + } + } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd", + systemIdentifier)) { + return true; + } + return false; +} + +void nsHtml5TreeBuilder::closeTheCell(int32_t eltPos) { + generateImpliedEndTags(); + if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) { + errUnclosedElementsCell(eltPos); + } + while (currentPtr >= eltPos) { + pop(); + } + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + mode = IN_ROW; + return; +} + +int32_t nsHtml5TreeBuilder::findLastInTableScopeTdTh() { + for (int32_t i = currentPtr; i > 0; i--) { + nsAtom* name = stack[i]->name; + if (stack[i]->ns == kNameSpaceID_XHTML) { + if (nsGkAtoms::td == name || nsGkAtoms::th == name) { + return i; + } else if (name == nsGkAtoms::table || name == nsGkAtoms::_template) { + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; + } + } + } + return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK; +} + +void nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos) { + int32_t eltGroup = stack[eltPos]->getGroup(); + while (currentPtr > eltPos) { + if (stack[currentPtr]->ns == kNameSpaceID_XHTML && + stack[currentPtr]->getGroup() == TEMPLATE && + (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT || + eltGroup == TR || !eltPos)) { + return; + } + pop(); + } +} + +void nsHtml5TreeBuilder::resetTheInsertionMode() { + nsHtml5StackNode* node; + nsAtom* name; + int32_t ns; + for (int32_t i = currentPtr; i >= 0; i--) { + node = stack[i]; + name = node->name; + ns = node->ns; + if (!i) { + if (!(contextNamespace == kNameSpaceID_XHTML && + (contextName == nsGkAtoms::td || contextName == nsGkAtoms::th))) { + if (fragment) { + name = contextName; + ns = contextNamespace; + } + } else { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + return; + } + } + if (nsGkAtoms::select == name) { + int32_t ancestorIndex = i; + while (ancestorIndex > 0) { + nsHtml5StackNode* ancestor = stack[ancestorIndex--]; + if (kNameSpaceID_XHTML == ancestor->ns) { + if (nsGkAtoms::_template == ancestor->name) { + break; + } + if (nsGkAtoms::table == ancestor->name) { + mode = IN_SELECT_IN_TABLE; + return; + } + } + } + mode = IN_SELECT; + return; + } else if (nsGkAtoms::td == name || nsGkAtoms::th == name) { + mode = IN_CELL; + return; + } else if (nsGkAtoms::tr == name) { + mode = IN_ROW; + return; + } else if (nsGkAtoms::tbody == name || nsGkAtoms::thead == name || + nsGkAtoms::tfoot == name) { + mode = IN_TABLE_BODY; + return; + } else if (nsGkAtoms::caption == name) { + mode = IN_CAPTION; + return; + } else if (nsGkAtoms::colgroup == name) { + mode = IN_COLUMN_GROUP; + return; + } else if (nsGkAtoms::table == name) { + mode = IN_TABLE; + return; + } else if (kNameSpaceID_XHTML != ns) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + return; + } else if (nsGkAtoms::_template == name) { + MOZ_ASSERT(templateModePtr >= 0); + mode = templateModeStack[templateModePtr]; + return; + } else if (nsGkAtoms::head == name) { + if (name == contextName) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + } else { + mode = IN_HEAD; + } + return; + } else if (nsGkAtoms::body == name) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + return; + } else if (nsGkAtoms::frameset == name) { + mode = IN_FRAMESET; + return; + } else if (nsGkAtoms::html == name) { + if (!headPointer) { + mode = BEFORE_HEAD; + } else { + mode = AFTER_HEAD; + } + return; + } else if (!i) { + mode = framesetOk ? FRAMESET_OK : IN_BODY; + return; + } + } +} + +void nsHtml5TreeBuilder::implicitlyCloseP() { + int32_t eltPos = findLastInButtonScope(nsGkAtoms::p); + if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) { + return; + } + generateImpliedEndTagsExceptFor(nsGkAtoms::p); + if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) { + errUnclosedElementsImplied(eltPos, nsGkAtoms::p); + } + while (currentPtr >= eltPos) { + pop(); + } +} + +bool nsHtml5TreeBuilder::debugOnlyClearLastStackSlot() { + stack[currentPtr] = nullptr; + return true; +} + +bool nsHtml5TreeBuilder::debugOnlyClearLastListSlot() { + listOfActiveFormattingElements[listPtr] = nullptr; + return true; +} + +void nsHtml5TreeBuilder::pushTemplateMode(int32_t mode) { + templateModePtr++; + if (templateModePtr == templateModeStack.length) { + jArray<int32_t, int32_t> newStack = + jArray<int32_t, int32_t>::newJArray(templateModeStack.length + 64); + nsHtml5ArrayCopy::arraycopy(templateModeStack, newStack, + templateModeStack.length); + templateModeStack = newStack; + } + templateModeStack[templateModePtr] = mode; +} + +void nsHtml5TreeBuilder::push(nsHtml5StackNode* node) { + currentPtr++; + if (currentPtr == stack.length) { + jArray<nsHtml5StackNode*, int32_t> newStack = + jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64); + nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length); + stack = newStack; + } + stack[currentPtr] = node; + elementPushed(node->ns, node->popName, node->node); +} + +void nsHtml5TreeBuilder::silentPush(nsHtml5StackNode* node) { + currentPtr++; + if (currentPtr == stack.length) { + jArray<nsHtml5StackNode*, int32_t> newStack = + jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64); + nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length); + stack = newStack; + } + stack[currentPtr] = node; +} + +void nsHtml5TreeBuilder::append(nsHtml5StackNode* node) { + listPtr++; + if (listPtr == listOfActiveFormattingElements.length) { + jArray<nsHtml5StackNode*, int32_t> newList = + jArray<nsHtml5StackNode*, int32_t>::newJArray( + listOfActiveFormattingElements.length + 64); + nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, newList, + listOfActiveFormattingElements.length); + listOfActiveFormattingElements = newList; + } + listOfActiveFormattingElements[listPtr] = node; +} + +void nsHtml5TreeBuilder:: + clearTheListOfActiveFormattingElementsUpToTheLastMarker() { + while (listPtr > -1) { + if (!listOfActiveFormattingElements[listPtr]) { + --listPtr; + return; + } + listOfActiveFormattingElements[listPtr]->release(this); + --listPtr; + } +} + +void nsHtml5TreeBuilder::removeFromStack(int32_t pos) { + if (currentPtr == pos) { + pop(); + } else { + stack[pos]->release(this); + nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos); + MOZ_ASSERT(debugOnlyClearLastStackSlot()); + currentPtr--; + } +} + +void nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode* node) { + if (stack[currentPtr] == node) { + pop(); + } else { + int32_t pos = currentPtr - 1; + while (pos >= 0 && stack[pos] != node) { + pos--; + } + if (pos == -1) { + return; + } + + node->release(this); + nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos); + currentPtr--; + } +} + +void nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos) { + MOZ_ASSERT(!!listOfActiveFormattingElements[pos]); + listOfActiveFormattingElements[pos]->release(this); + if (pos == listPtr) { + MOZ_ASSERT(debugOnlyClearLastListSlot()); + listPtr--; + return; + } + MOZ_ASSERT(pos < listPtr); + nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, pos + 1, pos, + listPtr - pos); + MOZ_ASSERT(debugOnlyClearLastListSlot()); + listPtr--; +} + +bool nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom* name) { + if (stack[currentPtr]->ns == kNameSpaceID_XHTML && + stack[currentPtr]->name == name && + findInListOfActiveFormattingElements(stack[currentPtr]) == -1) { + pop(); + return true; + } + for (int32_t i = 0; i < 8; ++i) { + int32_t formattingEltListPos = listPtr; + while (formattingEltListPos > -1) { + nsHtml5StackNode* listNode = + listOfActiveFormattingElements[formattingEltListPos]; + if (!listNode) { + formattingEltListPos = -1; + break; + } else if (listNode->name == name) { + break; + } + formattingEltListPos--; + } + if (formattingEltListPos == -1) { + return false; + } + nsHtml5StackNode* formattingElt = + listOfActiveFormattingElements[formattingEltListPos]; + int32_t formattingEltStackPos = currentPtr; + bool inScope = true; + while (formattingEltStackPos > -1) { + nsHtml5StackNode* node = stack[formattingEltStackPos]; + if (node == formattingElt) { + break; + } else if (node->isScoping()) { + inScope = false; + } + formattingEltStackPos--; + } + if (formattingEltStackPos == -1) { + errNoElementToCloseButEndTagSeen(name); + removeFromListOfActiveFormattingElements(formattingEltListPos); + return true; + } + if (!inScope) { + errNoElementToCloseButEndTagSeen(name); + return true; + } + if (formattingEltStackPos != currentPtr) { + errEndTagViolatesNestingRules(name); + } + int32_t furthestBlockPos = formattingEltStackPos + 1; + while (furthestBlockPos <= currentPtr) { + nsHtml5StackNode* node = stack[furthestBlockPos]; + MOZ_ASSERT(furthestBlockPos > 0, + "How is formattingEltStackPos + 1 not > 0?"); + if (node->isSpecial()) { + break; + } + furthestBlockPos++; + } + if (furthestBlockPos > currentPtr) { + while (currentPtr >= formattingEltStackPos) { + pop(); + } + removeFromListOfActiveFormattingElements(formattingEltListPos); + return true; + } + nsHtml5StackNode* commonAncestor = stack[formattingEltStackPos - 1]; + nsIContentHandle* insertionCommonAncestor = + nodeFromStackWithBlinkCompat(formattingEltStackPos - 1); + nsHtml5StackNode* furthestBlock = stack[furthestBlockPos]; + int32_t bookmark = formattingEltListPos; + int32_t nodePos = furthestBlockPos; + nsHtml5StackNode* lastNode = furthestBlock; + int32_t j = 0; + for (;;) { + ++j; + nodePos--; + if (nodePos == formattingEltStackPos) { + break; + } + nsHtml5StackNode* node = stack[nodePos]; + int32_t nodeListPos = findInListOfActiveFormattingElements(node); + if (j > 3 && nodeListPos != -1) { + removeFromListOfActiveFormattingElements(nodeListPos); + if (nodeListPos <= formattingEltListPos) { + formattingEltListPos--; + } + if (nodeListPos <= bookmark) { + bookmark--; + } + nodeListPos = -1; + } + if (nodeListPos == -1) { + MOZ_ASSERT(formattingEltStackPos < nodePos); + MOZ_ASSERT(bookmark < nodePos); + MOZ_ASSERT(furthestBlockPos > nodePos); + removeFromStack(nodePos); + furthestBlockPos--; + continue; + } + if (nodePos == furthestBlockPos) { + bookmark = nodeListPos + 1; + } + MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]); + MOZ_ASSERT(node == stack[nodePos]); + nsIContentHandle* clone = createElement( + kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(), + insertionCommonAncestor, htmlCreator(node->getHtmlCreator())); + nsHtml5StackNode* newNode = createStackNode( + node->getFlags(), node->ns, node->name, clone, node->popName, + node->attributes, node->getHtmlCreator()); + node->dropAttributes(); + stack[nodePos] = newNode; + newNode->retain(); + listOfActiveFormattingElements[nodeListPos] = newNode; + node->release(this); + node->release(this); + node = newNode; + detachFromParent(lastNode->node); + appendElement(lastNode->node, nodeFromStackWithBlinkCompat(nodePos)); + lastNode = node; + } + if (commonAncestor->isFosterParenting()) { + detachFromParent(lastNode->node); + insertIntoFosterParent(lastNode->node); + } else { + detachFromParent(lastNode->node); + appendElement(lastNode->node, insertionCommonAncestor); + } + nsIContentHandle* clone = createElement( + kNameSpaceID_XHTML, formattingElt->name, + formattingElt->attributes->cloneAttributes(), furthestBlock->node, + htmlCreator(formattingElt->getHtmlCreator())); + nsHtml5StackNode* formattingClone = createStackNode( + formattingElt->getFlags(), formattingElt->ns, formattingElt->name, + clone, formattingElt->popName, formattingElt->attributes, + formattingElt->getHtmlCreator()); + formattingElt->dropAttributes(); + appendChildrenToNewParent(furthestBlock->node, clone); + appendElement(clone, furthestBlock->node); + removeFromListOfActiveFormattingElements(formattingEltListPos); + insertIntoListOfActiveFormattingElements(formattingClone, bookmark); + MOZ_ASSERT(formattingEltStackPos < furthestBlockPos); + removeFromStack(formattingEltStackPos); + insertIntoStack(formattingClone, furthestBlockPos); + } + return true; +} + +void nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode* node, + int32_t position) { + MOZ_ASSERT(currentPtr + 1 < stack.length); + MOZ_ASSERT(position <= currentPtr + 1); + if (position == currentPtr + 1) { + push(node); + } else { + nsHtml5ArrayCopy::arraycopy(stack, position, position + 1, + (currentPtr - position) + 1); + currentPtr++; + stack[position] = node; + } +} + +void nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements( + nsHtml5StackNode* formattingClone, int32_t bookmark) { + formattingClone->retain(); + MOZ_ASSERT(listPtr + 1 < listOfActiveFormattingElements.length); + if (bookmark <= listPtr) { + nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, bookmark, + bookmark + 1, (listPtr - bookmark) + 1); + } + listPtr++; + listOfActiveFormattingElements[bookmark] = formattingClone; +} + +int32_t nsHtml5TreeBuilder::findInListOfActiveFormattingElements( + nsHtml5StackNode* node) { + for (int32_t i = listPtr; i >= 0; i--) { + if (node == listOfActiveFormattingElements[i]) { + return i; + } + } + return -1; +} + +int32_t nsHtml5TreeBuilder:: + findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker( + nsAtom* name) { + for (int32_t i = listPtr; i >= 0; i--) { + nsHtml5StackNode* node = listOfActiveFormattingElements[i]; + if (!node) { + return -1; + } else if (node->name == name) { + return i; + } + } + return -1; +} + +void nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement( + nsAtom* name, nsHtml5HtmlAttributes* attributes) { + int32_t candidate = -1; + int32_t count = 0; + for (int32_t i = listPtr; i >= 0; i--) { + nsHtml5StackNode* node = listOfActiveFormattingElements[i]; + if (!node) { + break; + } + if (node->name == name && node->attributes->equalsAnother(attributes)) { + candidate = i; + ++count; + } + } + if (count >= 3) { + removeFromListOfActiveFormattingElements(candidate); + } +} + +int32_t nsHtml5TreeBuilder::findLastOrRoot(nsAtom* name) { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) { + return i; + } + } + return 0; +} + +int32_t nsHtml5TreeBuilder::findLastOrRoot(int32_t group) { + for (int32_t i = currentPtr; i > 0; i--) { + if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->getGroup() == group) { + return i; + } + } + return 0; +} + +bool nsHtml5TreeBuilder::addAttributesToBody( + nsHtml5HtmlAttributes* attributes) { + if (currentPtr >= 1) { + nsHtml5StackNode* body = stack[1]; + if (body->getGroup() == nsHtml5TreeBuilder::BODY) { + addAttributesToElement(body->node, attributes); + return true; + } + } + return false; +} + +void nsHtml5TreeBuilder::addAttributesToHtml( + nsHtml5HtmlAttributes* attributes) { + addAttributesToElement(stack[0]->node, attributes); +} + +void nsHtml5TreeBuilder::pushHeadPointerOntoStack() { + MOZ_ASSERT(!!headPointer); + MOZ_ASSERT(mode == AFTER_HEAD); + + silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD, headPointer)); +} + +void nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() { + if (listPtr == -1) { + return; + } + nsHtml5StackNode* mostRecent = listOfActiveFormattingElements[listPtr]; + if (!mostRecent || isInStack(mostRecent)) { + return; + } + int32_t entryPos = listPtr; + for (;;) { + entryPos--; + if (entryPos == -1) { + break; + } + if (!listOfActiveFormattingElements[entryPos]) { + break; + } + if (isInStack(listOfActiveFormattingElements[entryPos])) { + break; + } + } + while (entryPos < listPtr) { + entryPos++; + nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos]; + nsHtml5StackNode* current = stack[currentPtr]; + nsIContentHandle* clone; + if (current->isFosterParenting()) { + clone = createAndInsertFosterParentedElement( + kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(), + htmlCreator(entry->getHtmlCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + clone = createElement(kNameSpaceID_XHTML, entry->name, + entry->attributes->cloneAttributes(), currentNode, + htmlCreator(entry->getHtmlCreator())); + appendElement(clone, currentNode); + } + nsHtml5StackNode* entryClone = createStackNode( + entry->getFlags(), entry->ns, entry->name, clone, entry->popName, + entry->attributes, entry->getHtmlCreator()); + entry->dropAttributes(); + push(entryClone); + listOfActiveFormattingElements[entryPos] = entryClone; + entry->release(this); + entryClone->retain(); + } +} + +void nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes) { + if (idxInStackNodes < stackNodesIdx) { + stackNodesIdx = idxInStackNodes; + } +} + +nsHtml5StackNode* nsHtml5TreeBuilder::getUnusedStackNode() { + while (stackNodesIdx < numStackNodes) { + if (stackNodes[stackNodesIdx]->isUnused()) { + return stackNodes[stackNodesIdx++]; + } + stackNodesIdx++; + } + if (stackNodesIdx < stackNodes.length) { + stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx); + numStackNodes++; + return stackNodes[stackNodesIdx++]; + } + jArray<nsHtml5StackNode*, int32_t> newStack = + jArray<nsHtml5StackNode*, int32_t>::newJArray(stackNodes.length + 64); + nsHtml5ArrayCopy::arraycopy(stackNodes, newStack, stackNodes.length); + stackNodes = newStack; + stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx); + numStackNodes++; + return stackNodes[stackNodesIdx++]; +} + +nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode( + int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node, + nsAtom* popName, nsHtml5HtmlAttributes* attributes, + mozilla::dom::HTMLContentCreatorFunction htmlCreator) { + nsHtml5StackNode* instance = getUnusedStackNode(); + instance->setValues(flags, ns, name, node, popName, attributes, htmlCreator); + return instance; +} + +nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode( + nsHtml5ElementName* elementName, nsIContentHandle* node) { + nsHtml5StackNode* instance = getUnusedStackNode(); + instance->setValues(elementName, node); + return instance; +} + +nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode( + nsHtml5ElementName* elementName, nsIContentHandle* node, + nsHtml5HtmlAttributes* attributes) { + nsHtml5StackNode* instance = getUnusedStackNode(); + instance->setValues(elementName, node, attributes); + return instance; +} + +nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode( + nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName) { + nsHtml5StackNode* instance = getUnusedStackNode(); + instance->setValues(elementName, node, popName); + return instance; +} + +nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode( + nsHtml5ElementName* elementName, nsAtom* popName, nsIContentHandle* node) { + nsHtml5StackNode* instance = getUnusedStackNode(); + instance->setValues(elementName, popName, node); + return instance; +} + +nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode( + nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName, + bool markAsIntegrationPoint) { + nsHtml5StackNode* instance = getUnusedStackNode(); + instance->setValues(elementName, node, popName, markAsIntegrationPoint); + return instance; +} + +void nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child) { + int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE); + int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE); + if (templatePos >= tablePos) { + appendElement(child, stack[templatePos]->node); + return; + } + nsHtml5StackNode* node = stack[tablePos]; + insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node); +} + +nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement( + int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes, + nsHtml5ContentCreatorFunction creator) { + return createAndInsertFosterParentedElement(ns, name, attributes, nullptr, + creator); +} + +nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement( + int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form, nsHtml5ContentCreatorFunction creator) { + int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE); + int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE); + if (templatePos >= tablePos) { + nsIContentHandle* child = createElement(ns, name, attributes, form, + stack[templatePos]->node, creator); + appendElement(child, stack[templatePos]->node); + return child; + } + nsHtml5StackNode* node = stack[tablePos]; + return createAndInsertFosterParentedElement( + ns, name, attributes, form, node->node, stack[tablePos - 1]->node, + creator); +} + +bool nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node) { + for (int32_t i = currentPtr; i >= 0; i--) { + if (stack[i] == node) { + return true; + } + } + return false; +} + +void nsHtml5TreeBuilder::popTemplateMode() { templateModePtr--; } + +void nsHtml5TreeBuilder::pop() { + nsHtml5StackNode* node = stack[currentPtr]; + MOZ_ASSERT(debugOnlyClearLastStackSlot()); + currentPtr--; + elementPopped(node->ns, node->popName, node->node); + node->release(this); +} + +void nsHtml5TreeBuilder::popForeign(int32_t origPos, int32_t eltPos) { + nsHtml5StackNode* node = stack[currentPtr]; + if (origPos != currentPtr || eltPos != currentPtr) { + markMalformedIfScript(node->node); + } + MOZ_ASSERT(debugOnlyClearLastStackSlot()); + currentPtr--; + elementPopped(node->ns, node->popName, node->node); + node->release(this); +} + +void nsHtml5TreeBuilder::silentPop() { + nsHtml5StackNode* node = stack[currentPtr]; + MOZ_ASSERT(debugOnlyClearLastStackSlot()); + currentPtr--; + node->release(this); +} + +void nsHtml5TreeBuilder::popOnEof() { + nsHtml5StackNode* node = stack[currentPtr]; + MOZ_ASSERT(debugOnlyClearLastStackSlot()); + currentPtr--; + markMalformedIfScript(node->node); + elementPopped(node->ns, node->popName, node->node); + node->release(this); +} + +void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush( + nsHtml5HtmlAttributes* attributes) { + nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes); + nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HTML, elt); + push(node); +} + +void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush() { + appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes()); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement( + nsHtml5HtmlAttributes* attributes) { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + nsIContentHandle* elt = + createElement(kNameSpaceID_XHTML, nsGkAtoms::head, attributes, + currentNode, htmlCreator(NS_NewHTMLSharedElement)); + appendElement(elt, currentNode); + headPointer = elt; + nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HEAD, elt); + push(node); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement( + nsHtml5HtmlAttributes* attributes) { + appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY, attributes); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement() { + appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes()); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster( + nsHtml5HtmlAttributes* attributes) { + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_XHTML, nsGkAtoms::form, attributes, + htmlCreator(NS_NewHTMLFormElement)); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes, + currentNode, htmlCreator(NS_NewHTMLFormElement)); + appendElement(elt, currentNode); + } + if (!isTemplateContents()) { + formPointer = elt; + } + nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_FORM, elt); + push(node); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(); + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_XHTML, elementName->getName(), attributes, + htmlCreator(elementName->getHtmlCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = + createElement(kNameSpaceID_XHTML, elementName->getName(), attributes, + currentNode, htmlCreator(elementName->getHtmlCreator())); + appendElement(elt, currentNode); + } + nsHtml5StackNode* node = createStackNode(elementName, elt, clone); + push(node); + append(node); + node->retain(); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + nsIContentHandle* elt = + createElement(kNameSpaceID_XHTML, elementName->getName(), attributes, + currentNode, htmlCreator(elementName->getHtmlCreator())); + appendElement(elt, currentNode); + if (nsHtml5ElementName::ELT_TEMPLATE == elementName) { + elt = getDocumentFragmentForTemplate(elt); + } + nsHtml5StackNode* node = createStackNode(elementName, elt); + push(node); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsAtom* popName = elementName->getName(); + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_XHTML, popName, attributes, + htmlCreator(elementName->getHtmlCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode, + htmlCreator(elementName->getHtmlCreator())); + appendElement(elt, currentNode); + } + nsHtml5StackNode* node = createStackNode(elementName, elt, popName); + push(node); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsAtom* popName = elementName->getName(); + bool markAsHtmlIntegrationPoint = false; + if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && + annotationXmlEncodingPermitsHtml(attributes)) { + markAsHtmlIntegrationPoint = true; + } + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr)); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode, + htmlCreator(nullptr)); + appendElement(elt, currentNode); + } + nsHtml5StackNode* node = + createStackNode(elementName, elt, popName, markAsHtmlIntegrationPoint); + push(node); +} + +bool nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml( + nsHtml5HtmlAttributes* attributes) { + nsHtml5String encoding = + attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING); + if (!encoding) { + return false; + } + return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "application/xhtml+xml", encoding) || + nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "text/html", encoding); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsAtom* popName = elementName->getCamelCaseName(); + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_SVG, popName, attributes, + svgCreator(elementName->getSvgCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode, + svgCreator(elementName->getSvgCreator())); + appendElement(elt, currentNode); + } + nsHtml5StackNode* node = createStackNode(elementName, popName, elt); + push(node); +} + +void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form) { + nsIContentHandle* elt; + nsIContentHandle* formOwner = + !form || fragment || isTemplateContents() ? nullptr : form; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_XHTML, elementName->getName(), attributes, formOwner, + htmlCreator(elementName->getHtmlCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_XHTML, elementName->getName(), attributes, + formOwner, currentNode, + htmlCreator(elementName->getHtmlCreator())); + appendElement(elt, currentNode); + } + nsHtml5StackNode* node = createStackNode(elementName, elt); + push(node); +} + +void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form) { + nsAtom* name = elementName->getName(); + nsIContentHandle* elt; + nsIContentHandle* formOwner = + !form || fragment || isTemplateContents() ? nullptr : form; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_XHTML, name, attributes, formOwner, + htmlCreator(elementName->getHtmlCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = + createElement(kNameSpaceID_XHTML, name, attributes, formOwner, + currentNode, htmlCreator(elementName->getHtmlCreator())); + appendElement(elt, currentNode); + } + elementPushed(kNameSpaceID_XHTML, name, elt); + elementPopped(kNameSpaceID_XHTML, name, elt); +} + +void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsAtom* popName = elementName->getName(); + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_XHTML, popName, attributes, + htmlCreator(elementName->getHtmlCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode, + htmlCreator(elementName->getHtmlCreator())); + appendElement(elt, currentNode); + } + elementPushed(kNameSpaceID_XHTML, popName, elt); + elementPopped(kNameSpaceID_XHTML, popName, elt); +} + +void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsAtom* popName = elementName->getCamelCaseName(); + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_SVG, popName, attributes, + svgCreator(elementName->getSvgCreator())); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode, + svgCreator(elementName->getSvgCreator())); + appendElement(elt, currentNode); + } + elementPushed(kNameSpaceID_SVG, popName, elt); + elementPopped(kNameSpaceID_SVG, popName, elt); +} + +void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { + nsAtom* popName = elementName->getName(); + nsIContentHandle* elt; + nsHtml5StackNode* current = stack[currentPtr]; + if (current->isFosterParenting()) { + elt = createAndInsertFosterParentedElement( + kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr)); + } else { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode, + htmlCreator(nullptr)); + appendElement(elt, currentNode); + } + elementPushed(kNameSpaceID_MathML, popName, elt); + elementPopped(kNameSpaceID_MathML, popName, elt); +} + +void nsHtml5TreeBuilder::appendVoidInputToCurrent( + nsHtml5HtmlAttributes* attributes, nsIContentHandle* form) { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + nsIContentHandle* elt = + createElement(kNameSpaceID_XHTML, nsGkAtoms::input, attributes, + !form || fragment || isTemplateContents() ? nullptr : form, + currentNode, htmlCreator(NS_NewHTMLInputElement)); + appendElement(elt, currentNode); + elementPushed(kNameSpaceID_XHTML, nsGkAtoms::input, elt); + elementPopped(kNameSpaceID_XHTML, nsGkAtoms::input, elt); +} + +void nsHtml5TreeBuilder::appendVoidFormToCurrent( + nsHtml5HtmlAttributes* attributes) { + nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr); + nsIContentHandle* elt = + createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes, + currentNode, htmlCreator(NS_NewHTMLFormElement)); + formPointer = elt; + appendElement(elt, currentNode); + elementPushed(kNameSpaceID_XHTML, nsGkAtoms::form, elt); + elementPopped(kNameSpaceID_XHTML, nsGkAtoms::form, elt); +} + +void nsHtml5TreeBuilder::requestSuspension() { + tokenizer->requestSuspension(); +} + +; +bool nsHtml5TreeBuilder::isInForeign() { + return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML; +} + +bool nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint() { + if (currentPtr < 0) { + return false; + } + return !isSpecialParentInForeign(stack[currentPtr]); +} + +void nsHtml5TreeBuilder::setFragmentContext(nsAtom* context, int32_t ns, + nsIContentHandle* node, + bool quirks) { + this->contextName = context; + this->contextNamespace = ns; + this->contextNode = node; + this->fragment = (!!contextName); + this->quirks = quirks; +} + +nsIContentHandle* nsHtml5TreeBuilder::currentNode() { + return stack[currentPtr]->node; +} + +bool nsHtml5TreeBuilder::isScriptingEnabled() { return scriptingEnabled; } + +void nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled) { + this->scriptingEnabled = scriptingEnabled; +} + +void nsHtml5TreeBuilder::setForceNoQuirks(bool forceNoQuirks) { + this->forceNoQuirks = forceNoQuirks; +} + +void nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument) { + this->setForceNoQuirks(isSrcdocDocument); +} + +void nsHtml5TreeBuilder::flushCharacters() { + if (charBufferLen > 0) { + if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW) && + charBufferContainsNonWhitespace()) { + errNonSpaceInTable(); + reconstructTheActiveFormattingElements(); + if (!stack[currentPtr]->isFosterParenting()) { + appendCharacters(currentNode(), charBuffer, 0, charBufferLen); + charBufferLen = 0; + return; + } + int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE); + int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE); + if (templatePos >= tablePos) { + appendCharacters(stack[templatePos]->node, charBuffer, 0, + charBufferLen); + charBufferLen = 0; + return; + } + nsHtml5StackNode* tableElt = stack[tablePos]; + insertFosterParentedCharacters(charBuffer, 0, charBufferLen, + tableElt->node, stack[tablePos - 1]->node); + charBufferLen = 0; + return; + } + appendCharacters(currentNode(), charBuffer, 0, charBufferLen); + charBufferLen = 0; + } +} + +bool nsHtml5TreeBuilder::charBufferContainsNonWhitespace() { + for (int32_t i = 0; i < charBufferLen; i++) { + switch (charBuffer[i]) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': { + continue; + } + default: { + return true; + } + } + } + return false; +} + +nsAHtml5TreeBuilderState* nsHtml5TreeBuilder::newSnapshot() { + jArray<nsHtml5StackNode*, int32_t> listCopy = + jArray<nsHtml5StackNode*, int32_t>::newJArray(listPtr + 1); + for (int32_t i = 0; i < listCopy.length; i++) { + nsHtml5StackNode* node = listOfActiveFormattingElements[i]; + if (node) { + nsHtml5StackNode* newNode = new nsHtml5StackNode(-1); + newNode->setValues(node->getFlags(), node->ns, node->name, node->node, + node->popName, node->attributes->cloneAttributes(), + node->getHtmlCreator()); + listCopy[i] = newNode; + } else { + listCopy[i] = nullptr; + } + } + jArray<nsHtml5StackNode*, int32_t> stackCopy = + jArray<nsHtml5StackNode*, int32_t>::newJArray(currentPtr + 1); + for (int32_t i = 0; i < stackCopy.length; i++) { + nsHtml5StackNode* node = stack[i]; + int32_t listIndex = findInListOfActiveFormattingElements(node); + if (listIndex == -1) { + nsHtml5StackNode* newNode = new nsHtml5StackNode(-1); + newNode->setValues(node->getFlags(), node->ns, node->name, node->node, + node->popName, nullptr, node->getHtmlCreator()); + stackCopy[i] = newNode; + } else { + stackCopy[i] = listCopy[listIndex]; + stackCopy[i]->retain(); + } + } + jArray<int32_t, int32_t> templateModeStackCopy = + jArray<int32_t, int32_t>::newJArray(templateModePtr + 1); + nsHtml5ArrayCopy::arraycopy(templateModeStack, templateModeStackCopy, + templateModeStackCopy.length); + return new nsHtml5StateSnapshot(stackCopy, listCopy, templateModeStackCopy, + formPointer, headPointer, mode, originalMode, + framesetOk, needToDropLF, quirks); +} + +bool nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot) { + jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack(); + int32_t stackLen = snapshot->getStackLength(); + jArray<nsHtml5StackNode*, int32_t> listCopy = + snapshot->getListOfActiveFormattingElements(); + int32_t listLen = snapshot->getListOfActiveFormattingElementsLength(); + jArray<int32_t, int32_t> templateModeStackCopy = + snapshot->getTemplateModeStack(); + int32_t templateModeStackLen = snapshot->getTemplateModeStackLength(); + if (stackLen != currentPtr + 1 || listLen != listPtr + 1 || + templateModeStackLen != templateModePtr + 1 || + formPointer != snapshot->getFormPointer() || + headPointer != snapshot->getHeadPointer() || + mode != snapshot->getMode() || + originalMode != snapshot->getOriginalMode() || + framesetOk != snapshot->isFramesetOk() || + needToDropLF != snapshot->isNeedToDropLF() || + quirks != snapshot->isQuirks()) { + return false; + } + for (int32_t i = listLen - 1; i >= 0; i--) { + if (!listCopy[i] && !listOfActiveFormattingElements[i]) { + continue; + } else if (!listCopy[i] || !listOfActiveFormattingElements[i]) { + return false; + } + if (listCopy[i]->node != listOfActiveFormattingElements[i]->node) { + return false; + } + } + for (int32_t i = stackLen - 1; i >= 0; i--) { + if (stackCopy[i]->node != stack[i]->node) { + return false; + } + } + for (int32_t i = templateModeStackLen - 1; i >= 0; i--) { + if (templateModeStackCopy[i] != templateModeStack[i]) { + return false; + } + } + return true; +} + +void nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState* snapshot) { + mCurrentHtmlScriptIsAsyncOrDefer = false; + jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack(); + int32_t stackLen = snapshot->getStackLength(); + jArray<nsHtml5StackNode*, int32_t> listCopy = + snapshot->getListOfActiveFormattingElements(); + int32_t listLen = snapshot->getListOfActiveFormattingElementsLength(); + jArray<int32_t, int32_t> templateModeStackCopy = + snapshot->getTemplateModeStack(); + int32_t templateModeStackLen = snapshot->getTemplateModeStackLength(); + for (int32_t i = 0; i <= listPtr; i++) { + if (listOfActiveFormattingElements[i]) { + listOfActiveFormattingElements[i]->release(this); + } + } + if (listOfActiveFormattingElements.length < listLen) { + listOfActiveFormattingElements = + jArray<nsHtml5StackNode*, int32_t>::newJArray(listLen); + } + listPtr = listLen - 1; + for (int32_t i = 0; i <= currentPtr; i++) { + stack[i]->release(this); + } + if (stack.length < stackLen) { + stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(stackLen); + } + currentPtr = stackLen - 1; + if (templateModeStack.length < templateModeStackLen) { + templateModeStack = + jArray<int32_t, int32_t>::newJArray(templateModeStackLen); + } + templateModePtr = templateModeStackLen - 1; + for (int32_t i = 0; i < listLen; i++) { + nsHtml5StackNode* node = listCopy[i]; + if (node) { + nsHtml5StackNode* newNode = createStackNode( + node->getFlags(), node->ns, node->name, node->node, node->popName, + node->attributes->cloneAttributes(), node->getHtmlCreator()); + listOfActiveFormattingElements[i] = newNode; + } else { + listOfActiveFormattingElements[i] = nullptr; + } + } + for (int32_t i = 0; i < stackLen; i++) { + nsHtml5StackNode* node = stackCopy[i]; + int32_t listIndex = findInArray(node, listCopy); + if (listIndex == -1) { + nsHtml5StackNode* newNode = + createStackNode(node->getFlags(), node->ns, node->name, node->node, + node->popName, nullptr, node->getHtmlCreator()); + stack[i] = newNode; + } else { + stack[i] = listOfActiveFormattingElements[listIndex]; + stack[i]->retain(); + } + } + nsHtml5ArrayCopy::arraycopy(templateModeStackCopy, templateModeStack, + templateModeStackLen); + formPointer = snapshot->getFormPointer(); + headPointer = snapshot->getHeadPointer(); + mode = snapshot->getMode(); + originalMode = snapshot->getOriginalMode(); + framesetOk = snapshot->isFramesetOk(); + needToDropLF = snapshot->isNeedToDropLF(); + quirks = snapshot->isQuirks(); +} + +int32_t nsHtml5TreeBuilder::findInArray( + nsHtml5StackNode* node, jArray<nsHtml5StackNode*, int32_t> arr) { + for (int32_t i = listPtr; i >= 0; i--) { + if (node == arr[i]) { + return i; + } + } + return -1; +} + +nsIContentHandle* nsHtml5TreeBuilder::nodeFromStackWithBlinkCompat( + int32_t stackPos) { + if (stackPos > 511) { + errDeepTree(); + return stack[511]->node; + } + return stack[stackPos]->node; +} + +nsIContentHandle* nsHtml5TreeBuilder::getFormPointer() { return formPointer; } + +nsIContentHandle* nsHtml5TreeBuilder::getHeadPointer() { return headPointer; } + +jArray<nsHtml5StackNode*, int32_t> +nsHtml5TreeBuilder::getListOfActiveFormattingElements() { + return listOfActiveFormattingElements; +} + +jArray<nsHtml5StackNode*, int32_t> nsHtml5TreeBuilder::getStack() { + return stack; +} + +jArray<int32_t, int32_t> nsHtml5TreeBuilder::getTemplateModeStack() { + return templateModeStack; +} + +int32_t nsHtml5TreeBuilder::getMode() { return mode; } + +int32_t nsHtml5TreeBuilder::getOriginalMode() { return originalMode; } + +bool nsHtml5TreeBuilder::isFramesetOk() { return framesetOk; } + +bool nsHtml5TreeBuilder::isNeedToDropLF() { return needToDropLF; } + +bool nsHtml5TreeBuilder::isQuirks() { return quirks; } + +int32_t nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength() { + return listPtr + 1; +} + +int32_t nsHtml5TreeBuilder::getStackLength() { return currentPtr + 1; } + +int32_t nsHtml5TreeBuilder::getTemplateModeStackLength() { + return templateModePtr + 1; +} + +void nsHtml5TreeBuilder::initializeStatics() {} + +void nsHtml5TreeBuilder::releaseStatics() {} + +#include "nsHtml5TreeBuilderCppSupplement.h" diff --git a/parser/html/nsHtml5TreeBuilder.h b/parser/html/nsHtml5TreeBuilder.h new file mode 100644 index 0000000000..97b0876601 --- /dev/null +++ b/parser/html/nsHtml5TreeBuilder.h @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2007 Henri Sivonen + * Copyright (c) 2007-2017 Mozilla Foundation + * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla + * Foundation, and Opera Software ASA. + * + * 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit TreeBuilder.java instead and regenerate. + */ + +#ifndef nsHtml5TreeBuilder_h +#define nsHtml5TreeBuilder_h + +#include "jArray.h" +#include "mozilla/ImportScanner.h" +#include "mozilla/Likely.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsAtom.h" +#include "nsContentUtils.h" +#include "nsGkAtoms.h" +#include "nsHtml5ArrayCopy.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5DocumentMode.h" +#include "nsHtml5Highlighter.h" +#include "nsHtml5OplessBuilder.h" +#include "nsHtml5Parser.h" +#include "nsHtml5PlainTextUtils.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5StreamParser.h" +#include "nsHtml5String.h" +#include "nsHtml5TreeOperation.h" +#include "nsHtml5TreeOpExecutor.h" +#include "nsHtml5ViewSourceUtils.h" +#include "nsIContent.h" +#include "nsIContentHandle.h" +#include "nsNameSpaceManager.h" +#include "nsTraceRefcnt.h" + +class nsHtml5StreamParser; + +class nsHtml5AttributeName; +class nsHtml5ElementName; +class nsHtml5Tokenizer; +class nsHtml5UTF16Buffer; +class nsHtml5StateSnapshot; +class nsHtml5Portability; + +class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState { + private: + static char16_t REPLACEMENT_CHARACTER[]; + + public: + static const int32_t OTHER = 0; + + static const int32_t A = 1; + + static const int32_t BASE = 2; + + static const int32_t BODY = 3; + + static const int32_t BR = 4; + + static const int32_t BUTTON = 5; + + static const int32_t CAPTION = 6; + + static const int32_t COL = 7; + + static const int32_t COLGROUP = 8; + + static const int32_t FORM = 9; + + static const int32_t FRAME = 10; + + static const int32_t FRAMESET = 11; + + static const int32_t IMAGE = 12; + + static const int32_t INPUT = 13; + + static const int32_t RT_OR_RP = 14; + + static const int32_t LI = 15; + + static const int32_t LINK_OR_BASEFONT_OR_BGSOUND = 16; + + static const int32_t MATH = 17; + + static const int32_t META = 18; + + static const int32_t SVG = 19; + + static const int32_t HEAD = 20; + + static const int32_t HR = 22; + + static const int32_t HTML = 23; + + static const int32_t NOBR = 24; + + static const int32_t NOFRAMES = 25; + + static const int32_t NOSCRIPT = 26; + + static const int32_t OPTGROUP = 27; + + static const int32_t OPTION = 28; + + static const int32_t P = 29; + + static const int32_t PLAINTEXT = 30; + + static const int32_t SCRIPT = 31; + + static const int32_t SELECT = 32; + + static const int32_t STYLE = 33; + + static const int32_t TABLE = 34; + + static const int32_t TEXTAREA = 35; + + static const int32_t TITLE = 36; + + static const int32_t TR = 37; + + static const int32_t XMP = 38; + + static const int32_t TBODY_OR_THEAD_OR_TFOOT = 39; + + static const int32_t TD_OR_TH = 40; + + static const int32_t DD_OR_DT = 41; + + static const int32_t H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 = 42; + + static const int32_t MARQUEE_OR_APPLET = 43; + + static const int32_t PRE_OR_LISTING = 44; + + static const int32_t + B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U = + 45; + + static const int32_t UL_OR_OL_OR_DL = 46; + + static const int32_t IFRAME = 47; + + static const int32_t EMBED = 48; + + static const int32_t AREA_OR_WBR = 49; + + static const int32_t DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU = 50; + + static const int32_t + ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY = + 51; + + static const int32_t RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR = 52; + + static const int32_t RB_OR_RTC = 53; + + static const int32_t PARAM_OR_SOURCE_OR_TRACK = 55; + + static const int32_t MGLYPH_OR_MALIGNMARK = 56; + + static const int32_t MI_MO_MN_MS_MTEXT = 57; + + static const int32_t ANNOTATION_XML = 58; + + static const int32_t FOREIGNOBJECT_OR_DESC = 59; + + static const int32_t NOEMBED = 60; + + static const int32_t FIELDSET = 61; + + static const int32_t OUTPUT = 62; + + static const int32_t OBJECT = 63; + + static const int32_t FONT = 64; + + static const int32_t KEYGEN = 65; + + static const int32_t TEMPLATE = 66; + + static const int32_t IMG = 67; + + private: + static const int32_t IN_ROW = 0; + + static const int32_t IN_TABLE_BODY = 1; + + static const int32_t IN_TABLE = 2; + + static const int32_t IN_CAPTION = 3; + + static const int32_t IN_CELL = 4; + + static const int32_t FRAMESET_OK = 5; + + static const int32_t IN_BODY = 6; + + static const int32_t IN_HEAD = 7; + + static const int32_t IN_HEAD_NOSCRIPT = 8; + + static const int32_t IN_COLUMN_GROUP = 9; + + static const int32_t IN_SELECT_IN_TABLE = 10; + + static const int32_t IN_SELECT = 11; + + static const int32_t AFTER_BODY = 12; + + static const int32_t IN_FRAMESET = 13; + + static const int32_t AFTER_FRAMESET = 14; + + static const int32_t INITIAL = 15; + + static const int32_t BEFORE_HTML = 16; + + static const int32_t BEFORE_HEAD = 17; + + static const int32_t AFTER_HEAD = 18; + + static const int32_t AFTER_AFTER_BODY = 19; + + static const int32_t AFTER_AFTER_FRAMESET = 20; + + static const int32_t TEXT = 21; + + static const int32_t IN_TEMPLATE = 22; + + static const int32_t CHARSET_INITIAL = 0; + + static const int32_t CHARSET_C = 1; + + static const int32_t CHARSET_H = 2; + + static const int32_t CHARSET_A = 3; + + static const int32_t CHARSET_R = 4; + + static const int32_t CHARSET_S = 5; + + static const int32_t CHARSET_E = 6; + + static const int32_t CHARSET_T = 7; + + static const int32_t CHARSET_EQUALS = 8; + + static const int32_t CHARSET_SINGLE_QUOTED = 9; + + static const int32_t CHARSET_DOUBLE_QUOTED = 10; + + static const int32_t CHARSET_UNQUOTED = 11; + + static staticJArray<const char*, int32_t> QUIRKY_PUBLIC_IDS; + static const int32_t NOT_FOUND_ON_STACK = INT32_MAX; + + int32_t mode; + int32_t originalMode; + bool framesetOk; + + protected: + nsHtml5Tokenizer* tokenizer; + + private: + bool scriptingEnabled; + bool needToDropLF; + bool fragment; + RefPtr<nsAtom> contextName; + int32_t contextNamespace; + nsIContentHandle* contextNode; + autoJArray<int32_t, int32_t> templateModeStack; + int32_t templateModePtr; + autoJArray<nsHtml5StackNode*, int32_t> stackNodes; + int32_t stackNodesIdx; + int32_t numStackNodes; + autoJArray<nsHtml5StackNode*, int32_t> stack; + int32_t currentPtr; + autoJArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements; + int32_t listPtr; + nsIContentHandle* formPointer; + nsIContentHandle* headPointer; + + protected: + autoJArray<char16_t, int32_t> charBuffer; + int32_t charBufferLen; + + private: + bool quirks; + bool forceNoQuirks; + inline nsHtml5ContentCreatorFunction htmlCreator( + mozilla::dom::HTMLContentCreatorFunction htmlCreator) { + nsHtml5ContentCreatorFunction creator; + creator.html = htmlCreator; + return creator; + } + + inline nsHtml5ContentCreatorFunction svgCreator( + mozilla::dom::SVGContentCreatorFunction svgCreator) { + nsHtml5ContentCreatorFunction creator; + creator.svg = svgCreator; + return creator; + } + + public: + void startTokenization(nsHtml5Tokenizer* self); + void doctype(nsAtom* name, nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, bool forceQuirks); + void comment(char16_t* buf, int32_t start, int32_t length); + void characters(const char16_t* buf, int32_t start, int32_t length); + void zeroOriginatingReplacementCharacter(); + void zeroOrReplacementCharacter(); + void eof(); + void endTokenization(); + void startTag(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes, bool selfClosing); + + private: + void startTagTitleInHead(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes); + void startTagGenericRawText(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes); + void startTagScriptInHead(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes); + void startTagTemplateInHead(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes); + bool isTemplateContents(); + bool isTemplateModeStackEmpty(); + bool isSpecialParentInForeign(nsHtml5StackNode* stackNode); + + public: + static nsHtml5String extractCharsetFromContent(nsHtml5String attributeValue, + nsHtml5TreeBuilder* tb); + + private: + void checkMetaCharset(nsHtml5HtmlAttributes* attributes); + + public: + void endTag(nsHtml5ElementName* elementName); + + private: + void endTagTemplateInHead(); + int32_t findLastInTableScopeOrRootTemplateTbodyTheadTfoot(); + int32_t findLast(nsAtom* name); + int32_t findLastInTableScope(nsAtom* name); + int32_t findLastInButtonScope(nsAtom* name); + int32_t findLastInScope(nsAtom* name); + int32_t findLastInListScope(nsAtom* name); + int32_t findLastInScopeHn(); + void generateImpliedEndTagsExceptFor(nsAtom* name); + void generateImpliedEndTags(); + void generateImpliedEndTagsThoroughly(); + bool isSecondOnStackBody(); + void documentModeInternal(nsHtml5DocumentMode m, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier); + bool isAlmostStandards(nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier); + bool isQuirky(nsAtom* name, nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, bool forceQuirks); + void closeTheCell(int32_t eltPos); + int32_t findLastInTableScopeTdTh(); + void clearStackBackTo(int32_t eltPos); + void resetTheInsertionMode(); + void implicitlyCloseP(); + bool debugOnlyClearLastStackSlot(); + bool debugOnlyClearLastListSlot(); + void pushTemplateMode(int32_t mode); + void push(nsHtml5StackNode* node); + void silentPush(nsHtml5StackNode* node); + void append(nsHtml5StackNode* node); + inline void insertMarker() { append(nullptr); } + + void clearTheListOfActiveFormattingElementsUpToTheLastMarker(); + inline bool isCurrent(nsAtom* name) { + return stack[currentPtr]->ns == kNameSpaceID_XHTML && + name == stack[currentPtr]->name; + } + + void removeFromStack(int32_t pos); + void removeFromStack(nsHtml5StackNode* node); + void removeFromListOfActiveFormattingElements(int32_t pos); + bool adoptionAgencyEndTag(nsAtom* name); + void insertIntoStack(nsHtml5StackNode* node, int32_t position); + void insertIntoListOfActiveFormattingElements( + nsHtml5StackNode* formattingClone, int32_t bookmark); + int32_t findInListOfActiveFormattingElements(nsHtml5StackNode* node); + int32_t findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker( + nsAtom* name); + void maybeForgetEarlierDuplicateFormattingElement( + nsAtom* name, nsHtml5HtmlAttributes* attributes); + int32_t findLastOrRoot(nsAtom* name); + int32_t findLastOrRoot(int32_t group); + bool addAttributesToBody(nsHtml5HtmlAttributes* attributes); + void addAttributesToHtml(nsHtml5HtmlAttributes* attributes); + void pushHeadPointerOntoStack(); + void reconstructTheActiveFormattingElements(); + + public: + void notifyUnusedStackNode(int32_t idxInStackNodes); + + private: + nsHtml5StackNode* getUnusedStackNode(); + nsHtml5StackNode* createStackNode( + int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node, + nsAtom* popName, nsHtml5HtmlAttributes* attributes, + mozilla::dom::HTMLContentCreatorFunction htmlCreator); + nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, + nsIContentHandle* node); + nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, + nsIContentHandle* node, + nsHtml5HtmlAttributes* attributes); + nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, + nsIContentHandle* node, nsAtom* popName); + nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, + nsAtom* popName, nsIContentHandle* node); + nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, + nsIContentHandle* node, nsAtom* popName, + bool markAsIntegrationPoint); + void insertIntoFosterParent(nsIContentHandle* child); + nsIContentHandle* createAndInsertFosterParentedElement( + int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes, + nsHtml5ContentCreatorFunction creator); + nsIContentHandle* createAndInsertFosterParentedElement( + int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form, nsHtml5ContentCreatorFunction creator); + bool isInStack(nsHtml5StackNode* node); + void popTemplateMode(); + void pop(); + void popForeign(int32_t origPos, int32_t eltPos); + void silentPop(); + void popOnEof(); + void appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes); + void appendHtmlElementToDocumentAndPush(); + void appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushBodyElement(nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushBodyElement(); + void appendToCurrentNodeAndPushFormElementMayFoster( + nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushFormattingElementMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushElementMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushElementMayFosterMathML( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); + bool annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushElementMayFosterSVG( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); + void appendToCurrentNodeAndPushElementMayFoster( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form); + void appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form); + void appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, + nsHtml5HtmlAttributes* attributes); + void appendVoidElementToCurrentMayFosterSVG( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); + void appendVoidElementToCurrentMayFosterMathML( + nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); + void appendVoidInputToCurrent(nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form); + void appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes); + + protected: + void accumulateCharacters(const char16_t* buf, int32_t start, int32_t length); + void requestSuspension(); + nsIContentHandle* createElement(int32_t ns, nsAtom* name, + nsHtml5HtmlAttributes* attributes, + nsIContentHandle* intendedParent, + nsHtml5ContentCreatorFunction creator); + nsIContentHandle* createElement(int32_t ns, nsAtom* name, + nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form, + nsIContentHandle* intendedParent, + nsHtml5ContentCreatorFunction creator); + nsIContentHandle* createHtmlElementSetAsRoot( + nsHtml5HtmlAttributes* attributes); + void detachFromParent(nsIContentHandle* element); + bool hasChildren(nsIContentHandle* element); + void appendElement(nsIContentHandle* child, nsIContentHandle* newParent); + void appendChildrenToNewParent(nsIContentHandle* oldParent, + nsIContentHandle* newParent); + void insertFosterParentedChild(nsIContentHandle* child, + nsIContentHandle* table, + nsIContentHandle* stackParent); + nsIContentHandle* createAndInsertFosterParentedElement( + int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes, + nsIContentHandle* form, nsIContentHandle* table, + nsIContentHandle* stackParent, nsHtml5ContentCreatorFunction creator); + ; + void insertFosterParentedCharacters(char16_t* buf, int32_t start, + int32_t length, nsIContentHandle* table, + nsIContentHandle* stackParent); + void appendCharacters(nsIContentHandle* parent, char16_t* buf, int32_t start, + int32_t length); + void appendComment(nsIContentHandle* parent, char16_t* buf, int32_t start, + int32_t length); + void appendCommentToDocument(char16_t* buf, int32_t start, int32_t length); + void addAttributesToElement(nsIContentHandle* element, + nsHtml5HtmlAttributes* attributes); + void markMalformedIfScript(nsIContentHandle* elt); + void start(bool fragmentMode); + void end(); + void appendDoctypeToDocument(nsAtom* name, nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier); + void elementPushed(int32_t ns, nsAtom* name, nsIContentHandle* node); + void elementPopped(int32_t ns, nsAtom* name, nsIContentHandle* node); + + public: + inline bool cdataSectionAllowed() { return isInForeign(); } + + private: + bool isInForeign(); + bool isInForeignButNotHtmlOrMathTextIntegrationPoint(); + + public: + void setFragmentContext(nsAtom* context, int32_t ns, nsIContentHandle* node, + bool quirks); + + protected: + nsIContentHandle* currentNode(); + + public: + bool isScriptingEnabled(); + void setScriptingEnabled(bool scriptingEnabled); + void setForceNoQuirks(bool forceNoQuirks); + void setIsSrcdocDocument(bool isSrcdocDocument); + void flushCharacters(); + + private: + bool charBufferContainsNonWhitespace(); + + public: + nsAHtml5TreeBuilderState* newSnapshot(); + bool snapshotMatches(nsAHtml5TreeBuilderState* snapshot); + void loadState(nsAHtml5TreeBuilderState* snapshot); + + private: + int32_t findInArray(nsHtml5StackNode* node, + jArray<nsHtml5StackNode*, int32_t> arr); + nsIContentHandle* nodeFromStackWithBlinkCompat(int32_t stackPos); + + public: + nsIContentHandle* getFormPointer() override; + nsIContentHandle* getHeadPointer() override; + jArray<nsHtml5StackNode*, int32_t> getListOfActiveFormattingElements() + override; + jArray<nsHtml5StackNode*, int32_t> getStack() override; + jArray<int32_t, int32_t> getTemplateModeStack() override; + int32_t getMode() override; + int32_t getOriginalMode() override; + bool isFramesetOk() override; + bool isNeedToDropLF() override; + bool isQuirks() override; + int32_t getListOfActiveFormattingElementsLength() override; + int32_t getStackLength() override; + int32_t getTemplateModeStackLength() override; + static void initializeStatics(); + static void releaseStatics(); + +#include "nsHtml5TreeBuilderHSupplement.h" +}; + +#endif diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h new file mode 100644 index 0000000000..d32c137071 --- /dev/null +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -0,0 +1,1830 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#include "ErrorList.h" +#include "nsError.h" +#include "nsNetUtil.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/Likely.h" +#include "mozilla/StaticPrefs_dom.h" +#include "mozilla/StaticPrefs_network.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/UniquePtrExtensions.h" + +nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder) + : mode(0), + originalMode(0), + framesetOk(false), + tokenizer(nullptr), + scriptingEnabled(false), + needToDropLF(false), + fragment(false), + contextName(nullptr), + contextNamespace(kNameSpaceID_None), + contextNode(nullptr), + templateModePtr(0), + stackNodesIdx(0), + numStackNodes(0), + currentPtr(0), + listPtr(0), + formPointer(nullptr), + headPointer(nullptr), + charBufferLen(0), + quirks(false), + forceNoQuirks(false), + mBuilder(aBuilder), + mViewSource(nullptr), + mOpSink(nullptr), + mHandles(nullptr), + mHandlesUsed(0), + mSpeculativeLoadStage(nullptr), + mBroken(NS_OK), + mCurrentHtmlScriptIsAsyncOrDefer(false), + mPreventScriptExecution(false), + mGenerateSpeculativeLoads(false), + mHasSeenImportMap(false) +#ifdef DEBUG + , + mActive(false) +#endif +{ + MOZ_COUNT_CTOR(nsHtml5TreeBuilder); +} + +nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink, + nsHtml5TreeOpStage* aStage, + bool aGenerateSpeculativeLoads) + : mode(0), + originalMode(0), + framesetOk(false), + tokenizer(nullptr), + scriptingEnabled(false), + needToDropLF(false), + fragment(false), + contextName(nullptr), + contextNamespace(kNameSpaceID_None), + contextNode(nullptr), + templateModePtr(0), + stackNodesIdx(0), + numStackNodes(0), + currentPtr(0), + listPtr(0), + formPointer(nullptr), + headPointer(nullptr), + charBufferLen(0), + quirks(false), + forceNoQuirks(false), + mBuilder(nullptr), + mViewSource(nullptr), + mOpSink(aOpSink), + mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH]), + mHandlesUsed(0), + mSpeculativeLoadStage(aStage), + mBroken(NS_OK), + mCurrentHtmlScriptIsAsyncOrDefer(false), + mPreventScriptExecution(false), + mGenerateSpeculativeLoads(aGenerateSpeculativeLoads), + mHasSeenImportMap(false) +#ifdef DEBUG + , + mActive(false) +#endif +{ + MOZ_ASSERT(!(!aStage && aGenerateSpeculativeLoads), + "Must not generate speculative loads without a stage"); + MOZ_COUNT_CTOR(nsHtml5TreeBuilder); +} + +nsHtml5TreeBuilder::~nsHtml5TreeBuilder() { + MOZ_COUNT_DTOR(nsHtml5TreeBuilder); + NS_ASSERTION(!mActive, + "nsHtml5TreeBuilder deleted without ever calling end() on it!"); + mOpQueue.Clear(); +} + +nsIContentHandle* nsHtml5TreeBuilder::createElement( + int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + nsIContentHandle* aIntendedParent, nsHtml5ContentCreatorFunction aCreator) { + MOZ_ASSERT(aAttributes, "Got null attributes."); + MOZ_ASSERT(aName, "Got null name."); + MOZ_ASSERT(aNamespace == kNameSpaceID_XHTML || + aNamespace == kNameSpaceID_SVG || + aNamespace == kNameSpaceID_MathML, + "Bogus namespace."); + + if (mBuilder) { + nsIContent* intendedParent = + aIntendedParent ? static_cast<nsIContent*>(aIntendedParent) : nullptr; + + // intendedParent == nullptr is a special case where the + // intended parent is the document. + nsNodeInfoManager* nodeInfoManager = + intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager() + : mBuilder->GetNodeInfoManager(); + + nsIContent* elem; + if (aNamespace == kNameSpaceID_XHTML) { + elem = nsHtml5TreeOperation::CreateHTMLElement( + aName, aAttributes, mozilla::dom::FROM_PARSER_FRAGMENT, + nodeInfoManager, mBuilder, aCreator.html); + } else if (aNamespace == kNameSpaceID_SVG) { + elem = nsHtml5TreeOperation::CreateSVGElement( + aName, aAttributes, mozilla::dom::FROM_PARSER_FRAGMENT, + nodeInfoManager, mBuilder, aCreator.svg); + } else { + MOZ_ASSERT(aNamespace == kNameSpaceID_MathML); + elem = nsHtml5TreeOperation::CreateMathMLElement( + aName, aAttributes, nodeInfoManager, mBuilder); + } + if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() && + aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) { + delete aAttributes; + } + return elem; + } + + nsIContentHandle* content = AllocateContentHandle(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + + if (aNamespace == kNameSpaceID_XHTML) { + opCreateHTMLElement opeation( + content, aName, aAttributes, aCreator.html, aIntendedParent, + (!!mSpeculativeLoadStage) ? mozilla::dom::FROM_PARSER_NETWORK + : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE); + treeOp->Init(mozilla::AsVariant(opeation)); + } else if (aNamespace == kNameSpaceID_SVG) { + opCreateSVGElement operation( + content, aName, aAttributes, aCreator.svg, aIntendedParent, + (!!mSpeculativeLoadStage) ? mozilla::dom::FROM_PARSER_NETWORK + : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE); + treeOp->Init(mozilla::AsVariant(operation)); + } else { + // kNameSpaceID_MathML + opCreateMathMLElement operation(content, aName, aAttributes, + aIntendedParent); + treeOp->Init(mozilla::AsVariant(operation)); + } + + // mSpeculativeLoadStage is non-null only in the off-the-main-thread + // tree builder, which handles the network stream + + // Start wall of code for speculative loading and line numbers + + if (mGenerateSpeculativeLoads && mode != IN_TEMPLATE) { + switch (aNamespace) { + case kNameSpaceID_XHTML: + if (nsGkAtoms::img == aName) { + nsHtml5String loading = + aAttributes->getValue(nsHtml5AttributeName::ATTR_LOADING); + if (!mozilla::StaticPrefs::dom_image_lazy_loading_enabled() || + !loading.LowerCaseEqualsASCII("lazy")) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC); + nsHtml5String srcset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET); + nsHtml5String crossOrigin = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); + nsHtml5String referrerPolicy = aAttributes->getValue( + nsHtml5AttributeName::ATTR_REFERRERPOLICY); + nsHtml5String sizes = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES); + mSpeculativeLoadQueue.AppendElement()->InitImage( + url, crossOrigin, /* aMedia = */ nullptr, referrerPolicy, + srcset, sizes, false); + } + } else if (nsGkAtoms::source == aName) { + nsHtml5String srcset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET); + // Sources without srcset cannot be selected. The source could also be + // for a media element, but in that context doesn't use srcset. See + // comments in nsHtml5SpeculativeLoad.h about <picture> preloading + if (srcset) { + nsHtml5String sizes = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES); + nsHtml5String type = + aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); + nsHtml5String media = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA); + mSpeculativeLoadQueue.AppendElement()->InitPictureSource( + srcset, sizes, type, media); + } + } else if (nsGkAtoms::script == aName) { + nsHtml5TreeOperation* treeOp = + mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder( + NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opSetScriptLineAndColumnNumberAndFreeze operation( + content, tokenizer->getLineNumber(), + tokenizer->getColumnNumber()); + treeOp->Init(mozilla::AsVariant(operation)); + + nsHtml5String type = + aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); + if (!mHasSeenImportMap) { + // If we see an importmap, we don't want to later start + // speculative loads for modulepreloads, since such load might + // finish before the importmap is created. + nsAutoString typeString; + type.ToString(typeString); + mHasSeenImportMap = + typeString.LowerCaseFindASCII("importmap") != kNotFound; + } + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC); + if (url) { + nsHtml5String charset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + nsHtml5String crossOrigin = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); + nsHtml5String integrity = + aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); + nsHtml5String referrerPolicy = aAttributes->getValue( + nsHtml5AttributeName::ATTR_REFERRERPOLICY); + bool async = + aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC); + bool defer = + aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER); + bool noModule = + aAttributes->contains(nsHtml5AttributeName::ATTR_NOMODULE); + mSpeculativeLoadQueue.AppendElement()->InitScript( + url, charset, type, crossOrigin, /* aMedia = */ nullptr, + integrity, referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD, + async, defer, noModule, false); + mCurrentHtmlScriptIsAsyncOrDefer = async || defer; + } + } else if (nsGkAtoms::link == aName) { + nsHtml5String rel = + aAttributes->getValue(nsHtml5AttributeName::ATTR_REL); + // Not splitting on space here is bogus but the old parser didn't even + // do a case-insensitive check. + if (rel) { + if (rel.LowerCaseEqualsASCII("stylesheet")) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (url) { + nsHtml5String charset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + nsHtml5String crossOrigin = aAttributes->getValue( + nsHtml5AttributeName::ATTR_CROSSORIGIN); + nsHtml5String integrity = + aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); + nsHtml5String referrerPolicy = aAttributes->getValue( + nsHtml5AttributeName::ATTR_REFERRERPOLICY); + nsHtml5String media = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA); + mSpeculativeLoadQueue.AppendElement()->InitStyle( + url, charset, crossOrigin, media, referrerPolicy, integrity, + false); + } + } else if (rel.LowerCaseEqualsASCII("preconnect")) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (url) { + nsHtml5String crossOrigin = aAttributes->getValue( + nsHtml5AttributeName::ATTR_CROSSORIGIN); + mSpeculativeLoadQueue.AppendElement()->InitPreconnect( + url, crossOrigin); + } + } else if (mozilla::StaticPrefs::network_preload() && + rel.LowerCaseEqualsASCII("preload")) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (url) { + nsHtml5String as = + aAttributes->getValue(nsHtml5AttributeName::ATTR_AS); + nsHtml5String charset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + nsHtml5String crossOrigin = aAttributes->getValue( + nsHtml5AttributeName::ATTR_CROSSORIGIN); + nsHtml5String integrity = + aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); + nsHtml5String referrerPolicy = aAttributes->getValue( + nsHtml5AttributeName::ATTR_REFERRERPOLICY); + nsHtml5String media = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA); + + // Note that respective speculative loaders for scripts and + // styles check all additional attributes to be equal to use the + // speculative load. So, if any of them is specified and the + // preload has to take the expected effect, those attributes + // must also be specified on the actual tag to use the preload. + // Omitting an attribute on both will make the values equal + // (empty) and thus use the preload. + if (as.LowerCaseEqualsASCII("script")) { + nsHtml5String type = + aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); + mSpeculativeLoadQueue.AppendElement()->InitScript( + url, charset, type, crossOrigin, media, integrity, + referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD, + false, false, false, true); + } else if (as.LowerCaseEqualsASCII("style")) { + mSpeculativeLoadQueue.AppendElement()->InitStyle( + url, charset, crossOrigin, media, referrerPolicy, + integrity, true); + } else if (as.LowerCaseEqualsASCII("image")) { + nsHtml5String srcset = aAttributes->getValue( + nsHtml5AttributeName::ATTR_IMAGESRCSET); + nsHtml5String sizes = aAttributes->getValue( + nsHtml5AttributeName::ATTR_IMAGESIZES); + mSpeculativeLoadQueue.AppendElement()->InitImage( + url, crossOrigin, media, referrerPolicy, srcset, sizes, + true); + } else if (as.LowerCaseEqualsASCII("font")) { + mSpeculativeLoadQueue.AppendElement()->InitFont( + url, crossOrigin, media, referrerPolicy); + } else if (as.LowerCaseEqualsASCII("fetch")) { + mSpeculativeLoadQueue.AppendElement()->InitFetch( + url, crossOrigin, media, referrerPolicy); + } + // Other "as" values will be supported later. + } + } else if (mozilla::StaticPrefs::network_modulepreload() && + rel.LowerCaseEqualsASCII("modulepreload") && + !mHasSeenImportMap) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (url && url.Length() != 0) { + nsHtml5String as = + aAttributes->getValue(nsHtml5AttributeName::ATTR_AS); + nsAutoString asString; + as.ToString(asString); + if (mozilla::net::IsScriptLikeOrInvalid(asString)) { + nsHtml5String charset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + RefPtr<nsAtom> moduleType = nsGkAtoms::_module; + nsHtml5String type = + nsHtml5String::FromAtom(moduleType.forget()); + nsHtml5String crossOrigin = aAttributes->getValue( + nsHtml5AttributeName::ATTR_CROSSORIGIN); + nsHtml5String media = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA); + nsHtml5String integrity = aAttributes->getValue( + nsHtml5AttributeName::ATTR_INTEGRITY); + nsHtml5String referrerPolicy = aAttributes->getValue( + nsHtml5AttributeName::ATTR_REFERRERPOLICY); + mSpeculativeLoadQueue.AppendElement()->InitScript( + url, charset, type, crossOrigin, media, integrity, + referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD, + false, false, false, true); + } + } + } + } + } else if (nsGkAtoms::video == aName) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER); + if (url) { + mSpeculativeLoadQueue.AppendElement()->InitImage( + url, nullptr, nullptr, nullptr, nullptr, nullptr, false); + } + } else if (nsGkAtoms::style == aName) { + mImportScanner.Start(); + nsHtml5TreeOperation* treeOp = + mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder( + NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opSetStyleLineNumber operation(content, tokenizer->getLineNumber()); + treeOp->Init(mozilla::AsVariant(operation)); + } else if (nsGkAtoms::html == aName) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST); + mSpeculativeLoadQueue.AppendElement()->InitManifest(url); + } else if (nsGkAtoms::base == aName) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (url) { + mSpeculativeLoadQueue.AppendElement()->InitBase(url); + } + } else if (nsGkAtoms::meta == aName) { + if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "content-security-policy", + aAttributes->getValue( + nsHtml5AttributeName::ATTR_HTTP_EQUIV))) { + nsHtml5String csp = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); + if (csp) { + mSpeculativeLoadQueue.AppendElement()->InitMetaCSP(csp); + } + } else if (nsHtml5Portability:: + lowerCaseLiteralEqualsIgnoreAsciiCaseString( + "referrer", + aAttributes->getValue( + nsHtml5AttributeName::ATTR_NAME))) { + nsHtml5String referrerPolicy = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); + if (referrerPolicy) { + mSpeculativeLoadQueue.AppendElement()->InitMetaReferrerPolicy( + referrerPolicy); + } + } + } + break; + case kNameSpaceID_SVG: + if (nsGkAtoms::image == aName) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (!url) { + url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); + } + if (url) { + mSpeculativeLoadQueue.AppendElement()->InitImage( + url, nullptr, nullptr, nullptr, nullptr, nullptr, false); + } + } else if (nsGkAtoms::script == aName) { + nsHtml5TreeOperation* treeOp = + mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder( + NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opSetScriptLineAndColumnNumberAndFreeze operation( + content, tokenizer->getLineNumber(), + tokenizer->getColumnNumber()); + treeOp->Init(mozilla::AsVariant(operation)); + + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (!url) { + url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); + } + if (url) { + nsHtml5String type = + aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); + nsHtml5String crossOrigin = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); + nsHtml5String integrity = + aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); + nsHtml5String referrerPolicy = aAttributes->getValue( + nsHtml5AttributeName::ATTR_REFERRERPOLICY); + mSpeculativeLoadQueue.AppendElement()->InitScript( + url, nullptr, type, crossOrigin, /* aMedia = */ nullptr, + integrity, referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD, + false, false, false, false); + } + } else if (nsGkAtoms::style == aName) { + mImportScanner.Start(); + nsHtml5TreeOperation* treeOp = + mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder( + NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opSetStyleLineNumber operation(content, tokenizer->getLineNumber()); + treeOp->Init(mozilla::AsVariant(operation)); + } + break; + } + } else if (aNamespace != kNameSpaceID_MathML) { + // No speculative loader--just line numbers and defer/async check + if (nsGkAtoms::style == aName) { + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opSetStyleLineNumber operation(content, tokenizer->getLineNumber()); + treeOp->Init(mozilla::AsVariant(operation)); + } else if (nsGkAtoms::script == aName) { + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opSetScriptLineAndColumnNumberAndFreeze operation( + content, tokenizer->getLineNumber(), tokenizer->getColumnNumber()); + treeOp->Init(mozilla::AsVariant(operation)); + if (aNamespace == kNameSpaceID_XHTML) { + mCurrentHtmlScriptIsAsyncOrDefer = + aAttributes->contains(nsHtml5AttributeName::ATTR_SRC) && + (aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) || + aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER)); + } + } else if (aNamespace == kNameSpaceID_XHTML) { + if (nsGkAtoms::html == aName) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST); + nsHtml5TreeOperation* treeOp = + mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder( + NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + if (url) { + nsString + urlString; // Not Auto, because using it to hold nsStringBuffer* + url.ToString(urlString); + opProcessOfflineManifest operation(ToNewUnicode(urlString)); + treeOp->Init(mozilla::AsVariant(operation)); + } else { + opProcessOfflineManifest operation(ToNewUnicode(u""_ns)); + treeOp->Init(mozilla::AsVariant(operation)); + } + } else if (nsGkAtoms::base == aName && mViewSource) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (url) { + mViewSource->AddBase(url); + } + } + } + } + + // End wall of code for speculative loading + + return content; +} + +nsIContentHandle* nsHtml5TreeBuilder::createElement( + int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + nsIContentHandle* aFormElement, nsIContentHandle* aIntendedParent, + nsHtml5ContentCreatorFunction aCreator) { + nsIContentHandle* content = + createElement(aNamespace, aName, aAttributes, aIntendedParent, aCreator); + if (aFormElement) { + if (mBuilder) { + nsHtml5TreeOperation::SetFormElement( + static_cast<nsIContent*>(content), + static_cast<nsIContent*>(aFormElement)); + } else { + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opSetFormElement operation(content, aFormElement); + treeOp->Init(mozilla::AsVariant(operation)); + } + } + return content; +} + +nsIContentHandle* nsHtml5TreeBuilder::createHtmlElementSetAsRoot( + nsHtml5HtmlAttributes* aAttributes) { + nsHtml5ContentCreatorFunction creator; + // <html> uses NS_NewHTMLSharedElement creator + creator.html = NS_NewHTMLSharedElement; + nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsGkAtoms::html, + aAttributes, nullptr, creator); + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::AppendToDocument( + static_cast<nsIContent*>(content), mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + } else { + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + opAppendToDocument operation(content); + treeOp->Init(mozilla::AsVariant(operation)); + } + return content; +} + +nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement( + int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + nsIContentHandle* aFormElement, nsIContentHandle* aTable, + nsIContentHandle* aStackParent, nsHtml5ContentCreatorFunction aCreator) { + MOZ_ASSERT(aTable, "Null table"); + MOZ_ASSERT(aStackParent, "Null stack parent"); + + if (mBuilder) { + // Get the foster parent to use as the intended parent when creating + // the child element. + nsIContent* fosterParent = nsHtml5TreeOperation::GetFosterParent( + static_cast<nsIContent*>(aTable), + static_cast<nsIContent*>(aStackParent)); + + nsIContentHandle* child = createElement( + aNamespace, aName, aAttributes, aFormElement, fosterParent, aCreator); + + insertFosterParentedChild(child, aTable, aStackParent); + + return child; + } + + // Tree op to get the foster parent that we use as the intended parent + // when creating the child element. + nsHtml5TreeOperation* fosterParentTreeOp = mOpQueue.AppendElement(); + NS_ASSERTION(fosterParentTreeOp, "Tree op allocation failed."); + nsIContentHandle* fosterParentHandle = AllocateContentHandle(); + opGetFosterParent operation(aTable, aStackParent, fosterParentHandle); + fosterParentTreeOp->Init(mozilla::AsVariant(operation)); + + // Create the element with the correct intended parent. + nsIContentHandle* child = + createElement(aNamespace, aName, aAttributes, aFormElement, + fosterParentHandle, aCreator); + + // Insert the child into the foster parent. + insertFosterParentedChild(child, aTable, aStackParent); + + return child; +} + +void nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement) { + MOZ_ASSERT(aElement, "Null element"); + + if (mBuilder) { + nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement), mBuilder); + return; + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opDetach operation(aElement); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::appendElement(nsIContentHandle* aChild, + nsIContentHandle* aParent) { + MOZ_ASSERT(aChild, "Null child"); + MOZ_ASSERT(aParent, "Null parent"); + + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::Append( + static_cast<nsIContent*>(aChild), static_cast<nsIContent*>(aParent), + mozilla::dom::FROM_PARSER_FRAGMENT, mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + + opAppend operation(aChild, aParent, + (!!mSpeculativeLoadStage) + ? mozilla::dom::FROM_PARSER_NETWORK + : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::appendChildrenToNewParent( + nsIContentHandle* aOldParent, nsIContentHandle* aNewParent) { + MOZ_ASSERT(aOldParent, "Null old parent"); + MOZ_ASSERT(aNewParent, "Null new parent"); + + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::AppendChildrenToNewParent( + static_cast<nsIContent*>(aOldParent), + static_cast<nsIContent*>(aNewParent), mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opAppendChildrenToNewParent operation(aOldParent, aNewParent); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::insertFosterParentedCharacters( + char16_t* aBuffer, int32_t aStart, int32_t aLength, + nsIContentHandle* aTable, nsIContentHandle* aStackParent) { + MOZ_ASSERT(aBuffer, "Null buffer"); + MOZ_ASSERT(aTable, "Null table"); + MOZ_ASSERT(aStackParent, "Null stack parent"); + MOZ_ASSERT(!aStart, "aStart must always be zero."); + + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::FosterParentText( + static_cast<nsIContent*>(aStackParent), + aBuffer, // XXX aStart always ignored??? + aLength, static_cast<nsIContent*>(aTable), mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength); + if (!bufferCopy) { + // Just assigning mBroken instead of generating tree op. The caller + // of tokenizeBuffer() will call MarkAsBroken() as appropriate. + mBroken = NS_ERROR_OUT_OF_MEMORY; + requestSuspension(); + return; + } + + memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t)); + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opFosterParentText operation(aStackParent, bufferCopy.release(), aTable, + aLength); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::insertFosterParentedChild( + nsIContentHandle* aChild, nsIContentHandle* aTable, + nsIContentHandle* aStackParent) { + MOZ_ASSERT(aChild, "Null child"); + MOZ_ASSERT(aTable, "Null table"); + MOZ_ASSERT(aStackParent, "Null stack parent"); + + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::FosterParent( + static_cast<nsIContent*>(aChild), + static_cast<nsIContent*>(aStackParent), + static_cast<nsIContent*>(aTable), mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opFosterParent operation(aChild, aStackParent, aTable); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::appendCharacters(nsIContentHandle* aParent, + char16_t* aBuffer, int32_t aStart, + int32_t aLength) { + MOZ_ASSERT(aBuffer, "Null buffer"); + MOZ_ASSERT(aParent, "Null parent"); + MOZ_ASSERT(!aStart, "aStart must always be zero."); + + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::AppendText( + aBuffer, // XXX aStart always ignored??? + aLength, static_cast<nsIContent*>(aParent), mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength); + if (!bufferCopy) { + // Just assigning mBroken instead of generating tree op. The caller + // of tokenizeBuffer() will call MarkAsBroken() as appropriate. + mBroken = NS_ERROR_OUT_OF_MEMORY; + requestSuspension(); + return; + } + + memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t)); + + if (mImportScanner.ShouldScan()) { + nsTArray<nsString> imports = + mImportScanner.Scan(mozilla::Span(aBuffer, aLength)); + for (nsString& url : imports) { + mSpeculativeLoadQueue.AppendElement()->InitImportStyle(std::move(url)); + } + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opAppendText operation(aParent, bufferCopy.release(), aLength); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent, + char16_t* aBuffer, int32_t aStart, + int32_t aLength) { + MOZ_ASSERT(aBuffer, "Null buffer"); + MOZ_ASSERT(aParent, "Null parent"); + MOZ_ASSERT(!aStart, "aStart must always be zero."); + + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::AppendComment( + static_cast<nsIContent*>(aParent), + aBuffer, // XXX aStart always ignored??? + aLength, mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength); + if (!bufferCopy) { + // Just assigning mBroken instead of generating tree op. The caller + // of tokenizeBuffer() will call MarkAsBroken() as appropriate. + mBroken = NS_ERROR_OUT_OF_MEMORY; + requestSuspension(); + return; + } + + memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t)); + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opAppendComment operation(aParent, bufferCopy.release(), aLength); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer, + int32_t aStart, + int32_t aLength) { + MOZ_ASSERT(aBuffer, "Null buffer"); + MOZ_ASSERT(!aStart, "aStart must always be zero."); + + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::AppendCommentToDocument( + aBuffer, // XXX aStart always ignored??? + aLength, mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength); + if (!bufferCopy) { + // Just assigning mBroken instead of generating tree op. The caller + // of tokenizeBuffer() will call MarkAsBroken() as appropriate. + mBroken = NS_ERROR_OUT_OF_MEMORY; + requestSuspension(); + return; + } + + memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t)); + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opAppendCommentToDocument data(bufferCopy.release(), aLength); + treeOp->Init(mozilla::AsVariant(data)); +} + +void nsHtml5TreeBuilder::addAttributesToElement( + nsIContentHandle* aElement, nsHtml5HtmlAttributes* aAttributes) { + MOZ_ASSERT(aElement, "Null element"); + MOZ_ASSERT(aAttributes, "Null attributes"); + + if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + return; + } + + if (mBuilder) { + MOZ_ASSERT( + aAttributes == tokenizer->GetAttributes(), + "Using attribute other than the tokenizer's to add to body or html."); + nsresult rv = nsHtml5TreeOperation::AddAttributes( + static_cast<nsIContent*>(aElement), aAttributes, mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opAddAttributes opeation(aElement, aAttributes); + treeOp->Init(mozilla::AsVariant(opeation)); +} + +void nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle* aElement) { + MOZ_ASSERT(aElement, "Null element"); + + if (mBuilder) { + nsHtml5TreeOperation::MarkMalformedIfScript( + static_cast<nsIContent*>(aElement)); + return; + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opMarkMalformedIfScript operation(aElement); + treeOp->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::start(bool fragment) { + mCurrentHtmlScriptIsAsyncOrDefer = false; +#ifdef DEBUG + mActive = true; +#endif +} + +void nsHtml5TreeBuilder::end() { + mOpQueue.Clear(); +#ifdef DEBUG + mActive = false; +#endif +} + +void nsHtml5TreeBuilder::appendDoctypeToDocument(nsAtom* aName, + nsHtml5String aPublicId, + nsHtml5String aSystemId) { + MOZ_ASSERT(aName, "Null name"); + nsString publicId; // Not Auto, because using it to hold nsStringBuffer* + nsString systemId; // Not Auto, because using it to hold nsStringBuffer* + aPublicId.ToString(publicId); + aSystemId.ToString(systemId); + if (mBuilder) { + nsresult rv = nsHtml5TreeOperation::AppendDoctypeToDocument( + aName, publicId, systemId, mBuilder); + if (NS_FAILED(rv)) { + MarkAsBrokenAndRequestSuspensionWithBuilder(rv); + } + return; + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opAppendDoctypeToDocument operation(aName, publicId, systemId); + treeOp->Init(mozilla::AsVariant(operation)); + // nsXMLContentSink can flush here, but what's the point? + // It can also interrupt here, but we can't. +} + +void nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsAtom* aName, + nsIContentHandle* aElement) { + NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || + aNamespace == kNameSpaceID_SVG || + aNamespace == kNameSpaceID_MathML, + "Element isn't HTML, SVG or MathML!"); + NS_ASSERTION(aName, "Element doesn't have local name!"); + NS_ASSERTION(aElement, "No element!"); + /* + * The frame constructor uses recursive algorithms, so it can't deal with + * arbitrarily deep trees. This is especially a problem on Windows where + * the permitted depth of the runtime stack is rather small. + * + * The following is a protection against author incompetence--not against + * malice. There are other ways to make the DOM deep anyway. + * + * The basic idea is that when the tree builder stack gets too deep, + * append operations no longer append to the node that the HTML parsing + * algorithm says they should but instead text nodes are append to the last + * element that was seen before a magic tree builder stack threshold was + * reached and element and comment nodes aren't appended to the DOM at all. + * + * However, for security reasons, non-child descendant text nodes inside an + * SVG script or style element should not become children. Also, non-cell + * table elements shouldn't be used as surrogate parents for user experience + * reasons. + */ + if (aNamespace != kNameSpaceID_XHTML) { + return; + } + if (aName == nsGkAtoms::body || aName == nsGkAtoms::frameset) { + if (mBuilder) { + // InnerHTML and DOMParser shouldn't start layout anyway + return; + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + treeOp->Init(mozilla::AsVariant(opStartLayout())); + return; + } + if (nsIContent::RequiresDoneCreatingElement(kNameSpaceID_XHTML, aName)) { + if (mBuilder) { + nsHtml5TreeOperation::DoneCreatingElement( + static_cast<nsIContent*>(aElement)); + } else { + opDoneCreatingElement operation(aElement); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); + } + return; + } + if (mGenerateSpeculativeLoads && aName == nsGkAtoms::picture) { + // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading + mSpeculativeLoadQueue.AppendElement()->InitOpenPicture(); + return; + } + if (aName == nsGkAtoms::_template) { + if (tokenizer->TemplatePushedOrHeadPopped()) { + requestSuspension(); + } + } +} + +void nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsAtom* aName, + nsIContentHandle* aElement) { + NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || + aNamespace == kNameSpaceID_SVG || + aNamespace == kNameSpaceID_MathML, + "Element isn't HTML, SVG or MathML!"); + NS_ASSERTION(aName, "Element doesn't have local name!"); + NS_ASSERTION(aElement, "No element!"); + if (aNamespace == kNameSpaceID_MathML) { + return; + } + // we now have only SVG and HTML + if (aName == nsGkAtoms::script) { + if (mPreventScriptExecution) { + if (mBuilder) { + nsHtml5TreeOperation::PreventScriptExecution( + static_cast<nsIContent*>(aElement)); + return; + } + opPreventScriptExecution operation(aElement); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); + return; + } + if (mBuilder) { + return; + } + if (mCurrentHtmlScriptIsAsyncOrDefer) { + NS_ASSERTION(aNamespace == kNameSpaceID_XHTML, + "Only HTML scripts may be async/defer."); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opRunScriptAsyncDefer operation(aElement); + treeOp->Init(mozilla::AsVariant(operation)); + mCurrentHtmlScriptIsAsyncOrDefer = false; + return; + } + requestSuspension(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opRunScript operation(aElement, nullptr); + treeOp->Init(mozilla::AsVariant(operation)); + return; + } + // Some nodes need DoneAddingChildren() called to initialize + // properly (e.g. form state restoration). + if (nsIContent::RequiresDoneAddingChildren(aNamespace, aName)) { + if (mBuilder) { + nsHtml5TreeOperation::DoneAddingChildren( + static_cast<nsIContent*>(aElement)); + return; + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opDoneAddingChildren operation(aElement); + treeOp->Init(mozilla::AsVariant(operation)); + if (aNamespace == kNameSpaceID_XHTML && aName == nsGkAtoms::head) { + if (tokenizer->TemplatePushedOrHeadPopped()) { + requestSuspension(); + } + } + return; + } + if (aName == nsGkAtoms::style || + (aNamespace == kNameSpaceID_XHTML && aName == nsGkAtoms::link)) { + if (mBuilder) { + MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), + "Scripts must be blocked."); + mBuilder->UpdateStyleSheet(static_cast<nsIContent*>(aElement)); + return; + } + + if (aName == nsGkAtoms::style) { + nsTArray<nsString> imports = mImportScanner.Stop(); + for (nsString& url : imports) { + mSpeculativeLoadQueue.AppendElement()->InitImportStyle(std::move(url)); + } + } + + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opUpdateStyleSheet operation(aElement); + treeOp->Init(mozilla::AsVariant(operation)); + return; + } + if (aNamespace == kNameSpaceID_SVG) { + if (aName == nsGkAtoms::svg) { + if (!scriptingEnabled || mPreventScriptExecution) { + return; + } + if (mBuilder) { + nsHtml5TreeOperation::SvgLoad(static_cast<nsIContent*>(aElement)); + return; + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opSvgLoad operation(aElement); + treeOp->Init(mozilla::AsVariant(operation)); + } + return; + } + + if (mGenerateSpeculativeLoads && aName == nsGkAtoms::picture) { + // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading + mSpeculativeLoadQueue.AppendElement()->InitEndPicture(); + return; + } +} + +void nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf, + int32_t aStart, int32_t aLength) { + MOZ_RELEASE_ASSERT(charBufferLen + aLength <= charBuffer.length, + "About to memcpy past the end of the buffer!"); + memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(char16_t) * aLength); + charBufferLen += aLength; +} + +// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits +// is 2^30. Note that this is counting char16_t units. The underlying +// bytes will be twice that, but they fit even in 32-bit size_t even +// if a contiguous chunk of memory of that size is pretty unlikely to +// be available on a 32-bit system. +#define MAX_POWER_OF_TWO_IN_INT32 0x40000000 + +bool nsHtml5TreeBuilder::EnsureBufferSpace(int32_t aLength) { + // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer + // so that this method becomes unnecessary. + mozilla::CheckedInt<int32_t> worstCase(charBufferLen); + worstCase += aLength; + if (!worstCase.isValid()) { + return false; + } + if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) { + return false; + } + if (!charBuffer) { + if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) { + // Add one to round to the next power of two to avoid immediate + // reallocation once there are a few characters in the buffer. + worstCase += 1; + } + charBuffer = jArray<char16_t, int32_t>::newFallibleJArray( + mozilla::RoundUpPow2(worstCase.value())); + if (!charBuffer) { + return false; + } + } else if (worstCase.value() > charBuffer.length) { + jArray<char16_t, int32_t> newBuf = + jArray<char16_t, int32_t>::newFallibleJArray( + mozilla::RoundUpPow2(worstCase.value())); + if (!newBuf) { + return false; + } + memcpy(newBuf, charBuffer, sizeof(char16_t) * size_t(charBufferLen)); + charBuffer = newBuf; + } + return true; +} + +nsIContentHandle* nsHtml5TreeBuilder::AllocateContentHandle() { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must never allocate a handle with builder."); + return nullptr; + } + if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) { + mOldHandles.AppendElement(std::move(mHandles)); + mHandles = mozilla::MakeUnique<nsIContent*[]>( + NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH); + mHandlesUsed = 0; + } +#ifdef DEBUG + mHandles[mHandlesUsed] = reinterpret_cast<nsIContent*>(uintptr_t(0xC0DEDBAD)); +#endif + return &mHandles[mHandlesUsed++]; +} + +bool nsHtml5TreeBuilder::HasScript() { + uint32_t len = mOpQueue.Length(); + if (!len) { + return false; + } + return mOpQueue.ElementAt(len - 1).IsRunScript(); +} + +mozilla::Result<bool, nsresult> nsHtml5TreeBuilder::Flush(bool aDiscretionary) { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must never flush with builder."); + return false; + } + if (NS_SUCCEEDED(mBroken)) { + if (!aDiscretionary || !(charBufferLen && currentPtr >= 0 && + stack[currentPtr]->isFosterParenting())) { + // Don't flush text on discretionary flushes if the current element on + // the stack is a foster-parenting element and there's pending text, + // because flushing in that case would make the tree shape dependent on + // where the flush points fall. + flushCharacters(); + } + FlushLoads(); + } + if (mOpSink) { + bool hasOps = !mOpQueue.IsEmpty(); + if (hasOps) { + // If the builder is broken and mOpQueue is not empty, there must be + // one op and it must be eTreeOpMarkAsBroken. + if (NS_FAILED(mBroken)) { + MOZ_ASSERT(mOpQueue.Length() == 1, + "Tree builder is broken with a non-empty op queue whose " + "length isn't 1."); + MOZ_ASSERT(mOpQueue[0].IsMarkAsBroken(), + "Tree builder is broken but the op in queue is not marked " + "as broken."); + } + if (!mOpSink->MoveOpsFrom(mOpQueue)) { + return mozilla::Err(NS_ERROR_OUT_OF_MEMORY); + } + } + return hasOps; + } + // no op sink: throw away ops + mOpQueue.Clear(); + return false; +} + +void nsHtml5TreeBuilder::FlushLoads() { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must never flush loads with builder."); + return; + } + if (!mSpeculativeLoadQueue.IsEmpty()) { + mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue); + } +} + +void nsHtml5TreeBuilder::SetDocumentCharset(NotNull<const Encoding*> aEncoding, + nsCharsetSource aCharsetSource, + bool aCommitEncodingSpeculation) { + MOZ_ASSERT(!mBuilder, "How did we call this with builder?"); + MOZ_ASSERT(mSpeculativeLoadStage, + "How did we call this without a speculative load stage?"); + mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset( + aEncoding, aCharsetSource, aCommitEncodingSpeculation); +} + +void nsHtml5TreeBuilder::UpdateCharsetSource(nsCharsetSource aCharsetSource) { + MOZ_ASSERT(!mBuilder, "How did we call this with builder?"); + MOZ_ASSERT(mSpeculativeLoadStage, + "How did we call this without a speculative load stage (even " + "though we don't need it right here)?"); + if (mViewSource) { + mViewSource->UpdateCharsetSource(aCharsetSource); + return; + } + opUpdateCharsetSource operation(aCharsetSource); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::StreamEnded() { + MOZ_ASSERT(!mBuilder, "Must not call StreamEnded with builder."); + MOZ_ASSERT(!fragment, "Must not parse fragments off the main thread."); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + treeOp->Init(mozilla::AsVariant(opStreamEnded())); +} + +void nsHtml5TreeBuilder::NeedsCharsetSwitchTo( + NotNull<const Encoding*> aEncoding, int32_t aCharsetSource, + int32_t aLineNumber) { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must never switch charset with builder."); + return; + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + opCharsetSwitchTo opeation(aEncoding, aCharsetSource, aLineNumber); + treeOp->Init(mozilla::AsVariant(opeation)); +} + +void nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId, + bool aError, + int32_t aLineNumber) { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must never complain about charset with builder."); + return; + } + + if (mSpeculativeLoadStage) { + mSpeculativeLoadQueue.AppendElement()->InitMaybeComplainAboutCharset( + aMsgId, aError, aLineNumber); + } else { + opMaybeComplainAboutCharset opeartion(const_cast<char*>(aMsgId), aError, + aLineNumber); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(opeartion)); + } +} + +void nsHtml5TreeBuilder::TryToEnableEncodingMenu() { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must never disable encoding menu with builder."); + return; + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + treeOp->Init(mozilla::AsVariant(opEnableEncodingMenu())); +} + +void nsHtml5TreeBuilder::AddSnapshotToScript( + nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine) { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must never use snapshots with builder."); + return; + } + MOZ_ASSERT(HasScript(), "No script to add a snapshot to!"); + MOZ_ASSERT(aSnapshot, "Got null snapshot."); + mOpQueue.ElementAt(mOpQueue.Length() - 1).SetSnapshot(aSnapshot, aLine); +} + +void nsHtml5TreeBuilder::DropHandles() { + MOZ_ASSERT(!mBuilder, "Must not drop handles with builder."); + mOldHandles.Clear(); + mHandlesUsed = 0; +} + +void nsHtml5TreeBuilder::MarkAsBroken(nsresult aRv) { + if (MOZ_UNLIKELY(mBuilder)) { + MOZ_ASSERT_UNREACHABLE("Must not call this with builder."); + return; + } + mBroken = aRv; + mOpQueue.Clear(); // Previous ops don't matter anymore + opMarkAsBroken operation(aRv); + mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation)); +} + +void nsHtml5TreeBuilder::MarkAsBrokenFromPortability(nsresult aRv) { + if (mBuilder) { + MarkAsBrokenAndRequestSuspensionWithBuilder(aRv); + return; + } + mBroken = aRv; + requestSuspension(); +} + +void nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle) { + MOZ_ASSERT(!mBuilder, "Must not view source with builder."); + + startTag(nsHtml5ElementName::ELT_META, + nsHtml5ViewSourceUtils::NewMetaViewportAttributes(), false); + + startTag(nsHtml5ElementName::ELT_TITLE, + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES, false); + + // XUL will add the "Source of: " prefix. + uint32_t length = aTitle.Length(); + if (length > INT32_MAX) { + length = INT32_MAX; + } + characters(aTitle.get(), 0, (int32_t)length); + endTag(nsHtml5ElementName::ELT_TITLE); + + startTag(nsHtml5ElementName::ELT_LINK, + nsHtml5ViewSourceUtils::NewLinkAttributes(), false); + + startTag(nsHtml5ElementName::ELT_BODY, + nsHtml5ViewSourceUtils::NewBodyAttributes(), false); + + StartPlainTextBody(); +} + +void nsHtml5TreeBuilder::StartPlainText() { + MOZ_ASSERT(!mBuilder, "Must not view source with builder."); + setForceNoQuirks(true); + startTag(nsHtml5ElementName::ELT_LINK, + nsHtml5PlainTextUtils::NewLinkAttributes(), false); + + startTag(nsHtml5ElementName::ELT_BODY, + nsHtml5PlainTextUtils::NewBodyAttributes(), false); + + StartPlainTextBody(); +} + +void nsHtml5TreeBuilder::StartPlainTextBody() { + MOZ_ASSERT(!mBuilder, "Must not view source with builder."); + startTag(nsHtml5ElementName::ELT_PRE, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES, + false); + needToDropLF = false; +} + +// DocumentModeHandler +void nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m) { + if (mBuilder) { + mBuilder->SetDocumentMode(m); + return; + } + if (mSpeculativeLoadStage) { + mSpeculativeLoadQueue.AppendElement()->InitSetDocumentMode(m); + return; + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return; + } + treeOp->Init(mozilla::AsVariant(m)); +} + +nsIContentHandle* nsHtml5TreeBuilder::getDocumentFragmentForTemplate( + nsIContentHandle* aTemplate) { + if (mBuilder) { + return nsHtml5TreeOperation::GetDocumentFragmentForTemplate( + static_cast<nsIContent*>(aTemplate)); + } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible); + if (MOZ_UNLIKELY(!treeOp)) { + MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + nsIContentHandle* fragHandle = AllocateContentHandle(); + opGetDocumentFragmentForTemplate operation(aTemplate, fragHandle); + treeOp->Init(mozilla::AsVariant(operation)); + return fragHandle; +} + +nsIContentHandle* nsHtml5TreeBuilder::getFormPointerForContext( + nsIContentHandle* aContext) { + MOZ_ASSERT(mBuilder, "Must have builder."); + if (!aContext) { + return nullptr; + } + + MOZ_ASSERT(NS_IsMainThread()); + + // aContext must always be an element that already exists + // in the document. + nsIContent* contextNode = static_cast<nsIContent*>(aContext); + nsIContent* currentAncestor = contextNode; + + // We traverse the ancestors of the context node to find the nearest + // form pointer. This traversal is why aContext must not be an emtpy handle. + nsIContent* nearestForm = nullptr; + while (currentAncestor) { + if (currentAncestor->IsHTMLElement(nsGkAtoms::form)) { + nearestForm = currentAncestor; + break; + } + currentAncestor = currentAncestor->GetParent(); + } + + if (!nearestForm) { + return nullptr; + } + + return nearestForm; +} + +// Error reporting + +void nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter* aHighlighter) { + MOZ_ASSERT(!mBuilder, "Must not view source with builder."); + mViewSource = aHighlighter; +} + +void nsHtml5TreeBuilder::errDeepTree() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errDeepTree"); + } else if (!mBuilder) { + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + MOZ_ASSERT(treeOp, "Tree op allocation failed."); + opMaybeComplainAboutDeepTree operation(tokenizer->getLineNumber()); + treeOp->Init(mozilla::AsVariant(operation)); + } +} + +void nsHtml5TreeBuilder::errStrayStartTag(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStrayStartTag2", aName); + } +} + +void nsHtml5TreeBuilder::errStrayEndTag(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStrayEndTag", aName); + } +} + +void nsHtml5TreeBuilder::errUnclosedElements(int32_t aIndex, nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errUnclosedElements", aName); + } +} + +void nsHtml5TreeBuilder::errUnclosedElementsImplied(int32_t aIndex, + nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errUnclosedElementsImplied", aName); + } +} + +void nsHtml5TreeBuilder::errUnclosedElementsCell(int32_t aIndex) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errUnclosedElementsCell"); + } +} + +void nsHtml5TreeBuilder::errStrayDoctype() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStrayDoctype"); + } +} + +void nsHtml5TreeBuilder::errAlmostStandardsDoctype() { + if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) { + mViewSource->AddErrorToCurrentRun("errAlmostStandardsDoctype"); + } +} + +void nsHtml5TreeBuilder::errQuirkyDoctype() { + if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) { + mViewSource->AddErrorToCurrentRun("errQuirkyDoctype"); + } +} + +void nsHtml5TreeBuilder::errNonSpaceInTrailer() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNonSpaceInTrailer"); + } +} + +void nsHtml5TreeBuilder::errNonSpaceAfterFrameset() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNonSpaceAfterFrameset"); + } +} + +void nsHtml5TreeBuilder::errNonSpaceInFrameset() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNonSpaceInFrameset"); + } +} + +void nsHtml5TreeBuilder::errNonSpaceAfterBody() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNonSpaceAfterBody"); + } +} + +void nsHtml5TreeBuilder::errNonSpaceInColgroupInFragment() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNonSpaceInColgroupInFragment"); + } +} + +void nsHtml5TreeBuilder::errNonSpaceInNoscriptInHead() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNonSpaceInNoscriptInHead"); + } +} + +void nsHtml5TreeBuilder::errFooBetweenHeadAndBody(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errFooBetweenHeadAndBody", aName); + } +} + +void nsHtml5TreeBuilder::errStartTagWithoutDoctype() { + if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) { + mViewSource->AddErrorToCurrentRun("errStartTagWithoutDoctype"); + } +} + +void nsHtml5TreeBuilder::errNoSelectInTableScope() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNoSelectInTableScope"); + } +} + +void nsHtml5TreeBuilder::errStartSelectWhereEndSelectExpected() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStartSelectWhereEndSelectExpected"); + } +} + +void nsHtml5TreeBuilder::errStartTagWithSelectOpen(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStartTagWithSelectOpen", aName); + } +} + +void nsHtml5TreeBuilder::errBadStartTagInNoscriptInHead(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errBadStartTagInNoscriptInHead", aName); + } +} + +void nsHtml5TreeBuilder::errImage() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errImage"); + } +} + +void nsHtml5TreeBuilder::errIsindex() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errIsindex"); + } +} + +void nsHtml5TreeBuilder::errFooSeenWhenFooOpen(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errFooSeenWhenFooOpen2", aName); + } +} + +void nsHtml5TreeBuilder::errHeadingWhenHeadingOpen() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errHeadingWhenHeadingOpen"); + } +} + +void nsHtml5TreeBuilder::errFramesetStart() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errFramesetStart"); + } +} + +void nsHtml5TreeBuilder::errNoCellToClose() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNoCellToClose"); + } +} + +void nsHtml5TreeBuilder::errStartTagInTable(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStartTagInTable", aName); + } +} + +void nsHtml5TreeBuilder::errFormWhenFormOpen() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errFormWhenFormOpen"); + } +} + +void nsHtml5TreeBuilder::errTableSeenWhileTableOpen() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errTableSeenWhileTableOpen"); + } +} + +void nsHtml5TreeBuilder::errStartTagInTableBody(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStartTagInTableBody", aName); + } +} + +void nsHtml5TreeBuilder::errEndTagSeenWithoutDoctype() { + if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) { + mViewSource->AddErrorToCurrentRun("errEndTagSeenWithoutDoctype"); + } +} + +void nsHtml5TreeBuilder::errEndTagAfterBody() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEndTagAfterBody"); + } +} + +void nsHtml5TreeBuilder::errEndTagSeenWithSelectOpen(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEndTagSeenWithSelectOpen", aName); + } +} + +void nsHtml5TreeBuilder::errGarbageInColgroup() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errGarbageInColgroup"); + } +} + +void nsHtml5TreeBuilder::errEndTagBr() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEndTagBr"); + } +} + +void nsHtml5TreeBuilder::errNoElementToCloseButEndTagSeen(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNoElementToCloseButEndTagSeen", + aName); + } +} + +void nsHtml5TreeBuilder::errHtmlStartTagInForeignContext(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errHtmlStartTagInForeignContext", aName); + } +} + +void nsHtml5TreeBuilder::errNoTableRowToClose() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNoTableRowToClose"); + } +} + +void nsHtml5TreeBuilder::errNonSpaceInTable() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNonSpaceInTable"); + } +} + +void nsHtml5TreeBuilder::errUnclosedChildrenInRuby() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errUnclosedChildrenInRuby"); + } +} + +void nsHtml5TreeBuilder::errStartTagSeenWithoutRuby(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errStartTagSeenWithoutRuby", aName); + } +} + +void nsHtml5TreeBuilder::errSelfClosing() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentSlash("errSelfClosing"); + } +} + +void nsHtml5TreeBuilder::errNoCheckUnclosedElementsOnStack() { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errNoCheckUnclosedElementsOnStack"); + } +} + +void nsHtml5TreeBuilder::errEndTagDidNotMatchCurrentOpenElement( + nsAtom* aName, nsAtom* aOther) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEndTagDidNotMatchCurrentOpenElement", + aName, aOther); + } +} + +void nsHtml5TreeBuilder::errEndTagViolatesNestingRules(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEndTagViolatesNestingRules", aName); + } +} + +void nsHtml5TreeBuilder::errEndWithUnclosedElements(nsAtom* aName) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errEndWithUnclosedElements", aName); + } +} + +void nsHtml5TreeBuilder::errListUnclosedStartTags(int32_t aIgnored) { + if (MOZ_UNLIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentRun("errListUnclosedStartTags"); + } +} diff --git a/parser/html/nsHtml5TreeBuilderHSupplement.h b/parser/html/nsHtml5TreeBuilderHSupplement.h new file mode 100644 index 0000000000..2439818d74 --- /dev/null +++ b/parser/html/nsHtml5TreeBuilderHSupplement.h @@ -0,0 +1,274 @@ +/* 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/. */ + +#define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512 +private: +using Encoding = mozilla::Encoding; +template <typename T> +using NotNull = mozilla::NotNull<T>; + +nsHtml5OplessBuilder* mBuilder; +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// If mBuilder is not null, the tree op machinery is not in use and +// the fields below aren't in use, either. +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +nsHtml5Highlighter* mViewSource; +mozilla::ImportScanner mImportScanner; +nsTArray<nsHtml5TreeOperation> mOpQueue; +nsTArray<nsHtml5SpeculativeLoad> mSpeculativeLoadQueue; +nsAHtml5TreeOpSink* mOpSink; +mozilla::UniquePtr<nsIContent*[]> mHandles; +int32_t mHandlesUsed; +nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles; +nsHtml5TreeOpStage* mSpeculativeLoadStage; +nsresult mBroken; +bool mCurrentHtmlScriptIsAsyncOrDefer; +bool mPreventScriptExecution; +/** + * Whether to actually generate speculative load operations that actually + * represent speculative loads as opposed to other operations traveling + * in the same queue. True for normal loads and false for XHR, plain text, + * and View Source. Needed, because we can't just null-check + * mSpeculativeLoadStage, since it is used for transferring encoding + * information even in the XHR/plain text/View Source cases. + */ +bool mGenerateSpeculativeLoads; + +bool mHasSeenImportMap; +#ifdef DEBUG +bool mActive; +#endif + +// DocumentModeHandler +/** + * Tree builder uses this to report quirkiness of the document + */ +void documentMode(nsHtml5DocumentMode m); + +nsIContentHandle* getDocumentFragmentForTemplate(nsIContentHandle* aTemplate); + +nsIContentHandle* getFormPointerForContext(nsIContentHandle* aContext); + +/** + * Using nsIContent** instead of nsIContent* is the parser deals with DOM + * nodes in a way that works off the main thread. Non-main-thread code + * can't refcount or otherwise touch nsIContent objects in any way. + * Yet, the off-the-main-thread code needs to have a way to hold onto a + * particular node and repeatedly operate on the same node. + * + * The way this works is that the off-the-main-thread code has an + * nsIContent** for each DOM node and a given nsIContent** is only ever + * actually dereferenced into an actual nsIContent* on the main thread. + * When the off-the-main-thread code requests a new node, it gets an + * nsIContent** immediately and a tree op is enqueued for later allocating + * an actual nsIContent object and writing a pointer to it into the memory + * location pointed to by the nsIContent**. + * + * Since tree ops are in a queue, the node creating tree op will always + * run before tree ops that try to further operate on the node that the + * nsIContent** is a handle to. + * + * On-the-main-thread parts of the parser use nsIContent* instead of + * nsIContent**. Since both cases share the same parser core, the parser + * core casts both to nsIContentHandle*. + */ +nsIContentHandle* AllocateContentHandle(); + +void accumulateCharactersForced(const char16_t* aBuf, int32_t aStart, + int32_t aLength) { + accumulateCharacters(aBuf, aStart, aLength); +} + +void MarkAsBrokenAndRequestSuspensionWithBuilder(nsresult aRv) { + mBuilder->MarkAsBroken(aRv); + requestSuspension(); +} + +void MarkAsBrokenAndRequestSuspensionWithoutBuilder(nsresult aRv) { + MarkAsBroken(aRv); + requestSuspension(); +} + +void MarkAsBrokenFromPortability(nsresult aRv); + +public: +explicit nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder); + +nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink, nsHtml5TreeOpStage* aStage, + bool aGenerateSpeculativeLoads); + +~nsHtml5TreeBuilder(); + +void StartPlainTextViewSource(const nsAutoString& aTitle); + +void StartPlainText(); + +void StartPlainTextBody(); + +bool HasScript(); + +void SetOpSink(nsAHtml5TreeOpSink* aOpSink) { mOpSink = aOpSink; } + +void ClearOps() { mOpQueue.Clear(); } + +/** + * Flushes tree ops. + * @return Ok(true) if there were ops to flush, Ok(false) + * if there were no ops to flush and Err() on OOM. + */ +mozilla::Result<bool, nsresult> Flush(bool aDiscretionary = false); + +void FlushLoads(); + +/** + * Sets the document charset via the speculation queue. + * + * @param aCommitEncodingSpeculation true iff the main thread should + * treat the first speculation as an + * encoding speculation. + */ +void SetDocumentCharset(NotNull<const Encoding*> aEncoding, + nsCharsetSource aCharsetSource, + bool aCommitEncodingSpeculation); + +/** + * Updates the charset source via the op queue. + */ +void UpdateCharsetSource(nsCharsetSource aCharsetSource); + +void StreamEnded(); + +void NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding, int32_t aSource, + int32_t aLineNumber); + +void MaybeComplainAboutCharset(const char* aMsgId, bool aError, + int32_t aLineNumber); + +void TryToEnableEncodingMenu(); + +void AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine); + +void DropHandles(); + +void SetPreventScriptExecution(bool aPrevent) { + mPreventScriptExecution = aPrevent; +} + +bool HasBuilder() { return mBuilder; } + +/** + * Makes sure the buffers are large enough to be able to tokenize aLength + * UTF-16 code units before having to make the buffers larger. + * + * @param aLength the number of UTF-16 code units to be tokenized before the + * next call to this method. + * @return true if successful; false if out of memory + */ +bool EnsureBufferSpace(int32_t aLength); + +void EnableViewSource(nsHtml5Highlighter* aHighlighter); + +void errDeepTree(); + +void errStrayStartTag(nsAtom* aName); + +void errStrayEndTag(nsAtom* aName); + +void errUnclosedElements(int32_t aIndex, nsAtom* aName); + +void errUnclosedElementsImplied(int32_t aIndex, nsAtom* aName); + +void errUnclosedElementsCell(int32_t aIndex); + +void errStrayDoctype(); + +void errAlmostStandardsDoctype(); + +void errQuirkyDoctype(); + +void errNonSpaceInTrailer(); + +void errNonSpaceAfterFrameset(); + +void errNonSpaceInFrameset(); + +void errNonSpaceAfterBody(); + +void errNonSpaceInColgroupInFragment(); + +void errNonSpaceInNoscriptInHead(); + +void errFooBetweenHeadAndBody(nsAtom* aName); + +void errStartTagWithoutDoctype(); + +void errNoSelectInTableScope(); + +void errStartSelectWhereEndSelectExpected(); + +void errStartTagWithSelectOpen(nsAtom* aName); + +void errBadStartTagInNoscriptInHead(nsAtom* aName); + +void errImage(); + +void errIsindex(); + +void errFooSeenWhenFooOpen(nsAtom* aName); + +void errHeadingWhenHeadingOpen(); + +void errFramesetStart(); + +void errNoCellToClose(); + +void errStartTagInTable(nsAtom* aName); + +void errFormWhenFormOpen(); + +void errTableSeenWhileTableOpen(); + +void errStartTagInTableBody(nsAtom* aName); + +void errEndTagSeenWithoutDoctype(); + +void errEndTagAfterBody(); + +void errEndTagSeenWithSelectOpen(nsAtom* aName); + +void errGarbageInColgroup(); + +void errEndTagBr(); + +void errNoElementToCloseButEndTagSeen(nsAtom* aName); + +void errHtmlStartTagInForeignContext(nsAtom* aName); + +void errNoTableRowToClose(); + +void errNonSpaceInTable(); + +void errUnclosedChildrenInRuby(); + +void errStartTagSeenWithoutRuby(nsAtom* aName); + +void errSelfClosing(); + +void errNoCheckUnclosedElementsOnStack(); + +void errEndTagDidNotMatchCurrentOpenElement(nsAtom* aName, nsAtom* aOther); + +void errEndTagViolatesNestingRules(nsAtom* aName); + +void errEndWithUnclosedElements(nsAtom* aName); + +void errListUnclosedStartTags(int32_t aIgnored); + +void MarkAsBroken(nsresult aRv); + +/** + * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0) + * value if broken. + */ +nsresult IsBroken() { return mBroken; } diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp new file mode 100644 index 0000000000..b74246fdca --- /dev/null +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -0,0 +1,1405 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=2 et tw=80: */ +/* 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/. */ + +#include "mozilla/DebugOnly.h" +#include "mozilla/Likely.h" +#include "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/MediaList.h" +#include "mozilla/dom/ScriptLoader.h" +#include "mozilla/dom/nsCSPContext.h" +#include "mozilla/dom/nsCSPService.h" + +#include "mozAutoDocUpdate.h" +#include "mozilla/IdleTaskRunner.h" +#include "mozilla/Preferences.h" +#include "mozilla/ProfilerLabels.h" +#include "mozilla/ProfilerMarkers.h" +#include "mozilla/StaticPrefs_content.h" +#include "mozilla/StaticPrefs_security.h" +#include "mozilla/StaticPrefs_view_source.h" +#include "mozilla/Telemetry.h" +#include "mozilla/css/Loader.h" +#include "mozilla/fallible.h" +#include "nsContentUtils.h" +#include "nsDocShell.h" +#include "nsError.h" +#include "nsHTMLDocument.h" +#include "nsHtml5AutoPauseUpdate.h" +#include "nsHtml5Parser.h" +#include "nsHtml5StreamParser.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5TreeOpExecutor.h" +#include "nsIContentSecurityPolicy.h" +#include "nsIDocShell.h" +#include "nsIDocShellTreeItem.h" +#include "nsINestedURI.h" +#include "nsIHttpChannel.h" +#include "nsIScriptContext.h" +#include "nsIScriptError.h" +#include "nsIScriptGlobalObject.h" +#include "nsIViewSourceChannel.h" +#include "nsNetUtil.h" +#include "xpcpublic.h" + +using namespace mozilla; + +static LazyLogModule gCharsetMenuLog("Chardetng"); + +#define LOGCHARDETNG(args) MOZ_LOG(gCharsetMenuLog, LogLevel::Debug, args) + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(nsHtml5TreeOpExecutor, + nsHtml5DocumentBuilder, + nsIContentSink) + +class nsHtml5ExecutorReflusher : public Runnable { + private: + RefPtr<nsHtml5TreeOpExecutor> mExecutor; + + public: + explicit nsHtml5ExecutorReflusher(nsHtml5TreeOpExecutor* aExecutor) + : Runnable("nsHtml5ExecutorReflusher"), mExecutor(aExecutor) {} + NS_IMETHOD Run() override { + dom::Document* doc = mExecutor->GetDocument(); + if (XRE_IsContentProcess() && + nsContentUtils:: + HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint( + doc)) { + // Possible early paint pending, reuse the runnable and try to + // call RunFlushLoop later. + nsCOMPtr<nsIRunnable> flusher = this; + if (NS_SUCCEEDED( + doc->Dispatch(TaskCategory::Network, flusher.forget()))) { + PROFILER_MARKER_UNTYPED("HighPrio blocking parser flushing(2)", DOM); + return NS_OK; + } + } + mExecutor->RunFlushLoop(); + return NS_OK; + } +}; + +class MOZ_RAII nsHtml5AutoFlush final { + private: + RefPtr<nsHtml5TreeOpExecutor> mExecutor; + size_t mOpsToRemove; + + public: + explicit nsHtml5AutoFlush(nsHtml5TreeOpExecutor* aExecutor) + : mExecutor(aExecutor), mOpsToRemove(aExecutor->OpQueueLength()) { + mExecutor->BeginFlush(); + mExecutor->BeginDocUpdate(); + } + ~nsHtml5AutoFlush() { + if (mExecutor->IsInDocUpdate()) { + mExecutor->EndDocUpdate(); + } else { + // We aren't in an update if nsHtml5AutoPauseUpdate + // caused something to terminate the parser. + MOZ_RELEASE_ASSERT( + mExecutor->IsComplete(), + "How do we have mParser but the doc update isn't open?"); + } + mExecutor->EndFlush(); + mExecutor->RemoveFromStartOfOpQueue(mOpsToRemove); + } + void SetNumberOfOpsToRemove(size_t aOpsToRemove) { + MOZ_ASSERT(aOpsToRemove < mOpsToRemove, + "Requested partial clearing of op queue but the number to clear " + "wasn't less than the length of the queue."); + mOpsToRemove = aOpsToRemove; + } +}; + +static LinkedList<nsHtml5TreeOpExecutor>* gBackgroundFlushList = nullptr; +StaticRefPtr<IdleTaskRunner> gBackgroundFlushRunner; + +nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor() + : nsHtml5DocumentBuilder(false), + mSuppressEOF(false), + mReadingFromStage(false), + mStreamParser(nullptr), + mPreloadedURLs(23), // Mean # of preloadable resources per page on dmoz + mStarted(false), + mRunFlushLoopOnStack(false), + mCallContinueInterruptedParsingIfEnabled(false), + mAlreadyComplainedAboutCharset(false), + mAlreadyComplainedAboutDeepTree(false) {} + +nsHtml5TreeOpExecutor::~nsHtml5TreeOpExecutor() { + if (gBackgroundFlushList && isInList()) { + ClearOpQueue(); + removeFrom(*gBackgroundFlushList); + if (gBackgroundFlushList->isEmpty()) { + delete gBackgroundFlushList; + gBackgroundFlushList = nullptr; + if (gBackgroundFlushRunner) { + gBackgroundFlushRunner->Cancel(); + gBackgroundFlushRunner = nullptr; + } + } + } + MOZ_ASSERT(NS_FAILED(mBroken) || mOpQueue.IsEmpty(), + "Somehow there's stuff in the op queue."); +} + +// nsIContentSink +NS_IMETHODIMP +nsHtml5TreeOpExecutor::WillParse() { + MOZ_ASSERT_UNREACHABLE("No one should call this"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +nsresult nsHtml5TreeOpExecutor::WillBuildModel() { + mDocument->AddObserver(this); + WillBuildModelImpl(); + GetDocument()->BeginLoad(); + if (mDocShell && !GetDocument()->GetWindow() && !IsExternalViewSource()) { + // Not loading as data but script global object not ready + return MarkAsBroken(NS_ERROR_DOM_INVALID_STATE_ERR); + } + return NS_OK; +} + +// This is called when the tree construction has ended +NS_IMETHODIMP +nsHtml5TreeOpExecutor::DidBuildModel(bool aTerminated) { + if (mRunsToCompletion) { + return NS_OK; + } + + MOZ_RELEASE_ASSERT(!IsInDocUpdate(), + "DidBuildModel from inside a doc update."); + + RefPtr<nsHtml5TreeOpExecutor> pin(this); + auto queueClearer = MakeScopeExit([&] { + if (aTerminated && (mFlushState == eNotFlushing)) { + ClearOpQueue(); // clear in order to be able to assert in destructor + } + }); + + // This comes from nsXMLContentSink and nsHTMLContentSink + // If this parser has been marked as broken, treat the end of parse as + // forced termination. + DidBuildModelImpl(aTerminated || NS_FAILED(IsBroken())); + + bool destroying = true; + if (mDocShell) { + mDocShell->IsBeingDestroyed(&destroying); + } + + if (!destroying) { + mDocument->OnParsingCompleted(); + + if (!mLayoutStarted) { + // We never saw the body, and layout never got started. Force + // layout *now*, to get an initial reflow. + + // NOTE: only force the layout if we are NOT destroying the + // docshell. If we are destroying it, then starting layout will + // likely cause us to crash, or at best waste a lot of time as we + // are just going to tear it down anyway. + nsContentSink::StartLayout(false); + } + } + + ScrollToRef(); + mDocument->RemoveObserver(this); + if (!mParser) { + // DidBuildModelImpl may cause mParser to be nulled out + // Return early to avoid unblocking the onload event too many times. + return NS_OK; + } + + // We may not have called BeginLoad() if loading is terminated before + // OnStartRequest call. + if (mStarted) { + mDocument->EndLoad(); + + // Gather telemetry only for top-level content navigations in order to + // avoid noise from ad iframes. + bool topLevel = false; + if (mozilla::dom::BrowsingContext* bc = mDocument->GetBrowsingContext()) { + topLevel = bc->IsTopContent(); + } + + // Gather telemetry only for text/html and text/plain (excluding CSS, JS, + // etc. being viewed as text.) + nsAutoString contentType; + mDocument->GetContentType(contentType); + bool htmlOrPlain = contentType.EqualsLiteral(u"text/html") || + contentType.EqualsLiteral(u"text/plain"); + + // Gather telemetry only for HTTP status code 200 in order to exclude + // error pages. + bool httpOk = false; + nsCOMPtr<nsIChannel> channel; + nsresult rv = GetParser()->GetChannel(getter_AddRefs(channel)); + if (NS_SUCCEEDED(rv) && channel) { + nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel); + if (httpChannel) { + uint32_t httpStatus; + rv = httpChannel->GetResponseStatus(&httpStatus); + if (NS_SUCCEEDED(rv) && httpStatus == 200) { + httpOk = true; + } + } + } + + // Gather chardetng telemetry + MOZ_ASSERT(mDocument->IsHTMLDocument()); + if (httpOk && htmlOrPlain && topLevel && !aTerminated && + !mDocument->AsHTMLDocument()->IsViewSource()) { + // We deliberately measure only normally-completed (non-aborted) loads + // that are not View Source loads. This seems like a better place for + // checking normal completion than anything in nsHtml5StreamParser. + bool plain = mDocument->AsHTMLDocument()->IsPlainText(); + int32_t charsetSource = mDocument->GetDocumentCharacterSetSource(); + switch (charsetSource) { + case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: + if (plain) { + LOGCHARDETNG(("TEXT::UtfInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::UtfInitial); + } else { + LOGCHARDETNG(("HTML::UtfInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::UtfInitial); + } + break; + case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: + if (plain) { + LOGCHARDETNG(("TEXT::GenericInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT:: + GenericInitial); + } else { + LOGCHARDETNG(("HTML::GenericInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML:: + GenericInitial); + } + break; + case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: + if (plain) { + LOGCHARDETNG(("TEXT::ContentInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT:: + ContentInitial); + } else { + LOGCHARDETNG(("HTML::ContentInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML:: + ContentInitial); + } + break; + case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: + if (plain) { + LOGCHARDETNG(("TEXT::TldInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::TldInitial); + } else { + LOGCHARDETNG(("HTML::TldInitial")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::TldInitial); + } + break; + case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: + if (plain) { + LOGCHARDETNG(("TEXT::UtfFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::UtfFinal); + } else { + LOGCHARDETNG(("HTML::UtfFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::UtfFinal); + } + break; + case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: + if (plain) { + LOGCHARDETNG(("TEXT::GenericFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT:: + GenericFinal); + } else { + LOGCHARDETNG(("HTML::GenericFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML:: + GenericFinal); + } + break; + case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: + if (plain) { + LOGCHARDETNG(("TEXT::GenericFinalA")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT:: + GenericFinalA); + } else { + LOGCHARDETNG(("HTML::GenericFinalA")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML:: + GenericFinalA); + } + break; + case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: + if (plain) { + LOGCHARDETNG(("TEXT::ContentFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT:: + ContentFinal); + } else { + LOGCHARDETNG(("HTML::ContentFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML:: + ContentFinal); + } + break; + case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: + if (plain) { + LOGCHARDETNG(("TEXT::ContentFinalA")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT:: + ContentFinalA); + } else { + LOGCHARDETNG(("HTML::ContentFinalA")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML:: + ContentFinalA); + } + break; + case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: + if (plain) { + LOGCHARDETNG(("TEXT::TldFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::TldFinal); + } else { + LOGCHARDETNG(("HTML::TldFinal")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::TldFinal); + } + break; + case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: + if (plain) { + LOGCHARDETNG(("TEXT::TldFinalA")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::TldFinalA); + } else { + LOGCHARDETNG(("HTML::TldFinalA")); + Telemetry::AccumulateCategorical( + Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::TldFinalA); + } + break; + default: + // Chardetng didn't run automatically or the input was all ASCII. + break; + } + } + } + + // Dropping the stream parser changes the parser's apparent + // script-createdness, which is why the stream parser must not be dropped + // before this executor's nsHtml5Parser has been made unreachable from its + // nsHTMLDocument. (mDocument->EndLoad() above drops the parser from the + // document.) + GetParser()->DropStreamParser(); + DropParserAndPerfHint(); +#ifdef GATHER_DOCWRITE_STATISTICS + printf("UNSAFE SCRIPTS: %d\n", sUnsafeDocWrites); + printf("TOKENIZER-SAFE SCRIPTS: %d\n", sTokenSafeDocWrites); + printf("TREEBUILDER-SAFE SCRIPTS: %d\n", sTreeSafeDocWrites); +#endif +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH + printf("MAX NOTIFICATION BATCH LEN: %d\n", sAppendBatchMaxSize); + if (sAppendBatchExaminations != 0) { + printf("AVERAGE SLOTS EXAMINED: %d\n", + sAppendBatchSlotsExamined / sAppendBatchExaminations); + } +#endif + return NS_OK; +} + +NS_IMETHODIMP +nsHtml5TreeOpExecutor::WillInterrupt() { + MOZ_ASSERT_UNREACHABLE("Don't call. For interface compat only."); + return NS_ERROR_NOT_IMPLEMENTED; +} + +void nsHtml5TreeOpExecutor::WillResume() { + MOZ_ASSERT_UNREACHABLE("Don't call. For interface compat only."); +} + +NS_IMETHODIMP +nsHtml5TreeOpExecutor::SetParser(nsParserBase* aParser) { + mParser = aParser; + return NS_OK; +} + +void nsHtml5TreeOpExecutor::InitialTranslationCompleted() { + nsContentSink::StartLayout(false); +} + +void nsHtml5TreeOpExecutor::FlushPendingNotifications(FlushType aType) { + if (aType >= FlushType::EnsurePresShellInitAndFrames) { + // Bug 577508 / 253951 + nsContentSink::StartLayout(true); + } +} + +nsISupports* nsHtml5TreeOpExecutor::GetTarget() { + return ToSupports(mDocument); +} + +nsresult nsHtml5TreeOpExecutor::MarkAsBroken(nsresult aReason) { + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + mBroken = aReason; + if (mStreamParser) { + mStreamParser->Terminate(); + } + // We are under memory pressure, but let's hope the following allocation + // works out so that we get to terminate and clean up the parser from + // a safer point. + if (mParser && mDocument) { // can mParser ever be null here? + nsCOMPtr<nsIRunnable> terminator = NewRunnableMethod( + "nsHtml5Parser::Terminate", GetParser(), &nsHtml5Parser::Terminate); + if (NS_FAILED( + mDocument->Dispatch(TaskCategory::Network, terminator.forget()))) { + NS_WARNING("failed to dispatch executor flush event"); + } + } + return aReason; +} + +static bool BackgroundFlushCallback(TimeStamp /*aDeadline*/) { + RefPtr<nsHtml5TreeOpExecutor> ex = gBackgroundFlushList->popFirst(); + if (ex) { + ex->RunFlushLoop(); + } + if (gBackgroundFlushList && gBackgroundFlushList->isEmpty()) { + delete gBackgroundFlushList; + gBackgroundFlushList = nullptr; + gBackgroundFlushRunner->Cancel(); + gBackgroundFlushRunner = nullptr; + return true; + } + return true; +} + +void nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync() { + if (mDocument && !mDocument->IsInBackgroundWindow()) { + nsCOMPtr<nsIRunnable> flusher = new nsHtml5ExecutorReflusher(this); + if (NS_FAILED( + mDocument->Dispatch(TaskCategory::Network, flusher.forget()))) { + NS_WARNING("failed to dispatch executor flush event"); + } + } else { + if (!gBackgroundFlushList) { + gBackgroundFlushList = new LinkedList<nsHtml5TreeOpExecutor>(); + } + if (!isInList()) { + gBackgroundFlushList->insertBack(this); + } + if (gBackgroundFlushRunner) { + return; + } + // Now we set up a repetitive idle scheduler for flushing background list. + gBackgroundFlushRunner = IdleTaskRunner::Create( + &BackgroundFlushCallback, + "nsHtml5TreeOpExecutor::BackgroundFlushCallback", + 0, // Start looking for idle time immediately. + TimeDuration::FromMilliseconds(250), // The hard deadline. + TimeDuration::FromMicroseconds( + StaticPrefs::content_sink_interactive_parse_time()), // Required + // budget. + true, // repeating + [] { return false; }); // MayStopProcessing + } +} + +void nsHtml5TreeOpExecutor::FlushSpeculativeLoads() { + nsTArray<nsHtml5SpeculativeLoad> speculativeLoadQueue; + mStage.MoveSpeculativeLoadsTo(speculativeLoadQueue); + nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements(); + nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length(); + for (nsHtml5SpeculativeLoad* iter = start; iter < end; ++iter) { + if (MOZ_UNLIKELY(!mParser)) { + // An extension terminated the parser from a HTTP observer. + return; + } + iter->Perform(this); + } +} + +class nsHtml5FlushLoopGuard { + private: + RefPtr<nsHtml5TreeOpExecutor> mExecutor; +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH + uint32_t mStartTime; +#endif + public: + explicit nsHtml5FlushLoopGuard(nsHtml5TreeOpExecutor* aExecutor) + : mExecutor(aExecutor) +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH + , + mStartTime(PR_IntervalToMilliseconds(PR_IntervalNow())) +#endif + { + mExecutor->mRunFlushLoopOnStack = true; + } + ~nsHtml5FlushLoopGuard() { +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH + uint32_t timeOffTheEventLoop = + PR_IntervalToMilliseconds(PR_IntervalNow()) - mStartTime; + if (timeOffTheEventLoop > + nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop) { + nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop = timeOffTheEventLoop; + } + printf("Longest time off the event loop: %d\n", + nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop); +#endif + + mExecutor->mRunFlushLoopOnStack = false; + } +}; + +/** + * The purpose of the loop here is to avoid returning to the main event loop + */ +void nsHtml5TreeOpExecutor::RunFlushLoop() { + AUTO_PROFILER_LABEL("nsHtml5TreeOpExecutor::RunFlushLoop", OTHER); + + if (mRunFlushLoopOnStack) { + // There's already a RunFlushLoop() on the call stack. + return; + } + + nsHtml5FlushLoopGuard guard(this); // this is also the self-kungfu! + + RefPtr<nsParserBase> parserKungFuDeathGrip(mParser); + RefPtr<nsHtml5StreamParser> streamParserGrip; + if (mParser) { + streamParserGrip = GetParser()->GetStreamParser(); + } + Unused << streamParserGrip; // Intentionally not used within function + + // Remember the entry time + (void)nsContentSink::WillParseImpl(); + + for (;;) { + if (!mParser) { + // Parse has terminated. + ClearOpQueue(); // clear in order to be able to assert in destructor + return; + } + + if (NS_FAILED(IsBroken())) { + return; + } + + if (!parserKungFuDeathGrip->IsParserEnabled()) { + // The parser is blocked. + return; + } + + if (mFlushState != eNotFlushing) { + // XXX Can this happen? In case it can, let's avoid crashing. + return; + } + + // If there are scripts executing, then the content sink is jumping the gun + // (probably due to a synchronous XMLHttpRequest) and will re-enable us + // later, see bug 460706. + if (IsScriptExecuting()) { + return; + } + + if (mReadingFromStage) { + nsTArray<nsHtml5SpeculativeLoad> speculativeLoadQueue; + MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing, + "mOpQueue modified during flush."); + if (!mStage.MoveOpsAndSpeculativeLoadsTo(mOpQueue, + speculativeLoadQueue)) { + MarkAsBroken(nsresult::NS_ERROR_OUT_OF_MEMORY); + return; + } + + // Make sure speculative loads never start after the corresponding + // normal loads for the same URLs. + nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements(); + nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length(); + for (nsHtml5SpeculativeLoad* iter = start; iter < end; ++iter) { + iter->Perform(this); + if (MOZ_UNLIKELY(!mParser)) { + // An extension terminated the parser from a HTTP observer. + ClearOpQueue(); // clear in order to be able to assert in destructor + return; + } + } + } else { + FlushSpeculativeLoads(); // Make sure speculative loads never start after + // the corresponding normal loads for the same + // URLs. + if (MOZ_UNLIKELY(!mParser)) { + // An extension terminated the parser from a HTTP observer. + ClearOpQueue(); // clear in order to be able to assert in destructor + return; + } + // Now parse content left in the document.write() buffer queue if any. + // This may generate tree ops on its own or dequeue a speculation. + nsresult rv = GetParser()->ParseUntilBlocked(); + + // ParseUntilBlocked flushes operations from the stage to the OpQueue. + // Those operations may have accompanying speculative operations. + // If so, we have to flush those speculative loads so that we maintain + // the invariant that no speculative load starts after the corresponding + // normal load for the same URL. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=1513292#c80 + // for a more detailed explanation of why this is necessary. + FlushSpeculativeLoads(); + + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + return; + } + } + + if (mOpQueue.IsEmpty()) { + // Avoid bothering the rest of the engine with a doc update if there's + // nothing to do. + return; + } + + nsIContent* scriptElement = nullptr; + bool interrupted = false; + bool streamEnded = false; + + { + // autoFlush clears mOpQueue in its destructor unless + // SetNumberOfOpsToRemove is called first, in which case only + // some ops from the start of the queue are cleared. + nsHtml5AutoFlush autoFlush(this); + + nsHtml5TreeOperation* first = mOpQueue.Elements(); + nsHtml5TreeOperation* last = first + mOpQueue.Length() - 1; + for (nsHtml5TreeOperation* iter = first;; ++iter) { + if (MOZ_UNLIKELY(!mParser)) { + // The previous tree op caused a call to nsIParser::Terminate(). + return; + } + MOZ_ASSERT(IsInDocUpdate(), + "Tried to perform tree op outside update batch."); + nsresult rv = + iter->Perform(this, &scriptElement, &interrupted, &streamEnded); + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + break; + } + + // Be sure not to check the deadline if the last op was just performed. + if (MOZ_UNLIKELY(iter == last)) { + break; + } else if (MOZ_UNLIKELY(interrupted) || + MOZ_UNLIKELY(nsContentSink::DidProcessATokenImpl() == + NS_ERROR_HTMLPARSER_INTERRUPTED)) { + autoFlush.SetNumberOfOpsToRemove((iter - first) + 1); + + nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync(); + return; + } + } + + if (MOZ_UNLIKELY(!mParser)) { + // The parse ended during an update pause. + return; + } + if (streamEnded) { + GetParser()->PermanentlyUndefineInsertionPoint(); + } + } // end autoFlush + + if (MOZ_UNLIKELY(!mParser)) { + // Ending the doc update caused a call to nsIParser::Terminate(). + return; + } + + if (streamEnded) { + DidBuildModel(false); +#ifdef DEBUG + if (scriptElement) { + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(scriptElement); + if (!sele) { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to script, but SVG wasn't disabled."); + } + MOZ_ASSERT(sele->IsMalformed(), "Script wasn't marked as malformed."); + } +#endif + } else if (scriptElement) { + // must be tail call when mFlushState is eNotFlushing + RunScript(scriptElement); + + // Always check the clock in nsContentSink right after a script + StopDeflecting(); + if (nsContentSink::DidProcessATokenImpl() == + NS_ERROR_HTMLPARSER_INTERRUPTED) { +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH + printf("REFLUSH SCHEDULED (after script): %d\n", + ++sTimesFlushLoopInterrupted); +#endif + nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync(); + return; + } + } + } +} + +nsresult nsHtml5TreeOpExecutor::FlushDocumentWrite() { + nsresult rv = IsBroken(); + NS_ENSURE_SUCCESS(rv, rv); + + FlushSpeculativeLoads(); // Make sure speculative loads never start after the + // corresponding normal loads for the same URLs. + + if (MOZ_UNLIKELY(!mParser)) { + // The parse has ended. + ClearOpQueue(); // clear in order to be able to assert in destructor + return rv; + } + + if (mFlushState != eNotFlushing) { + // XXX Can this happen? In case it can, let's avoid crashing. + return rv; + } + + // avoid crashing near EOF + RefPtr<nsHtml5TreeOpExecutor> kungFuDeathGrip(this); + RefPtr<nsParserBase> parserKungFuDeathGrip(mParser); + Unused << parserKungFuDeathGrip; // Intentionally not used within function + RefPtr<nsHtml5StreamParser> streamParserGrip; + if (mParser) { + streamParserGrip = GetParser()->GetStreamParser(); + } + Unused << streamParserGrip; // Intentionally not used within function + + MOZ_RELEASE_ASSERT(!mReadingFromStage, + "Got doc write flush when reading from stage"); + +#ifdef DEBUG + mStage.AssertEmpty(); +#endif + + nsIContent* scriptElement = nullptr; + bool interrupted = false; + bool streamEnded = false; + + { + // autoFlush clears mOpQueue in its destructor. + nsHtml5AutoFlush autoFlush(this); + + nsHtml5TreeOperation* start = mOpQueue.Elements(); + nsHtml5TreeOperation* end = start + mOpQueue.Length(); + for (nsHtml5TreeOperation* iter = start; iter < end; ++iter) { + if (MOZ_UNLIKELY(!mParser)) { + // The previous tree op caused a call to nsIParser::Terminate(). + return rv; + } + NS_ASSERTION(IsInDocUpdate(), + "Tried to perform tree op outside update batch."); + rv = iter->Perform(this, &scriptElement, &interrupted, &streamEnded); + if (NS_FAILED(rv)) { + MarkAsBroken(rv); + break; + } + } + + if (MOZ_UNLIKELY(!mParser)) { + // The parse ended during an update pause. + return rv; + } + if (streamEnded) { + // This should be redundant but let's do it just in case. + GetParser()->PermanentlyUndefineInsertionPoint(); + } + } // autoFlush + + if (MOZ_UNLIKELY(!mParser)) { + // Ending the doc update caused a call to nsIParser::Terminate(). + return rv; + } + + if (streamEnded) { + DidBuildModel(false); +#ifdef DEBUG + if (scriptElement) { + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(scriptElement); + if (!sele) { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to script, but SVG wasn't disabled."); + } + MOZ_ASSERT(sele->IsMalformed(), "Script wasn't marked as malformed."); + } +#endif + } else if (scriptElement) { + // must be tail call when mFlushState is eNotFlushing + RunScript(scriptElement); + } + return rv; +} + +void nsHtml5TreeOpExecutor::CommitToInternalEncoding() { + if (MOZ_UNLIKELY(!mParser || !mStreamParser)) { + // An extension terminated the parser from a HTTP observer. + ClearOpQueue(); // clear in order to be able to assert in destructor + return; + } + mStreamParser->ContinueAfterScriptsOrEncodingCommitment(nullptr, nullptr, + false); +} + +[[nodiscard]] bool nsHtml5TreeOpExecutor::TakeOpsFromStage() { + return mStage.MoveOpsTo(mOpQueue); +} + +// copied from HTML content sink +bool nsHtml5TreeOpExecutor::IsScriptEnabled() { + // Note that if we have no document or no docshell or no global or whatnot we + // want to claim script _is_ enabled, so we don't parse the contents of + // <noscript> tags! + if (!mDocument || !mDocShell) { + return true; + } + + return mDocument->IsScriptEnabled(); +} + +void nsHtml5TreeOpExecutor::StartLayout(bool* aInterrupted) { + if (mLayoutStarted || !mDocument) { + return; + } + + nsHtml5AutoPauseUpdate autoPause(this); + + if (MOZ_UNLIKELY(!mParser)) { + // got terminate + return; + } + + nsContentSink::StartLayout(false); + + if (mParser) { + *aInterrupted = !GetParser()->IsParserEnabled(); + } +} + +void nsHtml5TreeOpExecutor::PauseDocUpdate(bool* aInterrupted) { + // Pausing the document update allows JS to run, and potentially block + // further parsing. + nsHtml5AutoPauseUpdate autoPause(this); + + if (MOZ_LIKELY(mParser)) { + *aInterrupted = !GetParser()->IsParserEnabled(); + } +} + +/** + * The reason why this code is here and not in the tree builder even in the + * main-thread case is to allow the control to return from the tokenizer + * before scripts run. This way, the tokenizer is not invoked re-entrantly + * although the parser is. + * + * The reason why this is called as a tail call when mFlushState is set to + * eNotFlushing is to allow re-entry to Flush() but only after the current + * Flush() has cleared the op queue and is otherwise done cleaning up after + * itself. + */ +void nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement) { + if (mRunsToCompletion) { + // We are in createContextualFragment() or in the upcoming document.parse(). + // Do nothing. Let's not even mark scripts malformed here, because that + // could cause serialization weirdness later. + return; + } + + MOZ_ASSERT(mParser, "Trying to run script with a terminated parser."); + MOZ_ASSERT(aScriptElement, "No script to run"); + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aScriptElement); + if (!sele) { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to script, but SVG wasn't disabled."); + return; + } + + if (sele->GetScriptDeferred() || sele->GetScriptAsync()) { + DebugOnly<bool> block = sele->AttemptToExecute(); + NS_ASSERTION(!block, "Defer or async script tried to block."); + return; + } + + MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing, + "Tried to run script while flushing."); + + mReadingFromStage = false; + + sele->SetCreatorParser(GetParser()); + + // Copied from nsXMLContentSink + // Now tell the script that it's ready to go. This may execute the script + // or return true, or neither if the script doesn't need executing. + bool block = sele->AttemptToExecute(); + + // If the act of insertion evaluated the script, we're fine. + // Else, block the parser till the script has loaded. + if (block) { + if (mParser) { + GetParser()->BlockParser(); + } + } else { + // mParser may have been nulled out by now, but the flusher deals + + // If this event isn't needed, it doesn't do anything. It is sometimes + // necessary for the parse to continue after complex situations. + nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync(); + } +} + +void nsHtml5TreeOpExecutor::Start() { + MOZ_ASSERT(!mStarted, "Tried to start when already started."); + mStarted = true; +} + +void nsHtml5TreeOpExecutor::UpdateCharsetSource( + nsCharsetSource aCharsetSource) { + if (mDocument) { + mDocument->SetDocumentCharacterSetSource(aCharsetSource); + } +} + +void nsHtml5TreeOpExecutor::SetDocumentCharsetAndSource( + NotNull<const Encoding*> aEncoding, nsCharsetSource aCharsetSource) { + if (mDocument) { + mDocument->SetDocumentCharacterSetSource(aCharsetSource); + mDocument->SetDocumentCharacterSet(aEncoding); + } +} + +void nsHtml5TreeOpExecutor::NeedsCharsetSwitchTo( + NotNull<const Encoding*> aEncoding, int32_t aSource, uint32_t aLineNumber) { + nsHtml5AutoPauseUpdate autoPause(this); + if (MOZ_UNLIKELY(!mParser)) { + // got terminate + return; + } + + if (!mDocShell) { + return; + } + + RefPtr<nsDocShell> docShell = static_cast<nsDocShell*>(mDocShell.get()); + + if (NS_SUCCEEDED(docShell->CharsetChangeStopDocumentLoad())) { + docShell->CharsetChangeReloadDocument(aEncoding, aSource); + } + // if the charset switch was accepted, mDocShell has called Terminate() on the + // parser by now + if (!mParser) { + return; + } + + GetParser()->ContinueAfterFailedCharsetSwitch(); +} + +void nsHtml5TreeOpExecutor::MaybeComplainAboutCharset(const char* aMsgId, + bool aError, + uint32_t aLineNumber) { + // Encoding errors don't count towards already complaining + if (!(!strcmp(aMsgId, "EncError") || !strcmp(aMsgId, "EncErrorFrame") || + !strcmp(aMsgId, "EncErrorFramePlain"))) { + if (mAlreadyComplainedAboutCharset) { + return; + } + mAlreadyComplainedAboutCharset = true; + } + nsContentUtils::ReportToConsole( + aError ? nsIScriptError::errorFlag : nsIScriptError::warningFlag, + "HTML parser"_ns, mDocument, nsContentUtils::eHTMLPARSER_PROPERTIES, + aMsgId, nsTArray<nsString>(), nullptr, u""_ns, aLineNumber); +} + +void nsHtml5TreeOpExecutor::ComplainAboutBogusProtocolCharset( + Document* aDoc, bool aUnrecognized) { + NS_ASSERTION(!mAlreadyComplainedAboutCharset, + "How come we already managed to complain?"); + mAlreadyComplainedAboutCharset = true; + nsContentUtils::ReportToConsole( + nsIScriptError::errorFlag, "HTML parser"_ns, aDoc, + nsContentUtils::eHTMLPARSER_PROPERTIES, + aUnrecognized ? "EncProtocolUnsupported" : "EncProtocolReplacement"); +} + +void nsHtml5TreeOpExecutor::MaybeComplainAboutDeepTree(uint32_t aLineNumber) { + if (mAlreadyComplainedAboutDeepTree) { + return; + } + mAlreadyComplainedAboutDeepTree = true; + nsContentUtils::ReportToConsole( + nsIScriptError::errorFlag, "HTML parser"_ns, mDocument, + nsContentUtils::eHTMLPARSER_PROPERTIES, "errDeepTree", + nsTArray<nsString>(), nullptr, u""_ns, aLineNumber); +} + +nsHtml5Parser* nsHtml5TreeOpExecutor::GetParser() { + MOZ_ASSERT(!mRunsToCompletion); + return static_cast<nsHtml5Parser*>(mParser.get()); +} + +[[nodiscard]] bool nsHtml5TreeOpExecutor::MoveOpsFrom( + nsTArray<nsHtml5TreeOperation>& aOpQueue) { + MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing, + "Ops added to mOpQueue during tree op execution."); + return !!mOpQueue.AppendElements(std::move(aOpQueue), mozilla::fallible_t()); +} + +void nsHtml5TreeOpExecutor::ClearOpQueue() { + MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing, + "mOpQueue cleared during tree op execution."); + mOpQueue.Clear(); +} + +void nsHtml5TreeOpExecutor::RemoveFromStartOfOpQueue( + size_t aNumberOfOpsToRemove) { + MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing, + "Ops removed from mOpQueue during tree op execution."); + mOpQueue.RemoveElementsAt(0, aNumberOfOpsToRemove); +} + +void nsHtml5TreeOpExecutor::InitializeDocWriteParserState( + nsAHtml5TreeBuilderState* aState, int32_t aLine) { + GetParser()->InitializeDocWriteParserState(aState, aLine); +} + +nsIURI* nsHtml5TreeOpExecutor::GetViewSourceBaseURI() { + if (!mViewSourceBaseURI) { + // We query the channel for the baseURI because in certain situations it + // cannot otherwise be determined. If this process fails, fall back to the + // standard method. + nsCOMPtr<nsIViewSourceChannel> vsc = + do_QueryInterface(mDocument->GetChannel()); + if (vsc) { + nsresult rv = vsc->GetBaseURI(getter_AddRefs(mViewSourceBaseURI)); + if (NS_SUCCEEDED(rv) && mViewSourceBaseURI) { + return mViewSourceBaseURI; + } + } + + nsCOMPtr<nsIURI> orig = mDocument->GetOriginalURI(); + if (orig->SchemeIs("view-source")) { + nsCOMPtr<nsINestedURI> nested = do_QueryInterface(orig); + NS_ASSERTION(nested, "URI with scheme view-source didn't QI to nested!"); + nested->GetInnerURI(getter_AddRefs(mViewSourceBaseURI)); + } else { + // Fail gracefully if the base URL isn't a view-source: URL. + // Not sure if this can ever happen. + mViewSourceBaseURI = orig; + } + } + return mViewSourceBaseURI; +} + +bool nsHtml5TreeOpExecutor::IsExternalViewSource() { + if (!StaticPrefs::view_source_editor_external()) { + return false; + } + if (mDocumentURI) { + return mDocumentURI->SchemeIs("view-source"); + } + return false; +} + +// Speculative loading + +nsIURI* nsHtml5TreeOpExecutor::BaseURIForPreload() { + // The URL of the document without <base> + nsIURI* documentURI = mDocument->GetDocumentURI(); + // The URL of the document with non-speculative <base> + nsIURI* documentBaseURI = mDocument->GetDocBaseURI(); + + // If the two above are different, use documentBaseURI. If they are the same, + // the document object isn't aware of a <base>, so attempt to use the + // mSpeculationBaseURI or, failing, that, documentURI. + return (documentURI == documentBaseURI) + ? (mSpeculationBaseURI ? mSpeculationBaseURI.get() : documentURI) + : documentBaseURI; +} + +already_AddRefed<nsIURI> +nsHtml5TreeOpExecutor::ConvertIfNotPreloadedYetAndMediaApplies( + const nsAString& aURL, const nsAString& aMedia) { + nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL); + if (!uri) { + return nullptr; + } + + if (!MediaApplies(aMedia)) { + return nullptr; + } + return uri.forget(); +} + +bool nsHtml5TreeOpExecutor::MediaApplies(const nsAString& aMedia) { + using dom::MediaList; + + if (aMedia.IsEmpty()) { + return true; + } + RefPtr<MediaList> media = MediaList::Create(NS_ConvertUTF16toUTF8(aMedia)); + return media->Matches(*mDocument); +} + +already_AddRefed<nsIURI> nsHtml5TreeOpExecutor::ConvertIfNotPreloadedYet( + const nsAString& aURL) { + if (aURL.IsEmpty()) { + return nullptr; + } + + nsIURI* base = BaseURIForPreload(); + auto encoding = mDocument->GetDocumentCharacterSet(); + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, encoding, base); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to create a URI"); + return nullptr; + } + + if (ShouldPreloadURI(uri)) { + return uri.forget(); + } + + return nullptr; +} + +bool nsHtml5TreeOpExecutor::ShouldPreloadURI(nsIURI* aURI) { + nsAutoCString spec; + nsresult rv = aURI->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, false); + return mPreloadedURLs.EnsureInserted(spec); +} + +dom::ReferrerPolicy nsHtml5TreeOpExecutor::GetPreloadReferrerPolicy( + const nsAString& aReferrerPolicy) { + dom::ReferrerPolicy referrerPolicy = + dom::ReferrerInfo::ReferrerPolicyAttributeFromString(aReferrerPolicy); + return GetPreloadReferrerPolicy(referrerPolicy); +} + +dom::ReferrerPolicy nsHtml5TreeOpExecutor::GetPreloadReferrerPolicy( + ReferrerPolicy aReferrerPolicy) { + if (aReferrerPolicy != dom::ReferrerPolicy::_empty) { + return aReferrerPolicy; + } + + return mDocument->GetPreloadReferrerInfo()->ReferrerPolicy(); +} + +void nsHtml5TreeOpExecutor::PreloadScript( + const nsAString& aURL, const nsAString& aCharset, const nsAString& aType, + const nsAString& aCrossOrigin, const nsAString& aMedia, + const nsAString& aIntegrity, dom::ReferrerPolicy aReferrerPolicy, + bool aScriptFromHead, bool aAsync, bool aDefer, bool aNoModule, + bool aLinkPreload) { + nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia); + if (!uri) { + return; + } + auto key = PreloadHashKey::CreateAsScript(uri, aCrossOrigin, aType); + if (mDocument->Preloads().PreloadExists(key)) { + return; + } + mDocument->ScriptLoader()->PreloadURI( + uri, aCharset, aType, aCrossOrigin, aIntegrity, aScriptFromHead, aAsync, + aDefer, aNoModule, aLinkPreload, + GetPreloadReferrerPolicy(aReferrerPolicy), 0); +} + +void nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL, + const nsAString& aCharset, + const nsAString& aCrossOrigin, + const nsAString& aMedia, + const nsAString& aReferrerPolicy, + const nsAString& aIntegrity, + bool aLinkPreload) { + nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia); + if (!uri) { + return; + } + + if (aLinkPreload) { + auto hashKey = PreloadHashKey::CreateAsStyle( + uri, mDocument->NodePrincipal(), + dom::Element::StringToCORSMode(aCrossOrigin), + css::eAuthorSheetFeatures); + if (mDocument->Preloads().PreloadExists(hashKey)) { + return; + } + } + + mDocument->PreloadStyle(uri, Encoding::ForLabel(aCharset), aCrossOrigin, + GetPreloadReferrerPolicy(aReferrerPolicy), aIntegrity, + aLinkPreload + ? css::StylePreloadKind::FromLinkRelPreloadElement + : css::StylePreloadKind::FromParser, + 0); +} + +void nsHtml5TreeOpExecutor::PreloadImage( + const nsAString& aURL, const nsAString& aCrossOrigin, + const nsAString& aMedia, const nsAString& aSrcset, const nsAString& aSizes, + const nsAString& aImageReferrerPolicy, bool aLinkPreload, + const TimeStamp& aInitTimestamp) { + nsCOMPtr<nsIURI> baseURI = BaseURIForPreload(); + bool isImgSet = false; + nsCOMPtr<nsIURI> uri = + mDocument->ResolvePreloadImage(baseURI, aURL, aSrcset, aSizes, &isImgSet); + if (uri && ShouldPreloadURI(uri) && MediaApplies(aMedia)) { + // use document wide referrer policy + mDocument->MaybePreLoadImage(uri, aCrossOrigin, + GetPreloadReferrerPolicy(aImageReferrerPolicy), + isImgSet, aLinkPreload, aInitTimestamp); + } +} + +// These calls inform the document of picture state and seen sources, such that +// it can use them to inform ResolvePreLoadImage as necessary +void nsHtml5TreeOpExecutor::PreloadPictureSource(const nsAString& aSrcset, + const nsAString& aSizes, + const nsAString& aType, + const nsAString& aMedia) { + mDocument->PreloadPictureImageSource(aSrcset, aSizes, aType, aMedia); +} + +void nsHtml5TreeOpExecutor::PreloadFont(const nsAString& aURL, + const nsAString& aCrossOrigin, + const nsAString& aMedia, + const nsAString& aReferrerPolicy) { + nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia); + if (!uri) { + return; + } + + mDocument->Preloads().PreloadFont(uri, aCrossOrigin, aReferrerPolicy, 0); +} + +void nsHtml5TreeOpExecutor::PreloadFetch(const nsAString& aURL, + const nsAString& aCrossOrigin, + const nsAString& aMedia, + const nsAString& aReferrerPolicy) { + nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia); + if (!uri) { + return; + } + + mDocument->Preloads().PreloadFetch(uri, aCrossOrigin, aReferrerPolicy, 0); +} + +void nsHtml5TreeOpExecutor::PreloadOpenPicture() { + mDocument->PreloadPictureOpened(); +} + +void nsHtml5TreeOpExecutor::PreloadEndPicture() { + mDocument->PreloadPictureClosed(); +} + +void nsHtml5TreeOpExecutor::AddBase(const nsAString& aURL) { + auto encoding = mDocument->GetDocumentCharacterSet(); + nsresult rv = NS_NewURI(getter_AddRefs(mViewSourceBaseURI), aURL, encoding, + GetViewSourceBaseURI()); + if (NS_FAILED(rv)) { + mViewSourceBaseURI = nullptr; + } +} +void nsHtml5TreeOpExecutor::SetSpeculationBase(const nsAString& aURL) { + if (mSpeculationBaseURI) { + // the first one wins + return; + } + + auto encoding = mDocument->GetDocumentCharacterSet(); + nsCOMPtr<nsIURI> newBaseURI; + DebugOnly<nsresult> rv = NS_NewURI(getter_AddRefs(newBaseURI), aURL, encoding, + mDocument->GetDocumentURI()); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to create a URI"); + if (!newBaseURI) { + return; + } + + // Check the document's CSP usually delivered via the CSP header. + if (nsCOMPtr<nsIContentSecurityPolicy> csp = mDocument->GetCsp()) { + // base-uri should not fallback to the default-src and preloads should not + // trigger violation reports. + bool cspPermitsBaseURI = true; + nsresult rv = csp->Permits( + nullptr, nullptr, newBaseURI, + nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */, + false /* aSendViolationReports */, &cspPermitsBaseURI); + if (NS_FAILED(rv) || !cspPermitsBaseURI) { + return; + } + } + + // Also check the CSP discovered from the <meta> tag during speculative + // parsing. + if (nsCOMPtr<nsIContentSecurityPolicy> csp = mDocument->GetPreloadCsp()) { + bool cspPermitsBaseURI = true; + nsresult rv = csp->Permits( + nullptr, nullptr, newBaseURI, + nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */, + false /* aSendViolationReports */, &cspPermitsBaseURI); + if (NS_FAILED(rv) || !cspPermitsBaseURI) { + return; + } + } + + mSpeculationBaseURI = newBaseURI; + mDocument->Preloads().SetSpeculationBase(mSpeculationBaseURI); +} + +void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta( + const nsAString& aMetaReferrer) { + mDocument->UpdateReferrerInfoFromMeta(aMetaReferrer, true); +} + +void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + nsresult rv = NS_OK; + nsCOMPtr<nsIContentSecurityPolicy> preloadCsp = mDocument->GetPreloadCsp(); + if (!preloadCsp) { + RefPtr<nsCSPContext> csp = new nsCSPContext(); + csp->SuppressParserLogMessages(); + preloadCsp = csp; + rv = preloadCsp->SetRequestContextWithDocument(mDocument); + NS_ENSURE_SUCCESS_VOID(rv); + } + + // Please note that multiple meta CSPs need to be joined together. + rv = preloadCsp->AppendPolicy( + aCSP, + false, // csp via meta tag can not be report only + true); // delivered through the meta tag + NS_ENSURE_SUCCESS_VOID(rv); + + nsPIDOMWindowInner* inner = mDocument->GetInnerWindow(); + if (inner) { + inner->SetPreloadCsp(preloadCsp); + } + mDocument->ApplySettingsFromCSP(true); +} + +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH +uint32_t nsHtml5TreeOpExecutor::sAppendBatchMaxSize = 0; +uint32_t nsHtml5TreeOpExecutor::sAppendBatchSlotsExamined = 0; +uint32_t nsHtml5TreeOpExecutor::sAppendBatchExaminations = 0; +uint32_t nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop = 0; +uint32_t nsHtml5TreeOpExecutor::sTimesFlushLoopInterrupted = 0; +#endif diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h new file mode 100644 index 0000000000..e47d99a1b2 --- /dev/null +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -0,0 +1,320 @@ +/* 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/. */ + +#ifndef nsHtml5TreeOpExecutor_h +#define nsHtml5TreeOpExecutor_h + +#include "nsAtom.h" +#include "nsTraceRefcnt.h" +#include "nsHtml5TreeOperation.h" +#include "nsHtml5SpeculativeLoad.h" +#include "nsTArray.h" +#include "nsContentSink.h" +#include "nsNodeInfoManager.h" +#include "nsHtml5DocumentMode.h" +#include "nsIScriptElement.h" +#include "nsIParser.h" +#include "nsAHtml5TreeOpSink.h" +#include "nsHtml5TreeOpStage.h" +#include "nsIURI.h" +#include "nsTHashSet.h" +#include "nsHashKeys.h" +#include "mozilla/LinkedList.h" +#include "nsHtml5DocumentBuilder.h" +#include "nsCharsetSource.h" + +class nsHtml5Parser; +class nsHtml5StreamParser; +class nsIContent; +namespace mozilla { +namespace dom { +class Document; +} +} // namespace mozilla + +class nsHtml5TreeOpExecutor final + : public nsHtml5DocumentBuilder, + public nsIContentSink, + public nsAHtml5TreeOpSink, + public mozilla::LinkedListElement<nsHtml5TreeOpExecutor> { + friend class nsHtml5FlushLoopGuard; + typedef mozilla::dom::ReferrerPolicy ReferrerPolicy; + using Encoding = mozilla::Encoding; + template <typename T> + using NotNull = mozilla::NotNull<T>; + + public: + NS_DECL_ISUPPORTS_INHERITED + + private: +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH + static uint32_t sAppendBatchMaxSize; + static uint32_t sAppendBatchSlotsExamined; + static uint32_t sAppendBatchExaminations; + static uint32_t sLongestTimeOffTheEventLoop; + static uint32_t sTimesFlushLoopInterrupted; +#endif + + /** + * Whether EOF needs to be suppressed + */ + bool mSuppressEOF; + + bool mReadingFromStage; + nsTArray<nsHtml5TreeOperation> mOpQueue; + nsHtml5StreamParser* mStreamParser; + + /** + * URLs already preloaded/preloading. + */ + nsTHashSet<nsCString> mPreloadedURLs; + + nsCOMPtr<nsIURI> mSpeculationBaseURI; + + nsCOMPtr<nsIURI> mViewSourceBaseURI; + + /** + * Whether the parser has started + */ + bool mStarted; + + nsHtml5TreeOpStage mStage; + + bool mRunFlushLoopOnStack; + + bool mCallContinueInterruptedParsingIfEnabled; + + /** + * Whether this executor has already complained about matters related + * to character encoding declarations. + */ + bool mAlreadyComplainedAboutCharset; + + /** + * Whether this executor has already complained about the tree being too + * deep. + */ + bool mAlreadyComplainedAboutDeepTree; + + public: + nsHtml5TreeOpExecutor(); + + protected: + virtual ~nsHtml5TreeOpExecutor(); + + public: + // nsIContentSink + + /** + * Unimplemented. For interface compat only. + */ + NS_IMETHOD WillParse() override; + + NS_IMETHOD WillBuildModel(nsDTDMode /* unused */) override { + return WillBuildModel(); + } + nsresult WillBuildModel(); + + /** + * Emits EOF. + */ + NS_IMETHOD DidBuildModel(bool aTerminated) override; + + /** + * Forwards to nsContentSink + */ + NS_IMETHOD WillInterrupt() override; + + /** + * Unimplemented. For interface compat only. + */ + void WillResume() override; + + virtual nsIContentSink* AsExecutor() override { return this; } + + virtual void InitialTranslationCompleted() override; + + /** + * Sets the parser. + */ + NS_IMETHOD SetParser(nsParserBase* aParser) override; + + /** + * No-op for backwards compat. + */ + virtual void FlushPendingNotifications(mozilla::FlushType aType) override; + + /** + * Don't call. For interface compat only. + */ + virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override { + MOZ_ASSERT_UNREACHABLE("No one should call this."); + } + + /** + * Returns the document. + */ + virtual nsISupports* GetTarget() override; + + virtual void ContinueInterruptedParsingAsync() override; + + bool IsScriptExecuting() override { return IsScriptExecutingImpl(); } + + // Not from interface + + void SetStreamParser(nsHtml5StreamParser* aStreamParser) { + mStreamParser = aStreamParser; + } + + void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, + int32_t aLine); + + bool IsScriptEnabled(); + + virtual nsresult MarkAsBroken(nsresult aReason) override; + + void StartLayout(bool* aInterrupted); + + void PauseDocUpdate(bool* aInterrupted); + + void FlushSpeculativeLoads(); + + void RunFlushLoop(); + + nsresult FlushDocumentWrite(); + + void CommitToInternalEncoding(); + + [[nodiscard]] bool TakeOpsFromStage(); + + void MaybeSuspend(); + + void Start(); + + void SetDocumentCharsetAndSource(NotNull<const Encoding*> aEncoding, + nsCharsetSource aCharsetSource); + + void UpdateCharsetSource(nsCharsetSource aCharsetSource); + + void NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding, int32_t aSource, + uint32_t aLineNumber); + + void MaybeComplainAboutCharset(const char* aMsgId, bool aError, + uint32_t aLineNumber); + + void ComplainAboutBogusProtocolCharset(mozilla::dom::Document* aDoc, + bool aUnrecognized); + + void MaybeComplainAboutDeepTree(uint32_t aLineNumber); + + bool HasStarted() { return mStarted; } + + bool IsFlushing() { return mFlushState >= eInFlush; } + +#ifdef DEBUG + bool IsInFlushLoop() { return mRunFlushLoopOnStack; } +#endif + + void RunScript(nsIContent* aScriptElement); + + /** + * Flush the operations from the tree operations from the argument + * queue unconditionally. (This is for the main thread case.) + */ + [[nodiscard]] virtual bool MoveOpsFrom( + nsTArray<nsHtml5TreeOperation>& aOpQueue) override; + + void ClearOpQueue(); + + void RemoveFromStartOfOpQueue(size_t aNumberOfOpsToRemove); + + inline size_t OpQueueLength() { return mOpQueue.Length(); } + + nsHtml5TreeOpStage* GetStage() { return &mStage; } + + void StartReadingFromStage() { mReadingFromStage = true; } + + void StreamEnded(); + +#ifdef DEBUG + void AssertStageEmpty() { mStage.AssertEmpty(); } +#endif + + nsIURI* GetViewSourceBaseURI(); + + void PreloadScript(const nsAString& aURL, const nsAString& aCharset, + const nsAString& aType, const nsAString& aCrossOrigin, + const nsAString& aMedia, const nsAString& aIntegrity, + ReferrerPolicy aReferrerPolicy, bool aScriptFromHead, + bool aAsync, bool aDefer, bool aNoModule, + bool aLinkPreload); + + void PreloadStyle(const nsAString& aURL, const nsAString& aCharset, + const nsAString& aCrossOrigin, const nsAString& aMedia, + const nsAString& aReferrerPolicy, + const nsAString& aIntegrity, bool aLinkPreload); + + void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin, + const nsAString& aMedia, const nsAString& aSrcset, + const nsAString& aSizes, + const nsAString& aImageReferrerPolicy, bool aLinkPreload, + const mozilla::TimeStamp& aInitTimestamp); + + void PreloadOpenPicture(); + + void PreloadEndPicture(); + + void PreloadPictureSource(const nsAString& aSrcset, const nsAString& aSizes, + const nsAString& aType, const nsAString& aMedia); + + void PreloadFont(const nsAString& aURL, const nsAString& aCrossOrigin, + const nsAString& aMedia, const nsAString& aReferrerPolicy); + + void PreloadFetch(const nsAString& aURL, const nsAString& aCrossOrigin, + const nsAString& aMedia, const nsAString& aReferrerPolicy); + + void SetSpeculationBase(const nsAString& aURL); + + void UpdateReferrerInfoFromMeta(const nsAString& aMetaReferrer); + + void AddSpeculationCSP(const nsAString& aCSP); + + void AddBase(const nsAString& aURL); + + private: + nsHtml5Parser* GetParser(); + + bool IsExternalViewSource(); + + /** + * Get a nsIURI for an nsString if the URL hasn't been preloaded yet. + */ + already_AddRefed<nsIURI> ConvertIfNotPreloadedYet(const nsAString& aURL); + + /** + * The above, plus also checks that the media attribute applies. + */ + already_AddRefed<nsIURI> ConvertIfNotPreloadedYetAndMediaApplies( + const nsAString& aURL, const nsAString& aMedia); + + /** Returns whether the given media attribute applies to mDocument */ + bool MediaApplies(const nsAString& aMedia); + + /** + * The base URI we would use for current preload operations + */ + nsIURI* BaseURIForPreload(); + + /** + * Returns true if we haven't preloaded this URI yet, and adds it to the + * list of preloaded URIs + */ + bool ShouldPreloadURI(nsIURI* aURI); + + ReferrerPolicy GetPreloadReferrerPolicy(const nsAString& aReferrerPolicy); + + ReferrerPolicy GetPreloadReferrerPolicy(ReferrerPolicy aReferrerPolicy); +}; + +#endif // nsHtml5TreeOpExecutor_h diff --git a/parser/html/nsHtml5TreeOpStage.cpp b/parser/html/nsHtml5TreeOpStage.cpp new file mode 100644 index 0000000000..6f7cb5f608 --- /dev/null +++ b/parser/html/nsHtml5TreeOpStage.cpp @@ -0,0 +1,52 @@ +/* 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/. */ + +#include "nsHtml5TreeOpStage.h" + +using namespace mozilla; + +nsHtml5TreeOpStage::nsHtml5TreeOpStage() : mMutex("nsHtml5TreeOpStage mutex") {} + +nsHtml5TreeOpStage::~nsHtml5TreeOpStage() {} + +bool nsHtml5TreeOpStage::MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue) { + mozilla::MutexAutoLock autoLock(mMutex); + return !!mOpQueue.AppendElements(std::move(aOpQueue), mozilla::fallible_t()); +} + +[[nodiscard]] bool nsHtml5TreeOpStage::MoveOpsAndSpeculativeLoadsTo( + nsTArray<nsHtml5TreeOperation>& aOpQueue, + nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue) { + mozilla::MutexAutoLock autoLock(mMutex); + if (!aOpQueue.AppendElements(std::move(mOpQueue), mozilla::fallible_t())) { + return false; + }; + aSpeculativeLoadQueue.AppendElements(std::move(mSpeculativeLoadQueue)); + return true; +} + +[[nodiscard]] bool nsHtml5TreeOpStage::MoveOpsTo( + nsTArray<nsHtml5TreeOperation>& aOpQueue) { + mozilla::MutexAutoLock autoLock(mMutex); + return !!aOpQueue.AppendElements(std::move(mOpQueue), mozilla::fallible_t()); +} + +void nsHtml5TreeOpStage::MoveSpeculativeLoadsFrom( + nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue) { + mozilla::MutexAutoLock autoLock(mMutex); + mSpeculativeLoadQueue.AppendElements(std::move(aSpeculativeLoadQueue)); +} + +void nsHtml5TreeOpStage::MoveSpeculativeLoadsTo( + nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue) { + mozilla::MutexAutoLock autoLock(mMutex); + aSpeculativeLoadQueue.AppendElements(std::move(mSpeculativeLoadQueue)); +} + +#ifdef DEBUG +void nsHtml5TreeOpStage::AssertEmpty() { + mozilla::MutexAutoLock autoLock(mMutex); + MOZ_ASSERT(mOpQueue.IsEmpty(), "The stage was supposed to be empty."); +} +#endif diff --git a/parser/html/nsHtml5TreeOpStage.h b/parser/html/nsHtml5TreeOpStage.h new file mode 100644 index 0000000000..967ccfd008 --- /dev/null +++ b/parser/html/nsHtml5TreeOpStage.h @@ -0,0 +1,61 @@ +/* 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/. */ + +#ifndef nsHtml5TreeOpStage_h +#define nsHtml5TreeOpStage_h + +#include "mozilla/Mutex.h" +#include "nsHtml5TreeOperation.h" +#include "nsTArray.h" +#include "nsAHtml5TreeOpSink.h" +#include "nsHtml5SpeculativeLoad.h" + +class nsHtml5TreeOpStage : public nsAHtml5TreeOpSink { + public: + nsHtml5TreeOpStage(); + + virtual ~nsHtml5TreeOpStage(); + + /** + * Flush the operations from the tree operations from the argument + * queue unconditionally. + */ + [[nodiscard]] virtual bool MoveOpsFrom( + nsTArray<nsHtml5TreeOperation>& aOpQueue) override; + + /** + * Retrieve the staged operations into the argument. + */ + [[nodiscard]] bool MoveOpsTo(nsTArray<nsHtml5TreeOperation>& aOpQueue); + + /** + * Retrieve the staged operations and speculative loads into the arguments. + */ + [[nodiscard]] bool MoveOpsAndSpeculativeLoadsTo( + nsTArray<nsHtml5TreeOperation>& aOpQueue, + nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue); + + /** + * Move the speculative loads from the argument into the staging queue. + */ + void MoveSpeculativeLoadsFrom( + nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue); + + /** + * Retrieve the staged speculative loads into the argument. + */ + void MoveSpeculativeLoadsTo( + nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue); + +#ifdef DEBUG + void AssertEmpty(); +#endif + + private: + nsTArray<nsHtml5TreeOperation> mOpQueue; + nsTArray<nsHtml5SpeculativeLoad> mSpeculativeLoadQueue; + mozilla::Mutex mMutex MOZ_UNANNOTATED; +}; + +#endif /* nsHtml5TreeOpStage_h */ diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp new file mode 100644 index 0000000000..a6e0298420 --- /dev/null +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -0,0 +1,1208 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#include "nsHtml5TreeOperation.h" +#include "mozAutoDocUpdate.h" +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/Likely.h" +#include "mozilla/dom/Comment.h" +#include "mozilla/dom/CustomElementRegistry.h" +#include "mozilla/dom/DocGroup.h" +#include "mozilla/dom/DocumentType.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/LinkStyle.h" +#include "mozilla/dom/HTMLFormElement.h" +#include "mozilla/dom/HTMLImageElement.h" +#include "mozilla/dom/HTMLTemplateElement.h" +#include "mozilla/dom/MutationObservers.h" +#include "mozilla/dom/Text.h" +#include "nsAttrName.h" +#include "nsContentCreatorFunctions.h" +#include "nsContentUtils.h" +#include "nsDocElementCreatedNotificationRunner.h" +#include "nsEscape.h" +#include "nsHtml5AutoPauseUpdate.h" +#include "nsHtml5DocumentMode.h" +#include "nsHtml5HtmlAttributes.h" +#include "nsHtml5SVGLoadDispatcher.h" +#include "nsHtml5TreeBuilder.h" +#include "nsIDTD.h" +#include "nsIFormControl.h" +#include "nsIMutationObserver.h" +#include "nsINode.h" +#include "nsIProtocolHandler.h" +#include "nsIScriptElement.h" +#include "nsISupportsImpl.h" +#include "nsIURI.h" +#include "nsNetUtil.h" +#include "nsTextNode.h" + +using namespace mozilla; +using namespace mozilla::dom; +using mozilla::dom::Document; + +/** + * Helper class that opens a notification batch if the current doc + * is different from the executor doc. + */ +class MOZ_STACK_CLASS nsHtml5OtherDocUpdate { + public: + nsHtml5OtherDocUpdate(Document* aCurrentDoc, Document* aExecutorDoc) { + MOZ_ASSERT(aCurrentDoc, "Node has no doc?"); + MOZ_ASSERT(aExecutorDoc, "Executor has no doc?"); + if (MOZ_LIKELY(aCurrentDoc == aExecutorDoc)) { + mDocument = nullptr; + } else { + mDocument = aCurrentDoc; + aCurrentDoc->BeginUpdate(); + } + } + + ~nsHtml5OtherDocUpdate() { + if (MOZ_UNLIKELY(mDocument)) { + mDocument->EndUpdate(); + } + } + + private: + RefPtr<Document> mDocument; +}; + +nsHtml5TreeOperation::nsHtml5TreeOperation() : mOperation(uninitialized()) { + MOZ_COUNT_CTOR(nsHtml5TreeOperation); +} + +nsHtml5TreeOperation::~nsHtml5TreeOperation() { + MOZ_COUNT_DTOR(nsHtml5TreeOperation); + + struct TreeOperationMatcher { + void operator()(const opAppend& aOperation) {} + + void operator()(const opDetach& aOperation) {} + + void operator()(const opAppendChildrenToNewParent& aOperation) {} + + void operator()(const opFosterParent& aOperation) {} + + void operator()(const opAppendToDocument& aOperation) {} + + void operator()(const opAddAttributes& aOperation) { + delete aOperation.mAttributes; + } + + void operator()(const nsHtml5DocumentMode& aMode) {} + + void operator()(const opCreateHTMLElement& aOperation) { + aOperation.mName->Release(); + delete aOperation.mAttributes; + } + + void operator()(const opCreateSVGElement& aOperation) { + aOperation.mName->Release(); + delete aOperation.mAttributes; + } + + void operator()(const opCreateMathMLElement& aOperation) { + aOperation.mName->Release(); + delete aOperation.mAttributes; + } + + void operator()(const opSetFormElement& aOperation) {} + + void operator()(const opAppendText& aOperation) { + delete[] aOperation.mBuffer; + } + + void operator()(const opFosterParentText& aOperation) { + delete[] aOperation.mBuffer; + } + + void operator()(const opAppendComment& aOperation) { + delete[] aOperation.mBuffer; + } + + void operator()(const opAppendCommentToDocument& aOperation) { + delete[] aOperation.mBuffer; + } + + void operator()(const opAppendDoctypeToDocument& aOperation) { + aOperation.mName->Release(); + delete aOperation.mStringPair; + } + + void operator()(const opGetDocumentFragmentForTemplate& aOperation) {} + + void operator()(const opGetFosterParent& aOperation) {} + + void operator()(const opMarkAsBroken& aOperation) {} + + void operator()(const opRunScript& aOperation) {} + + void operator()(const opRunScriptAsyncDefer& aOperation) {} + + void operator()(const opPreventScriptExecution& aOperation) {} + + void operator()(const opDoneAddingChildren& aOperation) {} + + void operator()(const opDoneCreatingElement& aOperation) {} + + void operator()(const opUpdateCharsetSource& aOperation) {} + + void operator()(const opCharsetSwitchTo& aOperation) {} + + void operator()(const opUpdateStyleSheet& aOperation) {} + + void operator()(const opProcessOfflineManifest& aOperation) { + free(aOperation.mUrl); + } + + void operator()(const opMarkMalformedIfScript& aOperation) {} + + void operator()(const opStreamEnded& aOperation) {} + + void operator()(const opSetStyleLineNumber& aOperation) {} + + void operator()(const opSetScriptLineAndColumnNumberAndFreeze& aOperation) { + } + + void operator()(const opSvgLoad& aOperation) {} + + void operator()(const opMaybeComplainAboutCharset& aOperation) {} + + void operator()(const opMaybeComplainAboutDeepTree& aOperation) {} + + void operator()(const opAddClass& aOperation) {} + + void operator()(const opAddViewSourceHref& aOperation) { + delete[] aOperation.mBuffer; + } + + void operator()(const opAddViewSourceBase& aOperation) { + delete[] aOperation.mBuffer; + } + + void operator()(const opAddErrorType& aOperation) { + if (aOperation.mName) { + aOperation.mName->Release(); + } + if (aOperation.mOther) { + aOperation.mOther->Release(); + } + } + + void operator()(const opAddLineNumberId& aOperation) {} + + void operator()(const opStartLayout& aOperation) {} + + void operator()(const opEnableEncodingMenu& aOperation) {} + + void operator()(const uninitialized& aOperation) { + NS_WARNING("Uninitialized tree op."); + } + }; + + mOperation.match(TreeOperationMatcher()); +} + +nsresult nsHtml5TreeOperation::AppendTextToTextNode( + const char16_t* aBuffer, uint32_t aLength, dom::Text* aTextNode, + nsHtml5DocumentBuilder* aBuilder) { + MOZ_ASSERT(aTextNode, "Got null text node."); + MOZ_ASSERT(aBuilder); + MOZ_ASSERT(aBuilder->IsInDocUpdate()); + uint32_t oldLength = aTextNode->TextLength(); + CharacterDataChangeInfo info = {true, oldLength, oldLength, aLength}; + MutationObservers::NotifyCharacterDataWillChange(aTextNode, info); + + nsresult rv = aTextNode->AppendText(aBuffer, aLength, false); + NS_ENSURE_SUCCESS(rv, rv); + + MutationObservers::NotifyCharacterDataChanged(aTextNode, info); + return rv; +} + +nsresult nsHtml5TreeOperation::AppendText(const char16_t* aBuffer, + uint32_t aLength, nsIContent* aParent, + nsHtml5DocumentBuilder* aBuilder) { + nsresult rv = NS_OK; + nsIContent* lastChild = aParent->GetLastChild(); + if (lastChild && lastChild->IsText()) { + nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument()); + return AppendTextToTextNode(aBuffer, aLength, lastChild->GetAsText(), + aBuilder); + } + + nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager(); + RefPtr<nsTextNode> text = new (nodeInfoManager) nsTextNode(nodeInfoManager); + NS_ASSERTION(text, "Infallible malloc failed?"); + rv = text->SetText(aBuffer, aLength, false); + NS_ENSURE_SUCCESS(rv, rv); + + return Append(text, aParent, aBuilder); +} + +nsresult nsHtml5TreeOperation::Append(nsIContent* aNode, nsIContent* aParent, + nsHtml5DocumentBuilder* aBuilder) { + MOZ_ASSERT(aBuilder); + MOZ_ASSERT(aBuilder->IsInDocUpdate()); + ErrorResult rv; + nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument()); + aParent->AppendChildTo(aNode, false, rv); + if (!rv.Failed()) { + aNode->SetParserHasNotified(); + MutationObservers::NotifyContentAppended(aParent, aNode); + } + return rv.StealNSResult(); +} + +nsresult nsHtml5TreeOperation::Append(nsIContent* aNode, nsIContent* aParent, + mozilla::dom::FromParser aFromParser, + nsHtml5DocumentBuilder* aBuilder) { + Maybe<nsHtml5AutoPauseUpdate> autoPause; + Maybe<dom::AutoCEReaction> autoCEReaction; + dom::DocGroup* docGroup = aParent->OwnerDoc()->GetDocGroup(); + if (docGroup && aFromParser != mozilla::dom::FROM_PARSER_FRAGMENT) { + autoCEReaction.emplace(docGroup->CustomElementReactionsStack(), nullptr); + } + nsresult rv = Append(aNode, aParent, aBuilder); + // Pause the parser only when there are reactions to be invoked to avoid + // pausing parsing too aggressive. + if (autoCEReaction.isSome() && docGroup && + docGroup->CustomElementReactionsStack() + ->IsElementQueuePushedForCurrentRecursionDepth()) { + autoPause.emplace(aBuilder); + } + return rv; +} + +nsresult nsHtml5TreeOperation::AppendToDocument( + nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder) { + MOZ_ASSERT(aBuilder); + MOZ_ASSERT(aBuilder->GetDocument() == aNode->OwnerDoc()); + MOZ_ASSERT(aBuilder->IsInDocUpdate()); + + ErrorResult rv; + Document* doc = aBuilder->GetDocument(); + doc->AppendChildTo(aNode, false, rv); + if (rv.ErrorCodeIs(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR)) { + aNode->SetParserHasNotified(); + return NS_OK; + } + if (rv.Failed()) { + return rv.StealNSResult(); + } + + aNode->SetParserHasNotified(); + MutationObservers::NotifyContentInserted(doc, aNode); + + NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), + "Someone forgot to block scripts"); + if (aNode->IsElement()) { + nsContentUtils::AddScriptRunner( + new nsDocElementCreatedNotificationRunner(doc)); + } + return NS_OK; +} + +static bool IsElementOrTemplateContent(nsINode* aNode) { + if (aNode) { + if (aNode->IsElement()) { + return true; + } + if (aNode->IsDocumentFragment()) { + // Check if the node is a template content. + nsIContent* fragHost = aNode->AsDocumentFragment()->GetHost(); + if (fragHost && fragHost->IsTemplateElement()) { + return true; + } + } + } + return false; +} + +void nsHtml5TreeOperation::Detach(nsIContent* aNode, + nsHtml5DocumentBuilder* aBuilder) { + MOZ_ASSERT(aBuilder); + MOZ_ASSERT(aBuilder->IsInDocUpdate()); + nsCOMPtr<nsINode> parent = aNode->GetParentNode(); + if (parent) { + nsHtml5OtherDocUpdate update(parent->OwnerDoc(), aBuilder->GetDocument()); + parent->RemoveChildNode(aNode, true); + } +} + +nsresult nsHtml5TreeOperation::AppendChildrenToNewParent( + nsIContent* aNode, nsIContent* aParent, nsHtml5DocumentBuilder* aBuilder) { + MOZ_ASSERT(aBuilder); + MOZ_ASSERT(aBuilder->IsInDocUpdate()); + nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument()); + + bool didAppend = false; + while (aNode->HasChildren()) { + nsCOMPtr<nsIContent> child = aNode->GetFirstChild(); + aNode->RemoveChildNode(child, true); + + ErrorResult rv; + aParent->AppendChildTo(child, false, rv); + if (rv.Failed()) { + return rv.StealNSResult(); + } + didAppend = true; + } + if (didAppend) { + MutationObservers::NotifyContentAppended(aParent, aParent->GetLastChild()); + } + return NS_OK; +} + +nsresult nsHtml5TreeOperation::FosterParent(nsIContent* aNode, + nsIContent* aParent, + nsIContent* aTable, + nsHtml5DocumentBuilder* aBuilder) { + MOZ_ASSERT(aBuilder); + MOZ_ASSERT(aBuilder->IsInDocUpdate()); + nsIContent* foster = aTable->GetParent(); + + if (IsElementOrTemplateContent(foster)) { + nsHtml5OtherDocUpdate update(foster->OwnerDoc(), aBuilder->GetDocument()); + + ErrorResult rv; + foster->InsertChildBefore(aNode, aTable, false, rv); + if (rv.Failed()) { + return rv.StealNSResult(); + } + + MutationObservers::NotifyContentInserted(foster, aNode); + return NS_OK; + } + + return Append(aNode, aParent, aBuilder); +} + +nsresult nsHtml5TreeOperation::AddAttributes(nsIContent* aNode, + nsHtml5HtmlAttributes* aAttributes, + nsHtml5DocumentBuilder* aBuilder) { + dom::Element* node = aNode->AsElement(); + nsHtml5OtherDocUpdate update(node->OwnerDoc(), aBuilder->GetDocument()); + + int32_t len = aAttributes->getLength(); + for (int32_t i = len; i > 0;) { + --i; + nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i); + int32_t nsuri = aAttributes->getURINoBoundsCheck(i); + if (!node->HasAttr(nsuri, localName)) { + nsString value; // Not Auto, because using it to hold nsStringBuffer* + aAttributes->getValueNoBoundsCheck(i).ToString(value); + node->SetAttr(nsuri, localName, aAttributes->getPrefixNoBoundsCheck(i), + value, true); + // XXX what to do with nsresult? + } + } + return NS_OK; +} + +void nsHtml5TreeOperation::SetHTMLElementAttributes( + dom::Element* aElement, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes) { + int32_t len = aAttributes->getLength(); + for (int32_t i = 0; i < len; i++) { + nsHtml5String val = aAttributes->getValueNoBoundsCheck(i); + nsAtom* klass = val.MaybeAsAtom(); + if (klass) { + aElement->SetSingleClassFromParser(klass); + } else { + nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i); + nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i); + int32_t nsuri = aAttributes->getURINoBoundsCheck(i); + + nsString value; // Not Auto, because using it to hold nsStringBuffer* + val.ToString(value); + if (nsGkAtoms::a == aName && nsGkAtoms::name == localName) { + // This is an HTML5-incompliant Geckoism. + // Remove when fixing bug 582361 + NS_ConvertUTF16toUTF8 cname(value); + NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting())); + aElement->SetAttr(nsuri, localName, prefix, uv, false); + } else { + aElement->SetAttr(nsuri, localName, prefix, value, false); + } + } + } +} + +nsIContent* nsHtml5TreeOperation::CreateHTMLElement( + nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager, + nsHtml5DocumentBuilder* aBuilder, + mozilla::dom::HTMLContentCreatorFunction aCreator) { + RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_XHTML, nsINode::ELEMENT_NODE); + NS_ASSERTION(nodeInfo, "Got null nodeinfo."); + + dom::Element* newContent = nullptr; + Document* document = nodeInfo->GetDocument(); + bool willExecuteScript = false; + bool isCustomElement = false; + RefPtr<nsAtom> isAtom; + dom::CustomElementDefinition* definition = nullptr; + + if (aAttributes) { + nsHtml5String is = aAttributes->getValue(nsHtml5AttributeName::ATTR_IS); + if (is) { + nsAutoString isValue; + is.ToString(isValue); + isAtom = NS_Atomize(isValue); + } + } + + isCustomElement = (aCreator == NS_NewCustomElement || isAtom); + if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) { + RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom(); + RefPtr<nsAtom> typeAtom = + (aCreator == NS_NewCustomElement) ? tagAtom : isAtom; + + MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())); + definition = nsContentUtils::LookupCustomElementDefinition( + document, nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom); + + if (definition) { + willExecuteScript = true; + } + } + + if (willExecuteScript) { // This will cause custom element constructors to + // run + mozilla::dom::AutoSetThrowOnDynamicMarkupInsertionCounter + throwOnDynamicMarkupInsertionCounter(document); + nsHtml5AutoPauseUpdate autoPauseContentUpdate(aBuilder); + { nsAutoMicroTask mt; } + dom::AutoCEReaction autoCEReaction( + document->GetDocGroup()->CustomElementReactionsStack(), nullptr); + + nsCOMPtr<dom::Element> newElement; + NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(), + aFromParser, isAtom, definition); + + MOZ_ASSERT(newElement, "Element creation created null pointer."); + newContent = newElement; + aBuilder->HoldElement(newElement.forget()); + + if (MOZ_UNLIKELY(aName == nsGkAtoms::style || aName == nsGkAtoms::link)) { + if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) { + linkStyle->SetEnableUpdates(false); + } + } + + if (!aAttributes) { + return newContent; + } + + SetHTMLElementAttributes(newContent, aName, aAttributes); + } else { + nsCOMPtr<dom::Element> newElement; + + if (isCustomElement) { + NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(), + aFromParser, isAtom, definition); + } else { + newElement = aCreator(nodeInfo.forget(), aFromParser); + } + + MOZ_ASSERT(newElement, "Element creation created null pointer."); + + newContent = newElement; + aBuilder->HoldElement(newElement.forget()); + + if (MOZ_UNLIKELY(aName == nsGkAtoms::style || aName == nsGkAtoms::link)) { + if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) { + linkStyle->SetEnableUpdates(false); + } + } + + if (!aAttributes) { + return newContent; + } + + SetHTMLElementAttributes(newContent, aName, aAttributes); + } + + return newContent; +} + +nsIContent* nsHtml5TreeOperation::CreateSVGElement( + nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager, + nsHtml5DocumentBuilder* aBuilder, + mozilla::dom::SVGContentCreatorFunction aCreator) { + nsCOMPtr<nsIContent> newElement; + if (MOZ_LIKELY(aNodeInfoManager->SVGEnabled())) { + RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_SVG, nsINode::ELEMENT_NODE); + MOZ_ASSERT(nodeInfo, "Got null nodeinfo."); + + mozilla::DebugOnly<nsresult> rv = + aCreator(getter_AddRefs(newElement), nodeInfo.forget(), aFromParser); + MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement); + } else { + RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_disabled_SVG, nsINode::ELEMENT_NODE); + MOZ_ASSERT(nodeInfo, "Got null nodeinfo."); + + // The mismatch between NS_NewXMLElement and SVGContentCreatorFunction + // argument types is annoying. + nsCOMPtr<dom::Element> xmlElement; + mozilla::DebugOnly<nsresult> rv = + NS_NewXMLElement(getter_AddRefs(xmlElement), nodeInfo.forget()); + MOZ_ASSERT(NS_SUCCEEDED(rv) && xmlElement); + newElement = xmlElement; + } + + dom::Element* newContent = newElement->AsElement(); + aBuilder->HoldElement(newElement.forget()); + + if (MOZ_UNLIKELY(aName == nsGkAtoms::style)) { + if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) { + linkStyle->SetEnableUpdates(false); + } + } + + if (!aAttributes) { + return newContent; + } + + int32_t len = aAttributes->getLength(); + for (int32_t i = 0; i < len; i++) { + nsHtml5String val = aAttributes->getValueNoBoundsCheck(i); + nsAtom* klass = val.MaybeAsAtom(); + if (klass) { + newContent->SetSingleClassFromParser(klass); + } else { + nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i); + nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i); + int32_t nsuri = aAttributes->getURINoBoundsCheck(i); + + nsString value; // Not Auto, because using it to hold nsStringBuffer* + val.ToString(value); + newContent->SetAttr(nsuri, localName, prefix, value, false); + } + } + return newContent; +} + +nsIContent* nsHtml5TreeOperation::CreateMathMLElement( + nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + nsNodeInfoManager* aNodeInfoManager, nsHtml5DocumentBuilder* aBuilder) { + nsCOMPtr<dom::Element> newElement; + if (MOZ_LIKELY(aNodeInfoManager->MathMLEnabled())) { + RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_MathML, nsINode::ELEMENT_NODE); + NS_ASSERTION(nodeInfo, "Got null nodeinfo."); + + mozilla::DebugOnly<nsresult> rv = + NS_NewMathMLElement(getter_AddRefs(newElement), nodeInfo.forget()); + MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement); + } else { + RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_disabled_MathML, nsINode::ELEMENT_NODE); + NS_ASSERTION(nodeInfo, "Got null nodeinfo."); + + mozilla::DebugOnly<nsresult> rv = + NS_NewXMLElement(getter_AddRefs(newElement), nodeInfo.forget()); + MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement); + } + + dom::Element* newContent = newElement; + aBuilder->HoldElement(newElement.forget()); + + if (!aAttributes) { + return newContent; + } + + int32_t len = aAttributes->getLength(); + for (int32_t i = 0; i < len; i++) { + nsHtml5String val = aAttributes->getValueNoBoundsCheck(i); + nsAtom* klass = val.MaybeAsAtom(); + if (klass) { + newContent->SetSingleClassFromParser(klass); + } else { + nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i); + nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i); + int32_t nsuri = aAttributes->getURINoBoundsCheck(i); + + nsString value; // Not Auto, because using it to hold nsStringBuffer* + val.ToString(value); + newContent->SetAttr(nsuri, localName, prefix, value, false); + } + } + return newContent; +} + +void nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, + nsIContent* aParent) { + RefPtr<dom::HTMLFormElement> formElement = + dom::HTMLFormElement::FromNodeOrNull(aParent); + NS_ASSERTION(formElement, + "The form element doesn't implement HTMLFormElement."); + nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode)); + if (formControl && + formControl->ControlType() != + FormControlType::FormAssociatedCustomElement && + !aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) { + formControl->SetForm(formElement); + } else if (HTMLImageElement* domImageElement = + dom::HTMLImageElement::FromNodeOrNull(aNode)) { + domImageElement->SetForm(formElement); + } +} + +nsresult nsHtml5TreeOperation::FosterParentText( + nsIContent* aStackParent, char16_t* aBuffer, uint32_t aLength, + nsIContent* aTable, nsHtml5DocumentBuilder* aBuilder) { + MOZ_ASSERT(aBuilder); + MOZ_ASSERT(aBuilder->IsInDocUpdate()); + nsresult rv = NS_OK; + nsIContent* foster = aTable->GetParent(); + + if (IsElementOrTemplateContent(foster)) { + nsHtml5OtherDocUpdate update(foster->OwnerDoc(), aBuilder->GetDocument()); + + nsIContent* previousSibling = aTable->GetPreviousSibling(); + if (previousSibling && previousSibling->IsText()) { + return AppendTextToTextNode(aBuffer, aLength, + previousSibling->GetAsText(), aBuilder); + } + + nsNodeInfoManager* nodeInfoManager = + aStackParent->OwnerDoc()->NodeInfoManager(); + RefPtr<nsTextNode> text = new (nodeInfoManager) nsTextNode(nodeInfoManager); + NS_ASSERTION(text, "Infallible malloc failed?"); + rv = text->SetText(aBuffer, aLength, false); + NS_ENSURE_SUCCESS(rv, rv); + + ErrorResult error; + foster->InsertChildBefore(text, aTable, false, error); + if (error.Failed()) { + return error.StealNSResult(); + } + + MutationObservers::NotifyContentInserted(foster, text); + return rv; + } + + return AppendText(aBuffer, aLength, aStackParent, aBuilder); +} + +nsresult nsHtml5TreeOperation::AppendComment(nsIContent* aParent, + char16_t* aBuffer, int32_t aLength, + nsHtml5DocumentBuilder* aBuilder) { + nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager(); + RefPtr<dom::Comment> comment = + new (nodeInfoManager) dom::Comment(nodeInfoManager); + NS_ASSERTION(comment, "Infallible malloc failed?"); + nsresult rv = comment->SetText(aBuffer, aLength, false); + NS_ENSURE_SUCCESS(rv, rv); + + return Append(comment, aParent, aBuilder); +} + +nsresult nsHtml5TreeOperation::AppendCommentToDocument( + char16_t* aBuffer, int32_t aLength, nsHtml5DocumentBuilder* aBuilder) { + RefPtr<dom::Comment> comment = new (aBuilder->GetNodeInfoManager()) + dom::Comment(aBuilder->GetNodeInfoManager()); + NS_ASSERTION(comment, "Infallible malloc failed?"); + nsresult rv = comment->SetText(aBuffer, aLength, false); + NS_ENSURE_SUCCESS(rv, rv); + + return AppendToDocument(comment, aBuilder); +} + +nsresult nsHtml5TreeOperation::AppendDoctypeToDocument( + nsAtom* aName, const nsAString& aPublicId, const nsAString& aSystemId, + nsHtml5DocumentBuilder* aBuilder) { + // Adapted from nsXMLContentSink + // Create a new doctype node + RefPtr<dom::DocumentType> docType = + NS_NewDOMDocumentType(aBuilder->GetNodeInfoManager(), aName, aPublicId, + aSystemId, VoidString()); + return AppendToDocument(docType, aBuilder); +} + +nsIContent* nsHtml5TreeOperation::GetDocumentFragmentForTemplate( + nsIContent* aNode) { + dom::HTMLTemplateElement* tempElem = + static_cast<dom::HTMLTemplateElement*>(aNode); + RefPtr<dom::DocumentFragment> frag = tempElem->Content(); + return frag; +} + +nsIContent* nsHtml5TreeOperation::GetFosterParent(nsIContent* aTable, + nsIContent* aStackParent) { + nsIContent* tableParent = aTable->GetParent(); + return IsElementOrTemplateContent(tableParent) ? tableParent : aStackParent; +} + +void nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode) { + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode); + if (sele) { + sele->PreventExecution(); + } else { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to script, but SVG wasn't disabled."); + } +} + +void nsHtml5TreeOperation::DoneAddingChildren(nsIContent* aNode) { + aNode->DoneAddingChildren(aNode->HasParserNotified()); +} + +void nsHtml5TreeOperation::DoneCreatingElement(nsIContent* aNode) { + aNode->DoneCreatingElement(); +} + +void nsHtml5TreeOperation::SvgLoad(nsIContent* aNode) { + nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(aNode); + if (NS_FAILED( + aNode->OwnerDoc()->Dispatch(TaskCategory::Network, event.forget()))) { + NS_WARNING("failed to dispatch svg load dispatcher"); + } +} + +void nsHtml5TreeOperation::MarkMalformedIfScript(nsIContent* aNode) { + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode); + if (sele) { + // Make sure to serialize this script correctly, for nice round tripping. + sele->SetIsMalformed(); + } +} + +nsresult nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, + nsIContent** aScriptElement, + bool* aInterrupted, bool* aStreamEnded) { + struct TreeOperationMatcher { + TreeOperationMatcher(nsHtml5TreeOpExecutor* aBuilder, + nsIContent** aScriptElement, bool* aInterrupted, + bool* aStreamEnded) + : mBuilder(aBuilder), + mScriptElement(aScriptElement), + mInterrupted(aInterrupted), + mStreamEnded(aStreamEnded) {} + + nsHtml5TreeOpExecutor* mBuilder; + nsIContent** mScriptElement; + bool* mInterrupted; + bool* mStreamEnded; + + nsresult operator()(const opAppend& aOperation) { + return Append(*(aOperation.mChild), *(aOperation.mParent), + aOperation.mFromNetwork, mBuilder); + } + + nsresult operator()(const opDetach& aOperation) { + Detach(*(aOperation.mElement), mBuilder); + return NS_OK; + } + + nsresult operator()(const opAppendChildrenToNewParent& aOperation) { + nsCOMPtr<nsIContent> node = *(aOperation.mOldParent); + nsIContent* parent = *(aOperation.mNewParent); + return AppendChildrenToNewParent(node, parent, mBuilder); + } + + nsresult operator()(const opFosterParent& aOperation) { + nsIContent* node = *(aOperation.mChild); + nsIContent* parent = *(aOperation.mStackParent); + nsIContent* table = *(aOperation.mTable); + return FosterParent(node, parent, table, mBuilder); + } + + nsresult operator()(const opAppendToDocument& aOperation) { + nsresult rv = AppendToDocument(*(aOperation.mContent), mBuilder); + mBuilder->PauseDocUpdate(mInterrupted); + return rv; + } + + nsresult operator()(const opAddAttributes& aOperation) { + nsIContent* node = *(aOperation.mElement); + nsHtml5HtmlAttributes* attributes = aOperation.mAttributes; + return AddAttributes(node, attributes, mBuilder); + } + + nsresult operator()(const nsHtml5DocumentMode& aMode) { + mBuilder->SetDocumentMode(aMode); + return NS_OK; + } + + nsresult operator()(const opCreateHTMLElement& aOperation) { + nsIContent** target = aOperation.mContent; + mozilla::dom::HTMLContentCreatorFunction creator = aOperation.mCreator; + nsAtom* name = aOperation.mName; + nsHtml5HtmlAttributes* attributes = aOperation.mAttributes; + nsIContent* intendedParent = + aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr; + + // intendedParent == nullptr is a special case where the + // intended parent is the document. + nsNodeInfoManager* nodeInfoManager = + intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager() + : mBuilder->GetNodeInfoManager(); + + *target = CreateHTMLElement(name, attributes, aOperation.mFromNetwork, + nodeInfoManager, mBuilder, creator); + return NS_OK; + } + + nsresult operator()(const opCreateSVGElement& aOperation) { + nsIContent** target = aOperation.mContent; + mozilla::dom::SVGContentCreatorFunction creator = aOperation.mCreator; + nsAtom* name = aOperation.mName; + nsHtml5HtmlAttributes* attributes = aOperation.mAttributes; + nsIContent* intendedParent = + aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr; + + // intendedParent == nullptr is a special case where the + // intended parent is the document. + nsNodeInfoManager* nodeInfoManager = + intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager() + : mBuilder->GetNodeInfoManager(); + + *target = CreateSVGElement(name, attributes, aOperation.mFromNetwork, + nodeInfoManager, mBuilder, creator); + return NS_OK; + } + + nsresult operator()(const opCreateMathMLElement& aOperation) { + nsIContent** target = aOperation.mContent; + nsAtom* name = aOperation.mName; + nsHtml5HtmlAttributes* attributes = aOperation.mAttributes; + nsIContent* intendedParent = + aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr; + + // intendedParent == nullptr is a special case where the + // intended parent is the document. + nsNodeInfoManager* nodeInfoManager = + intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager() + : mBuilder->GetNodeInfoManager(); + + *target = + CreateMathMLElement(name, attributes, nodeInfoManager, mBuilder); + return NS_OK; + } + + nsresult operator()(const opSetFormElement& aOperation) { + SetFormElement(*(aOperation.mContent), *(aOperation.mFormElement)); + return NS_OK; + } + + nsresult operator()(const opAppendText& aOperation) { + nsIContent* parent = *aOperation.mParent; + char16_t* buffer = aOperation.mBuffer; + uint32_t length = aOperation.mLength; + return AppendText(buffer, length, parent, mBuilder); + } + + nsresult operator()(const opFosterParentText& aOperation) { + nsIContent* stackParent = *aOperation.mStackParent; + char16_t* buffer = aOperation.mBuffer; + uint32_t length = aOperation.mLength; + nsIContent* table = *aOperation.mTable; + return FosterParentText(stackParent, buffer, length, table, mBuilder); + } + + nsresult operator()(const opAppendComment& aOperation) { + nsIContent* parent = *aOperation.mParent; + char16_t* buffer = aOperation.mBuffer; + uint32_t length = aOperation.mLength; + return AppendComment(parent, buffer, length, mBuilder); + } + + nsresult operator()(const opAppendCommentToDocument& aOperation) { + char16_t* buffer = aOperation.mBuffer; + int32_t length = aOperation.mLength; + return AppendCommentToDocument(buffer, length, mBuilder); + } + + nsresult operator()(const opAppendDoctypeToDocument& aOperation) { + nsAtom* name = aOperation.mName; + nsHtml5TreeOperationStringPair* pair = aOperation.mStringPair; + nsString publicId; + nsString systemId; + pair->Get(publicId, systemId); + return AppendDoctypeToDocument(name, publicId, systemId, mBuilder); + } + + nsresult operator()(const opGetDocumentFragmentForTemplate& aOperation) { + nsIContent* node = *(aOperation.mTemplate); + *(aOperation.mFragHandle) = GetDocumentFragmentForTemplate(node); + return NS_OK; + } + + nsresult operator()(const opGetFosterParent& aOperation) { + nsIContent* table = *(aOperation.mTable); + nsIContent* stackParent = *(aOperation.mStackParent); + nsIContent* fosterParent = GetFosterParent(table, stackParent); + *aOperation.mParentHandle = fosterParent; + return NS_OK; + } + + nsresult operator()(const opMarkAsBroken& aOperation) { + return aOperation.mResult; + } + + nsresult operator()(const opRunScript& aOperation) { + nsIContent* node = *(aOperation.mElement); + nsAHtml5TreeBuilderState* snapshot = aOperation.mBuilderState; + if (snapshot) { + mBuilder->InitializeDocWriteParserState(snapshot, + aOperation.mLineNumber); + } + *mScriptElement = node; + return NS_OK; + } + + nsresult operator()(const opRunScriptAsyncDefer& aOperation) { + mBuilder->RunScript(*(aOperation.mElement)); + return NS_OK; + } + + nsresult operator()(const opPreventScriptExecution& aOperation) { + PreventScriptExecution(*(aOperation.mElement)); + return NS_OK; + } + + nsresult operator()(const opDoneAddingChildren& aOperation) { + nsIContent* node = *(aOperation.mElement); + node->DoneAddingChildren(node->HasParserNotified()); + return NS_OK; + } + + nsresult operator()(const opDoneCreatingElement& aOperation) { + DoneCreatingElement(*(aOperation.mElement)); + return NS_OK; + } + + nsresult operator()(const opUpdateCharsetSource& aOperation) { + mBuilder->UpdateCharsetSource(aOperation.mCharsetSource); + return NS_OK; + } + + nsresult operator()(const opCharsetSwitchTo& aOperation) { + auto encoding = WrapNotNull(aOperation.mEncoding); + mBuilder->NeedsCharsetSwitchTo(encoding, aOperation.mCharsetSource, + (uint32_t)aOperation.mLineNumber); + return NS_OK; + } + + nsresult operator()(const opUpdateStyleSheet& aOperation) { + mBuilder->UpdateStyleSheet(*(aOperation.mElement)); + return NS_OK; + } + + nsresult operator()(const opProcessOfflineManifest& aOperation) { + // TODO: remove this + return NS_OK; + } + + nsresult operator()(const opMarkMalformedIfScript& aOperation) { + MarkMalformedIfScript(*(aOperation.mElement)); + return NS_OK; + } + + nsresult operator()(const opStreamEnded& aOperation) { + *mStreamEnded = true; + return NS_OK; + } + + nsresult operator()(const opSetStyleLineNumber& aOperation) { + nsIContent* node = *(aOperation.mContent); + if (auto* linkStyle = dom::LinkStyle::FromNode(*node)) { + linkStyle->SetLineNumber(aOperation.mLineNumber); + } else { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to style, but SVG wasn't disabled."); + } + return NS_OK; + } + + nsresult operator()( + const opSetScriptLineAndColumnNumberAndFreeze& aOperation) { + nsIContent* node = *(aOperation.mContent); + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node); + if (sele) { + sele->SetScriptLineNumber(aOperation.mLineNumber); + sele->SetScriptColumnNumber(aOperation.mColumnNumber); + sele->FreezeExecutionAttrs(node->OwnerDoc()); + } else { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to script, but SVG wasn't disabled."); + } + return NS_OK; + } + + nsresult operator()(const opSvgLoad& aOperation) { + SvgLoad(*(aOperation.mElement)); + return NS_OK; + } + + nsresult operator()(const opMaybeComplainAboutCharset& aOperation) { + char* msgId = aOperation.mMsgId; + bool error = aOperation.mError; + int32_t lineNumber = aOperation.mLineNumber; + mBuilder->MaybeComplainAboutCharset(msgId, error, (uint32_t)lineNumber); + return NS_OK; + } + + nsresult operator()(const opMaybeComplainAboutDeepTree& aOperation) { + mBuilder->MaybeComplainAboutDeepTree((uint32_t)aOperation.mLineNumber); + return NS_OK; + } + + nsresult operator()(const opAddClass& aOperation) { + Element* element = (*(aOperation.mElement))->AsElement(); + char16_t* str = aOperation.mClass; + nsDependentString depStr(str); + // See viewsource.css for the possible classes + nsAutoString klass; + element->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass); + if (!klass.IsEmpty()) { + klass.Append(' '); + klass.Append(depStr); + element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true); + } else { + element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true); + } + return NS_OK; + } + + nsresult operator()(const opAddViewSourceHref& aOperation) { + Element* element = (*aOperation.mElement)->AsElement(); + char16_t* buffer = aOperation.mBuffer; + int32_t length = aOperation.mLength; + nsDependentString relative(buffer, length); + + Document* doc = mBuilder->GetDocument(); + + auto encoding = doc->GetDocumentCharacterSet(); + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), relative, encoding, + mBuilder->GetViewSourceBaseURI()); + NS_ENSURE_SUCCESS(rv, NS_OK); + + // Reuse the fix for bug 467852 + // URLs that execute script (e.g. "javascript:" URLs) should just be + // ignored. There's nothing reasonable we can do with them, and allowing + // them to execute in the context of the view-source window presents a + // security risk. Just return the empty string in this case. + bool openingExecutesScript = false; + rv = NS_URIChainHasFlags(uri, + nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, + &openingExecutesScript); + if (NS_FAILED(rv) || openingExecutesScript) { + return NS_OK; + } + + nsAutoCString viewSourceUrl; + + // URLs that return data (e.g. "http:" URLs) should be prefixed with + // "view-source:". URLs that don't return data should just be returned + // undecorated. + if (!nsContentUtils::IsExternalProtocol(uri)) { + viewSourceUrl.AssignLiteral("view-source:"); + } + + nsAutoCString spec; + rv = uri->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + + viewSourceUrl.Append(spec); + + nsAutoString utf16; + CopyUTF8toUTF16(viewSourceUrl, utf16); + + element->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true); + return NS_OK; + } + + nsresult operator()(const opAddViewSourceBase& aOperation) { + nsDependentString baseUrl(aOperation.mBuffer, aOperation.mLength); + mBuilder->AddBase(baseUrl); + return NS_OK; + } + + nsresult operator()(const opAddErrorType& aOperation) { + Element* element = (*(aOperation.mElement))->AsElement(); + char* msgId = aOperation.mMsgId; + nsAtom* atom = aOperation.mName; + nsAtom* otherAtom = aOperation.mOther; + // See viewsource.css for the possible classes in addition to "error". + nsAutoString klass; + element->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass); + if (!klass.IsEmpty()) { + klass.AppendLiteral(" error"); + element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true); + } else { + element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, u"error"_ns, + true); + } + + nsresult rv; + nsAutoString message; + if (otherAtom) { + rv = nsContentUtils::FormatLocalizedString( + message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, + nsDependentAtomString(atom), nsDependentAtomString(otherAtom)); + NS_ENSURE_SUCCESS(rv, NS_OK); + } else if (atom) { + rv = nsContentUtils::FormatLocalizedString( + message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, + nsDependentAtomString(atom)); + NS_ENSURE_SUCCESS(rv, NS_OK); + } else { + rv = nsContentUtils::GetLocalizedString( + nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message); + NS_ENSURE_SUCCESS(rv, NS_OK); + } + + nsAutoString title; + element->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title); + if (!title.IsEmpty()) { + title.Append('\n'); + title.Append(message); + element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, title, true); + } else { + element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true); + } + return rv; + } + + nsresult operator()(const opAddLineNumberId& aOperation) { + Element* element = (*(aOperation.mElement))->AsElement(); + int32_t lineNumber = aOperation.mLineNumber; + nsAutoString val(u"line"_ns); + val.AppendInt(lineNumber); + element->SetAttr(kNameSpaceID_None, nsGkAtoms::id, val, true); + return NS_OK; + } + + nsresult operator()(const opStartLayout& aOperation) { + mBuilder->StartLayout( + mInterrupted); // this causes a notification flush anyway + return NS_OK; + } + + nsresult operator()(const opEnableEncodingMenu& aOperation) { + Document* doc = mBuilder->GetDocument(); + doc->EnableEncodingMenu(); + return NS_OK; + } + + nsresult operator()(const uninitialized& aOperation) { + MOZ_CRASH("uninitialized"); + return NS_OK; + } + }; + + return mOperation.match(TreeOperationMatcher(aBuilder, aScriptElement, + aInterrupted, aStreamEnded)); +} diff --git a/parser/html/nsHtml5TreeOperation.h b/parser/html/nsHtml5TreeOperation.h new file mode 100644 index 0000000000..dd5d1e8c4a --- /dev/null +++ b/parser/html/nsHtml5TreeOperation.h @@ -0,0 +1,637 @@ +/* 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/. */ + +#ifndef nsHtml5TreeOperation_h +#define nsHtml5TreeOperation_h + +#include "nsHtml5DocumentMode.h" +#include "nsHtml5HtmlAttributes.h" +#include "mozilla/dom/FromParser.h" +#include "mozilla/NotNull.h" +#include "mozilla/Variant.h" +#include "nsCharsetSource.h" + +class nsIContent; +class nsHtml5TreeOpExecutor; +class nsHtml5DocumentBuilder; +namespace mozilla { +class Encoding; + +namespace dom { +class Text; +} // namespace dom +} // namespace mozilla + +struct uninitialized {}; + +// main HTML5 ops +struct opDetach { + nsIContent** mElement; + + explicit opDetach(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opAppend { + nsIContent** mChild; + nsIContent** mParent; + mozilla::dom::FromParser mFromNetwork; + + explicit opAppend(nsIContentHandle* aChild, nsIContentHandle* aParent, + mozilla::dom::FromParser aFromNetwork) + : mFromNetwork(aFromNetwork) { + mChild = static_cast<nsIContent**>(aChild); + mParent = static_cast<nsIContent**>(aParent); + }; +}; + +struct opAppendChildrenToNewParent { + nsIContent** mOldParent; + nsIContent** mNewParent; + + explicit opAppendChildrenToNewParent(nsIContentHandle* aOldParent, + nsIContentHandle* aNewParent) { + mOldParent = static_cast<nsIContent**>(aOldParent); + mNewParent = static_cast<nsIContent**>(aNewParent); + }; +}; + +struct opFosterParent { + nsIContent** mChild; + nsIContent** mStackParent; + nsIContent** mTable; + + explicit opFosterParent(nsIContentHandle* aChild, + nsIContentHandle* aStackParent, + nsIContentHandle* aTable) { + mChild = static_cast<nsIContent**>(aChild); + mStackParent = static_cast<nsIContent**>(aStackParent); + mTable = static_cast<nsIContent**>(aTable); + }; +}; + +struct opAppendToDocument { + nsIContent** mContent; + + explicit opAppendToDocument(nsIContentHandle* aContent) { + mContent = static_cast<nsIContent**>(aContent); + }; +}; + +struct opAddAttributes { + nsIContent** mElement; + nsHtml5HtmlAttributes* mAttributes; + + explicit opAddAttributes(nsIContentHandle* aElement, + nsHtml5HtmlAttributes* aAttributes) + : mAttributes(aAttributes) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opCreateHTMLElement { + nsIContent** mContent; + nsAtom* mName; + nsHtml5HtmlAttributes* mAttributes; + mozilla::dom::HTMLContentCreatorFunction mCreator; + nsIContent** mIntendedParent; + mozilla::dom::FromParser mFromNetwork; + + explicit opCreateHTMLElement( + nsIContentHandle* aContent, nsAtom* aName, + nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::HTMLContentCreatorFunction aCreator, + nsIContentHandle* aIntendedParent, mozilla::dom::FromParser mFromNetwork) + : mName(aName), + mAttributes(aAttributes), + mCreator(aCreator), + mFromNetwork(mFromNetwork) { + mContent = static_cast<nsIContent**>(aContent); + mIntendedParent = static_cast<nsIContent**>(aIntendedParent); + aName->AddRef(); + if (mAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + mAttributes = nullptr; + } + }; +}; + +struct opCreateSVGElement { + nsIContent** mContent; + nsAtom* mName; + nsHtml5HtmlAttributes* mAttributes; + mozilla::dom::SVGContentCreatorFunction mCreator; + nsIContent** mIntendedParent; + mozilla::dom::FromParser mFromNetwork; + + explicit opCreateSVGElement(nsIContentHandle* aContent, nsAtom* aName, + nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::SVGContentCreatorFunction aCreator, + nsIContentHandle* aIntendedParent, + mozilla::dom::FromParser mFromNetwork) + : mName(aName), + mAttributes(aAttributes), + mCreator(aCreator), + mFromNetwork(mFromNetwork) { + mContent = static_cast<nsIContent**>(aContent); + mIntendedParent = static_cast<nsIContent**>(aIntendedParent); + aName->AddRef(); + if (mAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + mAttributes = nullptr; + } + }; +}; + +struct opCreateMathMLElement { + nsIContent** mContent; + nsAtom* mName; + nsHtml5HtmlAttributes* mAttributes; + nsIContent** mIntendedParent; + + explicit opCreateMathMLElement(nsIContentHandle* aContent, nsAtom* aName, + nsHtml5HtmlAttributes* aAttributes, + nsIContentHandle* aIntendedParent) + : mName(aName), mAttributes(aAttributes) { + mContent = static_cast<nsIContent**>(aContent); + mIntendedParent = static_cast<nsIContent**>(aIntendedParent); + aName->AddRef(); + if (mAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + mAttributes = nullptr; + } + }; +}; + +struct opSetFormElement { + nsIContent** mContent; + nsIContent** mFormElement; + + explicit opSetFormElement(nsIContentHandle* aContent, + nsIContentHandle* aFormElement) { + mContent = static_cast<nsIContent**>(aContent); + mFormElement = static_cast<nsIContent**>(aFormElement); + }; +}; + +struct opAppendText { + nsIContent** mParent; + char16_t* mBuffer; + int32_t mLength; + + explicit opAppendText(nsIContentHandle* aParent, char16_t* aBuffer, + int32_t aLength) + : mBuffer(aBuffer), mLength(aLength) { + mParent = static_cast<nsIContent**>(aParent); + }; +}; + +struct opFosterParentText { + nsIContent** mStackParent; + char16_t* mBuffer; + nsIContent** mTable; + int32_t mLength; + + explicit opFosterParentText(nsIContentHandle* aStackParent, char16_t* aBuffer, + nsIContentHandle* aTable, int32_t aLength) + : mBuffer(aBuffer), mLength(aLength) { + mStackParent = static_cast<nsIContent**>(aStackParent); + mTable = static_cast<nsIContent**>(aTable); + }; +}; + +struct opAppendComment { + nsIContent** mParent; + char16_t* mBuffer; + int32_t mLength; + + explicit opAppendComment(nsIContentHandle* aParent, char16_t* aBuffer, + int32_t aLength) + : mBuffer(aBuffer), mLength(aLength) { + mParent = static_cast<nsIContent**>(aParent); + }; +}; + +struct opAppendCommentToDocument { + char16_t* mBuffer; + int32_t mLength; + + explicit opAppendCommentToDocument(char16_t* aBuffer, int32_t aLength) + : mBuffer(aBuffer), mLength(aLength){}; +}; + +class nsHtml5TreeOperationStringPair { + private: + nsString mPublicId; + nsString mSystemId; + + public: + nsHtml5TreeOperationStringPair(const nsAString& aPublicId, + const nsAString& aSystemId) + : mPublicId(aPublicId), mSystemId(aSystemId) { + MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair); + } + + ~nsHtml5TreeOperationStringPair() { + MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair); + } + + inline void Get(nsAString& aPublicId, nsAString& aSystemId) { + aPublicId.Assign(mPublicId); + aSystemId.Assign(mSystemId); + } +}; + +struct opAppendDoctypeToDocument { + nsAtom* mName; + nsHtml5TreeOperationStringPair* mStringPair; + + explicit opAppendDoctypeToDocument(nsAtom* aName, const nsAString& aPublicId, + const nsAString& aSystemId) { + mName = aName; + aName->AddRef(); + mStringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId); + } +}; + +struct opGetDocumentFragmentForTemplate { + nsIContent** mTemplate; + nsIContent** mFragHandle; + + explicit opGetDocumentFragmentForTemplate(nsIContentHandle* aTemplate, + nsIContentHandle* aFragHandle) { + mTemplate = static_cast<nsIContent**>(aTemplate); + mFragHandle = static_cast<nsIContent**>(aFragHandle); + } +}; + +struct opGetFosterParent { + nsIContent** mTable; + nsIContent** mStackParent; + nsIContent** mParentHandle; + + explicit opGetFosterParent(nsIContentHandle* aTable, + nsIContentHandle* aStackParent, + nsIContentHandle* aParentHandle) { + mTable = static_cast<nsIContent**>(aTable); + mStackParent = static_cast<nsIContent**>(aStackParent); + mParentHandle = static_cast<nsIContent**>(aParentHandle); + }; +}; + +// Gecko-specific on-pop ops +struct opMarkAsBroken { + nsresult mResult; + + explicit opMarkAsBroken(nsresult aResult) : mResult(aResult){}; +}; + +struct opRunScript { + nsIContent** mElement; + nsAHtml5TreeBuilderState* mBuilderState; + int32_t mLineNumber; + + explicit opRunScript(nsIContentHandle* aElement, + nsAHtml5TreeBuilderState* aBuilderState) + : mBuilderState(aBuilderState), mLineNumber(0) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opRunScriptAsyncDefer { + nsIContent** mElement; + + explicit opRunScriptAsyncDefer(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opPreventScriptExecution { + nsIContent** mElement; + + explicit opPreventScriptExecution(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opDoneAddingChildren { + nsIContent** mElement; + + explicit opDoneAddingChildren(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opDoneCreatingElement { + nsIContent** mElement; + + explicit opDoneCreatingElement(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opUpdateCharsetSource { + nsCharsetSource mCharsetSource; + + explicit opUpdateCharsetSource(nsCharsetSource aCharsetSource) + : mCharsetSource(aCharsetSource){}; +}; + +struct opCharsetSwitchTo { + const mozilla::Encoding* mEncoding; + int32_t mCharsetSource; + int32_t mLineNumber; + + explicit opCharsetSwitchTo(const mozilla::Encoding* aEncoding, + int32_t aCharsetSource, int32_t aLineNumber) + : mEncoding(aEncoding), + mCharsetSource(aCharsetSource), + mLineNumber(aLineNumber){}; +}; + +struct opUpdateStyleSheet { + nsIContent** mElement; + + explicit opUpdateStyleSheet(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opProcessOfflineManifest { + char16_t* mUrl; + + explicit opProcessOfflineManifest(char16_t* aUrl) : mUrl(aUrl){}; +}; + +struct opMarkMalformedIfScript { + nsIContent** mElement; + + explicit opMarkMalformedIfScript(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + } +}; + +struct opStreamEnded {}; + +struct opSetStyleLineNumber { + nsIContent** mContent; + int32_t mLineNumber; + + explicit opSetStyleLineNumber(nsIContentHandle* aContent, int32_t aLineNumber) + : mLineNumber(aLineNumber) { + mContent = static_cast<nsIContent**>(aContent); + }; +}; + +struct opSetScriptLineAndColumnNumberAndFreeze { + nsIContent** mContent; + int32_t mLineNumber; + int32_t mColumnNumber; + + explicit opSetScriptLineAndColumnNumberAndFreeze(nsIContentHandle* aContent, + int32_t aLineNumber, + int32_t aColumnNumber) + : mLineNumber(aLineNumber), mColumnNumber(aColumnNumber) { + mContent = static_cast<nsIContent**>(aContent); + }; +}; + +struct opSvgLoad { + nsIContent** mElement; + + explicit opSvgLoad(nsIContentHandle* aElement) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opMaybeComplainAboutCharset { + char* mMsgId; + bool mError; + int32_t mLineNumber; + + explicit opMaybeComplainAboutCharset(char* aMsgId, bool aError, + int32_t aLineNumber) + : mMsgId(aMsgId), mError(aError), mLineNumber(aLineNumber){}; +}; + +struct opMaybeComplainAboutDeepTree { + int32_t mLineNumber; + + explicit opMaybeComplainAboutDeepTree(int32_t aLineNumber) + : mLineNumber(aLineNumber){}; +}; + +struct opAddClass { + nsIContent** mElement; + char16_t* mClass; + + explicit opAddClass(nsIContentHandle* aElement, char16_t* aClass) + : mClass(aClass) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opAddViewSourceHref { + nsIContent** mElement; + char16_t* mBuffer; + int32_t mLength; + + explicit opAddViewSourceHref(nsIContentHandle* aElement, char16_t* aBuffer, + int32_t aLength) + : mBuffer(aBuffer), mLength(aLength) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opAddViewSourceBase { + char16_t* mBuffer; + int32_t mLength; + + explicit opAddViewSourceBase(char16_t* aBuffer, int32_t aLength) + : mBuffer(aBuffer), mLength(aLength){}; +}; + +struct opAddErrorType { + nsIContent** mElement; + char* mMsgId; + nsAtom* mName; + nsAtom* mOther; + + explicit opAddErrorType(nsIContentHandle* aElement, char* aMsgId, + nsAtom* aName = nullptr, nsAtom* aOther = nullptr) + : mMsgId(aMsgId), mName(aName), mOther(aOther) { + mElement = static_cast<nsIContent**>(aElement); + if (aName) { + aName->AddRef(); + } + if (aOther) { + aOther->AddRef(); + } + }; +}; + +struct opAddLineNumberId { + nsIContent** mElement; + int32_t mLineNumber; + + explicit opAddLineNumberId(nsIContentHandle* aElement, int32_t aLineNumber) + : mLineNumber(aLineNumber) { + mElement = static_cast<nsIContent**>(aElement); + }; +}; + +struct opStartLayout {}; + +struct opEnableEncodingMenu {}; + +typedef mozilla::Variant< + uninitialized, + // main HTML5 ops + opAppend, opDetach, opAppendChildrenToNewParent, opFosterParent, + opAppendToDocument, opAddAttributes, nsHtml5DocumentMode, + opCreateHTMLElement, opCreateSVGElement, opCreateMathMLElement, + opSetFormElement, opAppendText, opFosterParentText, opAppendComment, + opAppendCommentToDocument, opAppendDoctypeToDocument, + opGetDocumentFragmentForTemplate, opGetFosterParent, + // Gecko-specific on-pop ops + opMarkAsBroken, opRunScript, opRunScriptAsyncDefer, + opPreventScriptExecution, opDoneAddingChildren, opDoneCreatingElement, + opUpdateCharsetSource, opCharsetSwitchTo, opUpdateStyleSheet, + opProcessOfflineManifest, opMarkMalformedIfScript, opStreamEnded, + opSetStyleLineNumber, opSetScriptLineAndColumnNumberAndFreeze, opSvgLoad, + opMaybeComplainAboutCharset, opMaybeComplainAboutDeepTree, opAddClass, + opAddViewSourceHref, opAddViewSourceBase, opAddErrorType, opAddLineNumberId, + opStartLayout, opEnableEncodingMenu> + treeOperation; + +class nsHtml5TreeOperation final { + template <typename T> + using NotNull = mozilla::NotNull<T>; + using Encoding = mozilla::Encoding; + + public: + static nsresult AppendTextToTextNode(const char16_t* aBuffer, + uint32_t aLength, + mozilla::dom::Text* aTextNode, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult AppendText(const char16_t* aBuffer, uint32_t aLength, + nsIContent* aParent, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult Append(nsIContent* aNode, nsIContent* aParent, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult Append(nsIContent* aNode, nsIContent* aParent, + mozilla::dom::FromParser aFromParser, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult AppendToDocument(nsIContent* aNode, + nsHtml5DocumentBuilder* aBuilder); + + static void Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder); + + static nsresult AppendChildrenToNewParent(nsIContent* aNode, + nsIContent* aParent, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult FosterParent(nsIContent* aNode, nsIContent* aParent, + nsIContent* aTable, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult AddAttributes(nsIContent* aNode, + nsHtml5HtmlAttributes* aAttributes, + nsHtml5DocumentBuilder* aBuilder); + + static void SetHTMLElementAttributes(mozilla::dom::Element* aElement, + nsAtom* aName, + nsHtml5HtmlAttributes* aAttributes); + + static nsIContent* CreateHTMLElement( + nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager, + nsHtml5DocumentBuilder* aBuilder, + mozilla::dom::HTMLContentCreatorFunction aCreator); + + static nsIContent* CreateSVGElement( + nsAtom* aName, nsHtml5HtmlAttributes* aAttributes, + mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager, + nsHtml5DocumentBuilder* aBuilder, + mozilla::dom::SVGContentCreatorFunction aCreator); + + static nsIContent* CreateMathMLElement(nsAtom* aName, + nsHtml5HtmlAttributes* aAttributes, + nsNodeInfoManager* aNodeInfoManager, + nsHtml5DocumentBuilder* aBuilder); + + static void SetFormElement(nsIContent* aNode, nsIContent* aParent); + + static nsresult AppendIsindexPrompt(nsIContent* parent, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult FosterParentText(nsIContent* aStackParent, char16_t* aBuffer, + uint32_t aLength, nsIContent* aTable, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult AppendComment(nsIContent* aParent, char16_t* aBuffer, + int32_t aLength, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult AppendCommentToDocument(char16_t* aBuffer, int32_t aLength, + nsHtml5DocumentBuilder* aBuilder); + + static nsresult AppendDoctypeToDocument(nsAtom* aName, + const nsAString& aPublicId, + const nsAString& aSystemId, + nsHtml5DocumentBuilder* aBuilder); + + static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode); + + static nsIContent* GetFosterParent(nsIContent* aTable, + nsIContent* aStackParent); + + static void PreventScriptExecution(nsIContent* aNode); + + static void DoneAddingChildren(nsIContent* aNode); + + static void DoneCreatingElement(nsIContent* aNode); + + static void SvgLoad(nsIContent* aNode); + + static void MarkMalformedIfScript(nsIContent* aNode); + + nsHtml5TreeOperation(); + + ~nsHtml5TreeOperation(); + + inline void Init(const treeOperation& aOperation) { + NS_ASSERTION(mOperation.is<uninitialized>(), + "Op code must be uninitialized when initializing."); + mOperation = aOperation; + } + + inline bool IsRunScript() { return mOperation.is<opRunScript>(); } + + inline bool IsMarkAsBroken() { return mOperation.is<opMarkAsBroken>(); } + + inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine) { + NS_ASSERTION( + IsRunScript(), + "Setting a snapshot for a tree operation other than eTreeOpRunScript!"); + MOZ_ASSERT(aSnapshot, "Initialized tree op with null snapshot."); + opRunScript data = mOperation.as<opRunScript>(); + data.mBuilderState = aSnapshot; + data.mLineNumber = aLine; + mOperation = mozilla::AsVariant(data); + } + + nsresult Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent** aScriptElement, + bool* aInterrupted, bool* aStreamEnded); + + private: + nsHtml5TreeOperation(const nsHtml5TreeOperation&) = delete; + nsHtml5TreeOperation& operator=(const nsHtml5TreeOperation&) = delete; + + treeOperation mOperation; +}; + +#endif // nsHtml5TreeOperation_h diff --git a/parser/html/nsHtml5UTF16Buffer.cpp b/parser/html/nsHtml5UTF16Buffer.cpp new file mode 100644 index 0000000000..146f06ac69 --- /dev/null +++ b/parser/html/nsHtml5UTF16Buffer.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008-2010 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit UTF16Buffer.java instead and regenerate. + */ + +#define nsHtml5UTF16Buffer_cpp__ + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +#include "nsHtml5AttributeName.h" +#include "nsHtml5ElementName.h" +#include "nsHtml5Tokenizer.h" +#include "nsHtml5TreeBuilder.h" +#include "nsHtml5StackNode.h" +#include "nsHtml5StateSnapshot.h" +#include "nsHtml5Portability.h" + +#include "nsHtml5UTF16Buffer.h" + +int32_t nsHtml5UTF16Buffer::getStart() { return start; } + +void nsHtml5UTF16Buffer::setStart(int32_t start) { this->start = start; } + +char16_t* nsHtml5UTF16Buffer::getBuffer() { return buffer; } + +int32_t nsHtml5UTF16Buffer::getEnd() { return end; } + +bool nsHtml5UTF16Buffer::hasMore() { return start < end; } + +int32_t nsHtml5UTF16Buffer::getLength() { return end - start; } + +void nsHtml5UTF16Buffer::adjust(bool lastWasCR) { + if (lastWasCR && buffer[start] == '\n') { + start++; + } +} + +void nsHtml5UTF16Buffer::setEnd(int32_t end) { this->end = end; } + +void nsHtml5UTF16Buffer::initializeStatics() {} + +void nsHtml5UTF16Buffer::releaseStatics() {} + +#include "nsHtml5UTF16BufferCppSupplement.h" diff --git a/parser/html/nsHtml5UTF16Buffer.h b/parser/html/nsHtml5UTF16Buffer.h new file mode 100644 index 0000000000..e5867df3f9 --- /dev/null +++ b/parser/html/nsHtml5UTF16Buffer.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008-2010 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. + */ + +/* + * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT. + * Please edit UTF16Buffer.java instead and regenerate. + */ + +#ifndef nsHtml5UTF16Buffer_h +#define nsHtml5UTF16Buffer_h + +#include "nsAtom.h" +#include "nsHtml5AtomTable.h" +#include "nsHtml5String.h" +#include "nsNameSpaceManager.h" +#include "nsIContent.h" +#include "nsTraceRefcnt.h" +#include "jArray.h" +#include "nsHtml5ArrayCopy.h" +#include "nsAHtml5TreeBuilderState.h" +#include "nsGkAtoms.h" +#include "nsHtml5ByteReadable.h" +#include "nsHtml5Macros.h" +#include "nsIContentHandle.h" +#include "nsHtml5Portability.h" +#include "nsHtml5ContentCreatorFunction.h" + +class nsHtml5StreamParser; + +class nsHtml5AttributeName; +class nsHtml5ElementName; +class nsHtml5Tokenizer; +class nsHtml5TreeBuilder; +class nsHtml5StateSnapshot; +class nsHtml5Portability; + +class nsHtml5UTF16Buffer { + private: + char16_t* buffer; + int32_t start; + int32_t end; + + public: + int32_t getStart(); + void setStart(int32_t start); + char16_t* getBuffer(); + int32_t getEnd(); + bool hasMore(); + int32_t getLength(); + void adjust(bool lastWasCR); + void setEnd(int32_t end); + static void initializeStatics(); + static void releaseStatics(); + +#include "nsHtml5UTF16BufferHSupplement.h" +}; + +#endif diff --git a/parser/html/nsHtml5UTF16BufferCppSupplement.h b/parser/html/nsHtml5UTF16BufferCppSupplement.h new file mode 100644 index 0000000000..79f2658a45 --- /dev/null +++ b/parser/html/nsHtml5UTF16BufferCppSupplement.h @@ -0,0 +1,26 @@ +/* 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/. */ + +nsHtml5UTF16Buffer::nsHtml5UTF16Buffer(char16_t* aBuffer, int32_t aEnd) + : buffer(aBuffer), start(0), end(aEnd) { + MOZ_COUNT_CTOR(nsHtml5UTF16Buffer); +} + +nsHtml5UTF16Buffer::~nsHtml5UTF16Buffer() { + MOZ_COUNT_DTOR(nsHtml5UTF16Buffer); +} + +void nsHtml5UTF16Buffer::DeleteBuffer() { delete[] buffer; } + +void nsHtml5UTF16Buffer::Swap(nsHtml5UTF16Buffer* aOther) { + char16_t* tempBuffer = buffer; + int32_t tempStart = start; + int32_t tempEnd = end; + buffer = aOther->buffer; + start = aOther->start; + end = aOther->end; + aOther->buffer = tempBuffer; + aOther->start = tempStart; + aOther->end = tempEnd; +} diff --git a/parser/html/nsHtml5UTF16BufferHSupplement.h b/parser/html/nsHtml5UTF16BufferHSupplement.h new file mode 100644 index 0000000000..ef7b662cbe --- /dev/null +++ b/parser/html/nsHtml5UTF16BufferHSupplement.h @@ -0,0 +1,17 @@ +/* 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/. */ + +protected: +nsHtml5UTF16Buffer(char16_t* aBuffer, int32_t aEnd); +~nsHtml5UTF16Buffer(); + +/** + * For working around the privacy of |buffer| in the generated code. + */ +void DeleteBuffer(); + +/** + * For working around the privacy of |buffer| in the generated code. + */ +void Swap(nsHtml5UTF16Buffer* aOther); diff --git a/parser/html/nsHtml5ViewSourceUtils.cpp b/parser/html/nsHtml5ViewSourceUtils.cpp new file mode 100644 index 0000000000..3fb46e8bd2 --- /dev/null +++ b/parser/html/nsHtml5ViewSourceUtils.cpp @@ -0,0 +1,63 @@ +/* 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/. */ + +#include "nsHtml5ViewSourceUtils.h" +#include "mozilla/Preferences.h" +#include "nsHtml5AttributeName.h" +#include "nsHtml5String.h" +#include "mozilla/StaticPrefs_view_source.h" + +// static +nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewBodyAttributes() { + nsHtml5HtmlAttributes* bodyAttrs = new nsHtml5HtmlAttributes(0); + nsHtml5String id = nsHtml5Portability::newStringFromLiteral("viewsource"); + bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, id, -1); + + nsString klass; + if (mozilla::StaticPrefs::view_source_wrap_long_lines()) { + klass.AppendLiteral(u"wrap "); + } + if (mozilla::StaticPrefs::view_source_syntax_highlight()) { + klass.AppendLiteral(u"highlight"); + } + if (!klass.IsEmpty()) { + bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_CLASS, + nsHtml5String::FromString(klass), -1); + } + + int32_t tabSize = mozilla::StaticPrefs::view_source_tab_size(); + if (tabSize > 0) { + nsString style; + style.AssignLiteral("tab-size: "); + style.AppendInt(tabSize); + bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_STYLE, + nsHtml5String::FromString(style), -1); + } + + return bodyAttrs; +} + +// static +nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewLinkAttributes() { + nsHtml5HtmlAttributes* linkAttrs = new nsHtml5HtmlAttributes(0); + nsHtml5String rel = nsHtml5Portability::newStringFromLiteral("stylesheet"); + linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_REL, rel, -1); + nsHtml5String type = nsHtml5Portability::newStringFromLiteral("text/css"); + linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_TYPE, type, -1); + nsHtml5String href = nsHtml5Portability::newStringFromLiteral( + "resource://content-accessible/viewsource.css"); + linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_HREF, href, -1); + return linkAttrs; +} + +// static +nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewMetaViewportAttributes() { + nsHtml5HtmlAttributes* metaVpAttrs = new nsHtml5HtmlAttributes(0); + nsHtml5String name = nsHtml5Portability::newStringFromLiteral("viewport"); + metaVpAttrs->addAttribute(nsHtml5AttributeName::ATTR_NAME, name, -1); + nsHtml5String content = + nsHtml5Portability::newStringFromLiteral("width=device-width"); + metaVpAttrs->addAttribute(nsHtml5AttributeName::ATTR_CONTENT, content, -1); + return metaVpAttrs; +} diff --git a/parser/html/nsHtml5ViewSourceUtils.h b/parser/html/nsHtml5ViewSourceUtils.h new file mode 100644 index 0000000000..e5ba30f8d5 --- /dev/null +++ b/parser/html/nsHtml5ViewSourceUtils.h @@ -0,0 +1,17 @@ +/* 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/. */ + +#ifndef nsHtml5ViewSourceUtils_h +#define nsHtml5ViewSourceUtils_h + +#include "nsHtml5HtmlAttributes.h" + +class nsHtml5ViewSourceUtils { + public: + static nsHtml5HtmlAttributes* NewBodyAttributes(); + static nsHtml5HtmlAttributes* NewLinkAttributes(); + static nsHtml5HtmlAttributes* NewMetaViewportAttributes(); +}; + +#endif // nsHtml5ViewSourceUtils_h diff --git a/parser/html/nsIContentHandle.h b/parser/html/nsIContentHandle.h new file mode 100644 index 0000000000..b1cd6475f8 --- /dev/null +++ b/parser/html/nsIContentHandle.h @@ -0,0 +1,5 @@ +/* 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/. */ + +typedef void nsIContentHandle; diff --git a/parser/html/nsIParserUtils.idl b/parser/html/nsIParserUtils.idl new file mode 100644 index 0000000000..a8027a83fb --- /dev/null +++ b/parser/html/nsIParserUtils.idl @@ -0,0 +1,141 @@ +/* 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/. */ + +#include "nsISupports.idl" + +interface nsIURI; + +webidl DocumentFragment; +webidl Element; + +/** + * Non-Web HTML parser functionality to Firefox extensions and XULRunner apps. + * Don't use this from within Gecko--use nsContentUtils, nsTreeSanitizer, etc. + * directly instead. + */ +[builtinclass, scriptable, uuid(a1101145-0025-411e-8873-fdf57bf28128)] +interface nsIParserUtils : nsISupports +{ + /** + * Flag for sanitizer: Allow comment nodes. + */ + const unsigned long SanitizerAllowComments = (1 << 0); + + /** + * Flag for sanitizer: Allow <style> and style="" (with contents sanitized + * in case of -moz-binding). Note! If -moz-binding is absent, properties + * that might be XSS risks in other Web engines are preserved! + */ + const unsigned long SanitizerAllowStyle = (1 << 1); + + /** + * Flag for sanitizer: Only allow cid: URLs for embedded content. + * + * At present, sanitizing CSS backgrounds, etc., is not supported, so setting + * this together with SanitizerAllowStyle doesn't make sense. + * + * At present, sanitizing CSS syntax in SVG presentational attributes is not + * supported, so this option flattens out SVG. + */ + const unsigned long SanitizerCidEmbedsOnly = (1 << 2); + + /** + * Flag for sanitizer: Drop non-CSS presentational HTML elements and + * attributes, such as <font>, <center> and bgcolor="". + */ + const unsigned long SanitizerDropNonCSSPresentation = (1 << 3); + + /** + * Flag for sanitizer: Drop forms and form controls (excluding + * fieldset/legend). + */ + const unsigned long SanitizerDropForms = (1 << 4); + + /** + * Flag for sanitizer: Drop <img>, <video>, <audio> and <source> and flatten + * out SVG. + */ + const unsigned long SanitizerDropMedia = (1 << 5); + + /** + * Flag for sanitizer: Log messages to the console for everything that gets + * sanitized + */ + const unsigned long SanitizerLogRemovals = (1 << 6); + + /** + * Parses a string into an HTML document, sanitizes the document and + * returns the result serialized to a string. + * + * The sanitizer is designed to protect against XSS when sanitized content + * is inserted into a different-origin context without an iframe-equivalent + * sandboxing mechanism. + * + * By default, the sanitizer doesn't try to avoid leaking information that + * the content was viewed to third parties. That is, by default, e.g. + * <img src> pointing to an HTTP server potentially controlled by a third + * party is not removed. To avoid ambient information leakage upon loading + * the sanitized content, use the SanitizerInternalEmbedsOnly flag. In that + * case, <a href> links (and similar) to other content are preserved, so an + * explicit user action (following a link) after the content has been loaded + * can still leak information. + * + * By default, non-dangerous non-CSS presentational HTML elements and + * attributes or forms are not removed. To remove these, use + * SanitizerDropNonCSSPresentation and/or SanitizerDropForms. + * + * By default, comments and CSS is removed. To preserve comments, use + * SanitizerAllowComments. To preserve <style> and style="", use + * SanitizerAllowStyle. -moz-binding is removed from <style> and style="" if + * present. In this case, properties that Gecko doesn't recognize can get + * removed as a side effect. Note! If -moz-binding is not present, <style> + * and style="" and SanitizerAllowStyle is specified, the sanitized content + * may still be XSS dangerous if loaded into a non-Gecko Web engine! + * + * @param src the HTML source to parse (C++ callers are allowed but not + * required to use the same string for the return value.) + * @param flags sanitization option flags defined above + */ + AString sanitize(in AString src, in unsigned long flags); + + /** + * Removes conditional CSS (@media / etc) from the input string. + */ + AString removeConditionalCSS(in AString src); + + /** + * Convert HTML to plain text. + * + * @param src the HTML source to parse (C++ callers are allowed but not + * required to use the same string for the return value.) + * @param flags conversion option flags defined in nsIDocumentEncoder + * @param wrapCol number of characters per line; 0 for no auto-wrapping + */ + AString convertToPlainText(in AString src, + in unsigned long flags, + in unsigned long wrapCol); + + /** + * Parses markup into a sanitized document fragment. + * + * @param fragment the input markup + * @param flags sanitization option flags defined above + * @param isXML true if |fragment| is XML and false if HTML + * @param baseURI the base URL for this fragment + * @param element the context node for the fragment parsing algorithm + */ + DocumentFragment parseFragment(in AString fragment, + in unsigned long flags, + in boolean isXML, + in nsIURI baseURI, + in Element element); + +}; + +%{ C++ +#define NS_PARSERUTILS_CONTRACTID \ + "@mozilla.org/parserutils;1" +#define NS_PARSERUTILS_CID \ +{ 0xaf7b24cb, 0x893f, 0x41bb, { 0x96, 0x1f, 0x5a, 0x69, 0x38, 0x8e, 0x27, 0xc3 } } +%} diff --git a/parser/html/nsParserUtils.cpp b/parser/html/nsParserUtils.cpp new file mode 100644 index 0000000000..74b86febe8 --- /dev/null +++ b/parser/html/nsParserUtils.cpp @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#include "nsParserUtils.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/ScriptLoader.h" +#include "nsAttrName.h" +#include "nsCOMPtr.h" +#include "nsContentCID.h" +#include "nsContentUtils.h" +#include "nsEscape.h" +#include "nsHTMLParts.h" +#include "nsHtml5Module.h" +#include "nsIContent.h" +#include "nsIContentSink.h" +#include "nsIDTD.h" +#include "mozilla/dom/Document.h" +#include "nsIDocumentEncoder.h" +#include "nsIFragmentContentSink.h" +#include "nsIParser.h" +#include "nsNetCID.h" +#include "nsNetUtil.h" +#include "nsString.h" +#include "nsTreeSanitizer.h" +#include "nsXPCOM.h" + +#define XHTML_DIV_TAG u"div xmlns=\"http://www.w3.org/1999/xhtml\"" + +using namespace mozilla::dom; + +NS_IMPL_ISUPPORTS(nsParserUtils, nsIParserUtils) + +NS_IMETHODIMP +nsParserUtils::ConvertToPlainText(const nsAString& aFromStr, uint32_t aFlags, + uint32_t aWrapCol, nsAString& aToStr) { + return nsContentUtils::ConvertToPlainText(aFromStr, aToStr, aFlags, aWrapCol); +} + +template <typename Callable> +static nsresult SanitizeWith(const nsAString& aInput, nsAString& aOutput, + Callable aDoSanitize) { + RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr); + if (!document) { + return NS_ERROR_FAILURE; + } + + nsresult rv = nsContentUtils::ParseDocumentHTML(aInput, document, false); + NS_ENSURE_SUCCESS(rv, rv); + + aDoSanitize(document.get()); + + nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/html"); + encoder->NativeInit(document, u"text/html"_ns, + nsIDocumentEncoder::OutputDontRewriteEncodingDeclaration | + nsIDocumentEncoder::OutputNoScriptContent | + nsIDocumentEncoder::OutputEncodeBasicEntities | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputRaw); + return encoder->EncodeToString(aOutput); +} + +NS_IMETHODIMP +nsParserUtils::Sanitize(const nsAString& aFromStr, uint32_t aFlags, + nsAString& aToStr) { + return SanitizeWith(aFromStr, aToStr, [&](Document* aDocument) { + nsTreeSanitizer sanitizer(aFlags); + sanitizer.Sanitize(aDocument); + }); +} + +NS_IMETHODIMP +nsParserUtils::RemoveConditionalCSS(const nsAString& aFromStr, + nsAString& aToStr) { + return SanitizeWith(aFromStr, aToStr, [](Document* aDocument) { + nsTreeSanitizer::RemoveConditionalCSSFromSubtree(aDocument); + }); +} + +NS_IMETHODIMP +nsParserUtils::ParseFragment(const nsAString& aFragment, uint32_t aFlags, + bool aIsXML, nsIURI* aBaseURI, + Element* aContextElement, + DocumentFragment** aReturn) { + NS_ENSURE_ARG(aContextElement); + *aReturn = nullptr; + + RefPtr<Document> document = aContextElement->OwnerDoc(); + + nsAutoScriptBlockerSuppressNodeRemoved autoBlocker; + + // stop scripts + RefPtr<ScriptLoader> loader = document->ScriptLoader(); + bool scripts_enabled = loader->GetEnabled(); + if (scripts_enabled) { + loader->SetEnabled(false); + } + + // Wrap things in a div or body for parsing, but it won't show up in + // the fragment. + nsresult rv = NS_OK; + AutoTArray<nsString, 2> tagStack; + RefPtr<DocumentFragment> fragment; + if (aIsXML) { + // XHTML + tagStack.AppendElement(nsLiteralString(XHTML_DIV_TAG)); + rv = nsContentUtils::ParseFragmentXML(aFragment, document, tagStack, true, + aFlags, getter_AddRefs(fragment)); + } else { + fragment = new (document->NodeInfoManager()) + DocumentFragment(document->NodeInfoManager()); + rv = nsContentUtils::ParseFragmentHTML(aFragment, fragment, nsGkAtoms::body, + kNameSpaceID_XHTML, false, true, + aFlags); + } + + if (scripts_enabled) { + loader->SetEnabled(true); + } + + fragment.forget(aReturn); + return rv; +} diff --git a/parser/html/nsParserUtils.h b/parser/html/nsParserUtils.h new file mode 100644 index 0000000000..cd92d6add9 --- /dev/null +++ b/parser/html/nsParserUtils.h @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef nsParserUtils_h +#define nsParserUtils_h + +#include "nsIParserUtils.h" +#include "mozilla/Attributes.h" + +class nsParserUtils final : public nsIParserUtils { + ~nsParserUtils() {} + + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPARSERUTILS +}; + +#endif // nsParserUtils_h |