summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2019-09-04 15:27:40 +0200
committerwolfbeast <mcwerewolf@wolfbeast.com>2019-09-04 15:27:40 +0200
commit0ce08b418d84a57bae22a0aa395fecb7412ed931 (patch)
tree7d46a9b019e57aee76879290695ce2173a8891af
parentcc60a093cb65745602dc1f5eab9f5e328ddaad15 (diff)
downloaduxp-0ce08b418d84a57bae22a0aa395fecb7412ed931.tar.gz
Fix an issue with the html5 tokenizer and tree builder.
-rw-r--r--parser/html/jArray.h43
-rw-r--r--parser/html/javasrc/Tokenizer.java33
-rw-r--r--parser/html/javasrc/TreeBuilder.java22
-rw-r--r--parser/html/nsHtml5Tokenizer.cpp19
-rw-r--r--parser/html/nsHtml5Tokenizer.h3
-rw-r--r--parser/html/nsHtml5TreeBuilder.cpp22
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;