diff options
author | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-09-04 15:27:40 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-09-04 15:27:40 +0200 |
commit | 0ce08b418d84a57bae22a0aa395fecb7412ed931 (patch) | |
tree | 7d46a9b019e57aee76879290695ce2173a8891af | |
parent | cc60a093cb65745602dc1f5eab9f5e328ddaad15 (diff) | |
download | uxp-0ce08b418d84a57bae22a0aa395fecb7412ed931.tar.gz |
Fix an issue with the html5 tokenizer and tree builder.
-rw-r--r-- | parser/html/jArray.h | 43 | ||||
-rw-r--r-- | parser/html/javasrc/Tokenizer.java | 33 | ||||
-rw-r--r-- | parser/html/javasrc/TreeBuilder.java | 22 | ||||
-rw-r--r-- | parser/html/nsHtml5Tokenizer.cpp | 19 | ||||
-rw-r--r-- | parser/html/nsHtml5Tokenizer.h | 3 | ||||
-rw-r--r-- | parser/html/nsHtml5TreeBuilder.cpp | 22 |
6 files changed, 103 insertions, 39 deletions
diff --git a/parser/html/jArray.h b/parser/html/jArray.h index 45548a0773..98889059ca 100644 --- a/parser/html/jArray.h +++ b/parser/html/jArray.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2008-2015 Mozilla Foundation + * Copyright (c) 2019 Moonchild Productions * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -44,32 +45,66 @@ struct staticJArray { } }; -template<class T, class L> -struct jArray { +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; } + + 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) + { + } +}; // class jArray template<class T, class L> class autoJArray { diff --git a/parser/html/javasrc/Tokenizer.java b/parser/html/javasrc/Tokenizer.java index 70e1df75c1..f141d94d79 100644 --- a/parser/html/javasrc/Tokenizer.java +++ b/parser/html/javasrc/Tokenizer.java @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2007 Henri Sivonen * Copyright (c) 2007-2015 Mozilla Foundation + * Copyright (c) 2019 Moonchild Productions * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla * Foundation, and Opera Software ASA. * @@ -680,6 +681,22 @@ public class Tokenizer implements Locator { * * @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 */ @@ -695,6 +712,8 @@ public class Tokenizer implements Locator { 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 @@ -3759,11 +3778,17 @@ public class Tokenizer implements Locator { c = checkChar(buf, pos); /* * ASSERT! when entering this state, set index to 0 and - * call clearStrBufBeforeUse() assert (contentModelElement != - * null); Let's implement the above without lookahead. - * strBuf is the 'temporary buffer'. + * call clearStrBufBeforeUse(); Let's implement the above + * without lookahead. strBuf is the 'temporary buffer'. */ - if (index < endTagExpectationAsArray.length) { + 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') { diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java index 5e83d18473..58074086d3 100644 --- a/parser/html/javasrc/TreeBuilder.java +++ b/parser/html/javasrc/TreeBuilder.java @@ -1,6 +1,7 @@ /* * Copyright (c) 2007 Henri Sivonen * Copyright (c) 2007-2015 Mozilla Foundation + * Copyright (c) 2018-2019 Moonchild Productions * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla * Foundation, and Opera Software ASA. * @@ -640,8 +641,7 @@ public abstract class TreeBuilder<T> implements TokenHandler, ); currentPtr++; stack[currentPtr] = node; - tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA, - contextName); + 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; @@ -671,8 +671,7 @@ public abstract class TreeBuilder<T> implements TokenHandler, ); currentPtr++; stack[currentPtr] = node; - tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA, - contextName); + 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; @@ -691,23 +690,18 @@ public abstract class TreeBuilder<T> implements TokenHandler, resetTheInsertionMode(); formPointer = getFormPointerForContext(contextNode); if ("title" == contextName || "textarea" == contextName) { - tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA, - contextName); + tokenizer.setState(Tokenizer.RCDATA); } else if ("style" == contextName || "xmp" == contextName || "iframe" == contextName || "noembed" == contextName || "noframes" == contextName || (scriptingEnabled && "noscript" == contextName)) { - tokenizer.setStateAndEndTagExpectation(Tokenizer.RAWTEXT, - contextName); + tokenizer.setState(Tokenizer.RAWTEXT); } else if ("plaintext" == contextName) { - tokenizer.setStateAndEndTagExpectation(Tokenizer.PLAINTEXT, - contextName); + tokenizer.setState(Tokenizer.PLAINTEXT); } else if ("script" == contextName) { - tokenizer.setStateAndEndTagExpectation( - Tokenizer.SCRIPT_DATA, contextName); + tokenizer.setState(Tokenizer.SCRIPT_DATA); } else { - tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA, - contextName); + tokenizer.setState(Tokenizer.DATA); } } contextName = null; diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index e70c081bf1..8aae5613aa 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2007 Henri Sivonen * Copyright (c) 2007-2015 Mozilla Foundation + * Copyright (c) 2019 Moonchild Productions * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla * Foundation, and Opera Software ASA. * @@ -127,15 +128,11 @@ nsHtml5Tokenizer::isViewingXmlSource() } void -nsHtml5Tokenizer::setStateAndEndTagExpectation(int32_t specialTokenizerState, nsIAtom* endTagExpectation) +nsHtml5Tokenizer::setState(int32_t specialTokenizerState) { this->stateSave = specialTokenizerState; - if (specialTokenizerState == NS_HTML5TOKENIZER_DATA) { - return; - } - autoJArray<char16_t,int32_t> asArray = nsHtml5Portability::newCharArrayFromLocal(endTagExpectation); - this->endTagExpectation = nsHtml5ElementName::elementNameByBuffer(asArray, 0, asArray.length, interner); - endTagExpectationToArray(); + this->endTagExpectation = nullptr; + this->endTagExpectationAsArray = nullptr; } void @@ -2040,7 +2037,13 @@ nsHtml5Tokenizer::stateLoop(int32_t state, char16_t c, int32_t pos, char16_t* bu NS_HTML5_BREAK(stateloop); } c = checkChar(buf, pos); - if (index < endTagExpectationAsArray.length) { + if (!endTagExpectationAsArray) { + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + cstart = pos; + reconsume = true; + state = P::transition(mViewSource, 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') { diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h index 00cca9a9c1..11a9bab1b9 100644 --- a/parser/html/nsHtml5Tokenizer.h +++ b/parser/html/nsHtml5Tokenizer.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2007 Henri Sivonen * Copyright (c) 2007-2015 Mozilla Foundation + * Copyright (c) 2019 Moonchild Productions * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla * Foundation, and Opera Software ASA. * @@ -143,7 +144,7 @@ class nsHtml5Tokenizer void setInterner(nsHtml5AtomTable* interner); void initLocation(nsHtml5String newPublicId, nsHtml5String newSystemId); bool isViewingXmlSource(); - void setStateAndEndTagExpectation(int32_t specialTokenizerState, nsIAtom* endTagExpectation); + void setState(int32_t specialTokenizerState); void setStateAndEndTagExpectation(int32_t specialTokenizerState, nsHtml5ElementName* endTagExpectation); private: void endTagExpectationToArray(); diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index 457c7deb11..e5040d050a 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2007 Henri Sivonen * Copyright (c) 2007-2015 Mozilla Foundation + * Copyright (c) 2019 Moonchild Productions * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla * Foundation, and Opera Software ASA. * @@ -105,7 +106,7 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elementName->camelCaseName, elt); currentPtr++; stack[currentPtr] = node; - tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName); + tokenizer->setState(NS_HTML5TOKENIZER_DATA); mode = NS_HTML5TREE_BUILDER_FRAMESET_OK; } else if (contextNamespace == kNameSpaceID_MathML) { nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH; @@ -117,7 +118,7 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, elementName->name, false); currentPtr++; stack[currentPtr] = node; - tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName); + tokenizer->setState(NS_HTML5TOKENIZER_DATA); mode = NS_HTML5TREE_BUILDER_FRAMESET_OK; } else { nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HTML, elt); @@ -129,15 +130,20 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) resetTheInsertionMode(); formPointer = getFormPointerForContext(contextNode); if (nsHtml5Atoms::title == contextName || nsHtml5Atoms::textarea == contextName) { - tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RCDATA, contextName); - } else if (nsHtml5Atoms::style == contextName || nsHtml5Atoms::xmp == contextName || nsHtml5Atoms::iframe == contextName || nsHtml5Atoms::noembed == contextName || nsHtml5Atoms::noframes == contextName || (scriptingEnabled && nsHtml5Atoms::noscript == contextName)) { - tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, contextName); + tokenizer->setState(NS_HTML5TOKENIZER_RCDATA); + } else if (nsHtml5Atoms::style == contextName || + nsHtml5Atoms::xmp == contextName || + nsHtml5Atoms::iframe == contextName || + nsHtml5Atoms::noembed == contextName || + nsHtml5Atoms::noframes == contextName || + (scriptingEnabled && nsHtml5Atoms::noscript == contextName)) { + tokenizer->setState(NS_HTML5TOKENIZER_RAWTEXT); } else if (nsHtml5Atoms::plaintext == contextName) { - tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_PLAINTEXT, contextName); + tokenizer->setState(NS_HTML5TOKENIZER_PLAINTEXT); } else if (nsHtml5Atoms::script == contextName) { - tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_SCRIPT_DATA, contextName); + tokenizer->setState(NS_HTML5TOKENIZER_SCRIPT_DATA); } else { - tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName); + tokenizer->setState(NS_HTML5TOKENIZER_DATA); } } contextName = nullptr; |