From c718393931b30bb55b2a874700c0b5755997a3dd Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 1 Nov 2011 13:33:11 +0200 Subject: [PATCH] Bug 482921 part 14 - Address review comments. r=Olli.Pettay. --- parser/html/javasrc/TreeBuilder.java | 3 + parser/html/nsHtml5Highlighter.cpp | 52 +++---- parser/html/nsHtml5Highlighter.h | 13 +- parser/html/nsHtml5StreamParser.cpp | 12 +- parser/html/nsHtml5Tokenizer.cpp | 100 ++++++------ parser/html/nsHtml5TokenizerCppSupplement.h | 162 +++++++++++++------- parser/html/nsHtml5TokenizerLoopPolicies.h | 12 +- parser/html/nsHtml5TreeBuilderHSupplement.h | 23 +++ parser/html/nsHtml5TreeOpExecutor.cpp | 2 + parser/html/nsHtml5TreeOperation.cpp | 5 +- 10 files changed, 243 insertions(+), 141 deletions(-) diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java index 32973e535d4d..3db2c69aef44 100644 --- a/parser/html/javasrc/TreeBuilder.java +++ b/parser/html/javasrc/TreeBuilder.java @@ -868,6 +868,8 @@ public abstract class TreeBuilder implements TokenHandler, */ 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: } @@ -1271,6 +1273,7 @@ public abstract class TreeBuilder implements TokenHandler, public final void eof() throws SAXException { flushCharacters(); + // Note: Can't attach error messages to EOF in C++ yet eofloop: for (;;) { if (isInForeign()) { // [NOCPP[ diff --git a/parser/html/nsHtml5Highlighter.cpp b/parser/html/nsHtml5Highlighter.cpp index 7e1f3102c378..68832fdc3153 100644 --- a/parser/html/nsHtml5Highlighter.cpp +++ b/parser/html/nsHtml5Highlighter.cpp @@ -205,10 +205,10 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) case NS_HTML5TOKENIZER_TAG_NAME: switch (aState) { case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME: - EndInline(); // NS_HTML5TOKENIZER_TAG_NAME + EndSpanOrA(); // NS_HTML5TOKENIZER_TAG_NAME break; case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG: - EndInline(); // NS_HTML5TOKENIZER_TAG_NAME + EndSpanOrA(); // NS_HTML5TOKENIZER_TAG_NAME StartSpan(); // for highlighting the slash mSlash = CurrentNode(); break; @@ -235,10 +235,10 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) switch (aState) { case NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_NAME: case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_VALUE: - EndInline(); // NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME + EndSpanOrA(); // NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME break; case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG: - EndInline(); // NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME + EndSpanOrA(); // NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME StartSpan(); // for highlighting the slash mSlash = CurrentNode(); break; @@ -266,7 +266,7 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_SINGLE_QUOTED: switch (aState) { case NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_VALUE_QUOTED: - EndInline(); + EndSpanOrA(); break; case NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE: StartSpan(); @@ -292,7 +292,7 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) } break; case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG: - EndInline(); // end the slash highlight + EndSpanOrA(); // end the slash highlight switch (aState) { case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME: break; @@ -304,7 +304,7 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_UNQUOTED: switch (aState) { case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME: - EndInline(); + EndSpanOrA(); break; case NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE: StartSpan(); @@ -353,14 +353,14 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) } break; case NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE: - EndInline(); // the span for the ampersand + EndSpanOrA(); // the span for the ampersand switch (aState) { case NS_HTML5TOKENIZER_CONSUME_NCR: case NS_HTML5TOKENIZER_CHARACTER_REFERENCE_HILO_LOOKUP: break; default: // not actually a character reference - EndInline(); + EndSpanOrA(); break; } break; @@ -369,13 +369,13 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) break; } // not actually a character reference - EndInline(); + EndSpanOrA(); break; case NS_HTML5TOKENIZER_CHARACTER_REFERENCE_TAIL: if (!aReconsume) { FlushCurrent(); } - EndInline(); + EndSpanOrA(); break; case NS_HTML5TOKENIZER_DECIMAL_NRC_LOOP: case NS_HTML5TOKENIZER_HEX_NCR_LOOP: @@ -388,7 +388,7 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) AddClass(sEntity); break; } - EndInline(); + EndSpanOrA(); break; case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN: switch (aState) { @@ -406,18 +406,18 @@ nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos) StartSpan(); // don't know if it is "end-tag" yet :-( break; } - EndInline(); + EndSpanOrA(); StartCharacters(); break; case NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME: switch (aState) { case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME: AddClass(sEndTag); - EndInline(); + EndSpanOrA(); break; case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG: AddClass(sEndTag); - EndInline(); + EndSpanOrA(); StartSpan(); // for highlighting the slash mSlash = CurrentNode(); break; @@ -557,7 +557,7 @@ nsHtml5Highlighter::StartSpan(const PRUnichar* aClass) } void -nsHtml5Highlighter::EndInline() +nsHtml5Highlighter::EndSpanOrA() { FlushChars(); Pop(); @@ -596,10 +596,10 @@ void nsHtml5Highlighter::FinishTag() { while (mInlinesOpen > 1) { - EndInline(); + EndSpanOrA(); } FlushCurrent(); // > - EndInline(); // DATA + EndSpanOrA(); // DATA NS_ASSERTION(!mInlinesOpen, "mInlinesOpen got out of sync!"); StartCharacters(); } @@ -685,14 +685,14 @@ void nsHtml5Highlighter::MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName, nsString* 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)) { + 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); diff --git a/parser/html/nsHtml5Highlighter.h b/parser/html/nsHtml5Highlighter.h index 3def948c9d5d..b2b06b22e245 100644 --- a/parser/html/nsHtml5Highlighter.h +++ b/parser/html/nsHtml5Highlighter.h @@ -192,9 +192,9 @@ class nsHtml5Highlighter void StartSpan(const PRUnichar* aClass); /** - * End the current or . + * End the current or in the highlighter output. */ - void EndInline(); + void EndSpanOrA(); /** * Starts a wrapper around a run of characters. @@ -222,8 +222,10 @@ class nsHtml5Highlighter void FlushCurrent(); /** - * Finishes a source tag being highlighted by closing the open and - * elements. + * Finishes highlighting a tag in the input data by closing the open + * and elements in the highlighter output and then starts + * another for potentially highlighting characters potentially + * appearing next. */ void FinishTag(); @@ -238,6 +240,9 @@ class nsHtml5Highlighter /** * Allocates a handle for an element. * + * See the documentation for nsHtml5TreeBuilder::AllocateContentHandle() + * in nsHtml5TreeBuilderHSupplement.h. + * * @return the handle */ nsIContent** AllocateContentHandle(); diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp index f91fa98c4788..6b569f5b27a8 100644 --- a/parser/html/nsHtml5StreamParser.cpp +++ b/parser/html/nsHtml5StreamParser.cpp @@ -516,6 +516,14 @@ nsHtml5StreamParser::FinalizeSniffing(const PRUint8* aFromSegment, // can be nul XML_SetUserData(ud.mExpat, static_cast(&ud)); XML_Status status = XML_STATUS_OK; + + // aFromSegment points to the data obtained from the current network + // event. mSniffingBuffer (if it exists) contains the data obtained before + // the current event. Thus, mSniffingLenth bytes of mSniffingBuffer + // followed by aCountToSniffingLimit bytes from aFromSegment are the + // first 1024 bytes of the file (or the file as a whole if the file is + // 1024 bytes long or shorter). Thus, we parse both buffers, but if the + // first call succeeds already, we skip parsing the second buffer. if (mSniffingBuffer) { status = XML_Parse(ud.mExpat, reinterpret_cast(mSniffingBuffer.get()), @@ -682,8 +690,8 @@ nsHtml5StreamParser::SniffStreamBytes(const PRUint8* aFromSegment, PRUint32 countToSniffingLimit = NS_HTML5_STREAM_PARSER_SNIFFING_BUFFER_SIZE - mSniffingLength; if (mMode == NORMAL || mMode == VIEW_SOURCE_HTML) { - nsHtml5ByteReadable readable(aFromSegment, aFromSegment - + countToSniffingLimit); + nsHtml5ByteReadable readable(aFromSegment, aFromSegment + + countToSniffingLimit); mMetaScanner->sniff(&readable, getter_AddRefs(mUnicodeDecoder), mCharset); if (mUnicodeDecoder) { mUnicodeDecoder->SetInputErrorBehavior( diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 6d120c94b69b..28428e320bcd 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -496,7 +496,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* state = P::transition(mViewSource, NS_HTML5TOKENIZER_PROCESSING_INSTRUCTION, reconsume, pos); NS_HTML5_CONTINUE(stateloop); } - if (P::viewingSource) { + if (P::reportErrors) { errProcessingInstruction(); } clearLongStrBufAndAppend(c); @@ -504,7 +504,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errLtGt(); } tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 2); @@ -513,7 +513,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } default: { - if (P::viewingSource) { + if (P::reportErrors) { errBadCharAfterLt(c); } tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); @@ -617,7 +617,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '\'': case '<': case '=': { - if (P::viewingSource) { + if (P::reportErrors) { errBadCharBeforeAttributeNameOrNull(c); } } @@ -682,7 +682,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '\"': case '\'': case '<': { - if (P::viewingSource) { + if (P::reportErrors) { errQuoteOrLtInAttributeNameOrNull(c); } } @@ -734,7 +734,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errAttributeValueMissing(); } addAttributeWithoutValue(); @@ -750,7 +750,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '<': case '=': case '`': { - if (P::viewingSource) { + if (P::reportErrors) { errLtOrEqualsOrGraveInUnquotedAttributeOrNull(c); } } @@ -839,7 +839,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } default: { - if (P::viewingSource) { + if (P::reportErrors) { errNoSpaceBetweenAttributes(); } state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME, reconsume, pos); @@ -864,7 +864,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } default: { - if (P::viewingSource) { + if (P::reportErrors) { errSlashNotFollowedByGt(); } state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME, reconsume, pos); @@ -923,7 +923,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '\'': case '=': case '`': { - if (P::viewingSource) { + if (P::reportErrors) { errUnquotedAttributeValOrNull(c); } } @@ -977,7 +977,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '\"': case '\'': case '<': { - if (P::viewingSource) { + if (P::reportErrors) { errQuoteOrLtInAttributeNameOrNull(c); } } @@ -1021,7 +1021,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } default: { - if (P::viewingSource) { + if (P::reportErrors) { errBogusComment(); } clearLongStrBuf(); @@ -1049,7 +1049,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_BREAK(markupdeclarationhyphenloop); } default: { - if (P::viewingSource) { + if (P::reportErrors) { errBogusComment(); } state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos); @@ -1073,7 +1073,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errPrematureEndOfComment(); } emitComment(0, pos); @@ -1194,7 +1194,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '!': { - if (P::viewingSource) { + if (P::reportErrors) { errHyphenHyphenBang(); } appendLongStrBuf(c); @@ -1261,7 +1261,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errPrematureEndOfComment(); } emitComment(1, pos); @@ -1298,7 +1298,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* if (c == nsHtml5Tokenizer::CDATA_LSQB[index]) { appendLongStrBuf(c); } else { - if (P::viewingSource) { + if (P::reportErrors) { errBogusComment(); } state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos); @@ -1474,7 +1474,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } else if (c >= 'A' && c <= 'Z') { firstCharKey = c - 'A'; } else { - if (P::viewingSource) { + if (P::reportErrors) { errNoNamedCharacterMatch(); } emitOrAppendStrBuf(returnState); @@ -1507,7 +1507,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } if (!hilo) { - if (P::viewingSource) { + if (P::reportErrors) { errNoNamedCharacterMatch(); } emitOrAppendStrBuf(returnState); @@ -1578,7 +1578,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } outer_end: ; if (candidate == -1) { - if (P::viewingSource) { + if (P::reportErrors) { errNoNamedCharacterMatch(); } emitOrAppendStrBuf(returnState); @@ -1599,7 +1599,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* ch = strBuf[strBufMark]; } if (ch == '=' || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { - if (P::viewingSource) { + if (P::reportErrors) { errNoNamedCharacterMatch(); } appendStrBufToLongStrBuf(); @@ -1609,11 +1609,11 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } if ((returnState & NS_HTML5TOKENIZER_DATA_AND_RCDATA_MASK)) { - if (P::viewingSource) { + if (P::reportErrors) { errUnescapedAmpersandInterpretedAsCharacterReference(); } } else { - if (P::viewingSource) { + if (P::reportErrors) { errNotSemicolonTerminated(); } } @@ -1690,7 +1690,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* state = P::transition(mViewSource, NS_HTML5TOKENIZER_HANDLE_NCR_VALUE, reconsume, pos); NS_HTML5_BREAK(decimalloop); } else { - if (P::viewingSource) { + if (P::reportErrors) { errNoDigitsInNCR(); } appendStrBuf(';'); @@ -1703,7 +1703,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } else { if (!seenDigits) { - if (P::viewingSource) { + if (P::reportErrors) { errNoDigitsInNCR(); } emitOrAppendStrBuf(returnState); @@ -1714,7 +1714,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* reconsume = true; NS_HTML5_CONTINUE(stateloop); } else { - if (P::viewingSource) { + if (P::reportErrors) { errCharRefLacksSemicolon(); } if (!(returnState & NS_HTML5TOKENIZER_DATA_AND_RCDATA_MASK)) { @@ -1766,7 +1766,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* state = P::transition(mViewSource, NS_HTML5TOKENIZER_HANDLE_NCR_VALUE, reconsume, pos); NS_HTML5_CONTINUE(stateloop); } else { - if (P::viewingSource) { + if (P::reportErrors) { errNoDigitsInNCR(); } appendStrBuf(';'); @@ -1779,7 +1779,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } else { if (!seenDigits) { - if (P::viewingSource) { + if (P::reportErrors) { errNoDigitsInNCR(); } emitOrAppendStrBuf(returnState); @@ -1790,7 +1790,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* reconsume = true; NS_HTML5_CONTINUE(stateloop); } else { - if (P::viewingSource) { + if (P::reportErrors) { errCharRefLacksSemicolon(); } if (!(returnState & NS_HTML5TOKENIZER_DATA_AND_RCDATA_MASK)) { @@ -1839,7 +1839,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* c = checkChar(buf, pos); switch(c) { case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errLtSlashGt(); } cstart = pos + 1; @@ -1848,7 +1848,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } case '\r': { silentCarriageReturn(); - if (P::viewingSource) { + if (P::reportErrors) { errGarbageAfterLtSlash(); } clearLongStrBufAndAppend('\n'); @@ -1857,7 +1857,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } case '\n': { silentLineFeed(); - if (P::viewingSource) { + if (P::reportErrors) { errGarbageAfterLtSlash(); } clearLongStrBufAndAppend('\n'); @@ -1877,7 +1877,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* state = P::transition(mViewSource, NS_HTML5TOKENIZER_TAG_NAME, reconsume, pos); NS_HTML5_CONTINUE(stateloop); } else { - if (P::viewingSource) { + if (P::reportErrors) { errGarbageAfterLtSlash(); } clearLongStrBufAndAppend(c); @@ -2625,7 +2625,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* if (folded == nsHtml5Tokenizer::OCTYPE[index]) { appendLongStrBuf(c); } else { - if (P::viewingSource) { + if (P::reportErrors) { errBogusComment(); } state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos); @@ -2669,7 +2669,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_BREAK(doctypeloop); } default: { - if (P::viewingSource) { + if (P::reportErrors) { errMissingSpaceBeforeDoctypeName(); } state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_DOCTYPE_NAME, reconsume, pos); @@ -2704,7 +2704,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* continue; } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errNamelessDoctype(); } forceQuirks = true; @@ -2868,7 +2868,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_BREAK(afterdoctypepublickeywordloop); } case '\"': { - if (P::viewingSource) { + if (P::reportErrors) { errNoSpaceBetweenDoctypePublicKeywordAndQuote(); } clearLongStrBuf(); @@ -2876,7 +2876,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '\'': { - if (P::viewingSource) { + if (P::reportErrors) { errNoSpaceBetweenDoctypePublicKeywordAndQuote(); } clearLongStrBuf(); @@ -2884,7 +2884,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errExpectedPublicId(); } forceQuirks = true; @@ -2931,7 +2931,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errExpectedPublicId(); } forceQuirks = true; @@ -2961,7 +2961,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_BREAK(doctypepublicidentifierdoublequotedloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errGtInPublicId(); } forceQuirks = true; @@ -3016,7 +3016,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '\"': { - if (P::viewingSource) { + if (P::reportErrors) { errNoSpaceBetweenPublicAndSystemIds(); } clearLongStrBuf(); @@ -3024,7 +3024,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '\'': { - if (P::viewingSource) { + if (P::reportErrors) { errNoSpaceBetweenPublicAndSystemIds(); } clearLongStrBuf(); @@ -3096,7 +3096,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errGtInSystemId(); } forceQuirks = true; @@ -3239,7 +3239,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_BREAK(afterdoctypesystemkeywordloop); } case '\"': { - if (P::viewingSource) { + if (P::reportErrors) { errNoSpaceBetweenDoctypeSystemKeywordAndQuote(); } clearLongStrBuf(); @@ -3247,7 +3247,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '\'': { - if (P::viewingSource) { + if (P::reportErrors) { errNoSpaceBetweenDoctypeSystemKeywordAndQuote(); } clearLongStrBuf(); @@ -3255,7 +3255,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errExpectedPublicId(); } forceQuirks = true; @@ -3302,7 +3302,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_BREAK(beforedoctypesystemidentifierloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errExpectedSystemId(); } forceQuirks = true; @@ -3332,7 +3332,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errGtInSystemId(); } forceQuirks = true; @@ -3372,7 +3372,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* NS_HTML5_CONTINUE(stateloop); } case '>': { - if (P::viewingSource) { + if (P::reportErrors) { errGtInPublicId(); } forceQuirks = true; diff --git a/parser/html/nsHtml5TokenizerCppSupplement.h b/parser/html/nsHtml5TokenizerCppSupplement.h index e62481b38566..9b71c6db2bfe 100644 --- a/parser/html/nsHtml5TokenizerCppSupplement.h +++ b/parser/html/nsHtml5TokenizerCppSupplement.h @@ -64,67 +64,79 @@ nsHtml5Tokenizer::errWarnLtSlashInRcdata() { } +// The null checks below annotated NS_LIKELY are not actually necessary. + void nsHtml5Tokenizer::errUnquotedAttributeValOrNull(PRUnichar c) { - switch (c) { - case '<': - mViewSource->AddErrorToCurrentNode("errUnquotedAttributeLt"); - return; - case '`': - mViewSource->AddErrorToCurrentNode("errUnquotedAttributeGrave"); - return; - case '\'': - case '"': - mViewSource->AddErrorToCurrentNode("errUnquotedAttributeQuote"); - return; - case '=': - mViewSource->AddErrorToCurrentNode("errUnquotedAttributeEquals"); - return; + if (NS_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(PRUnichar c) { - switch (c) { - case '=': - mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartEquals"); - return; - case '<': - mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartLt"); - return; - case '`': - mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartGrave"); - return; + if (NS_LIKELY(mViewSource)) { + switch (c) { + case '=': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartEquals"); + return; + case '<': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartLt"); + return; + case '`': + mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartGrave"); + return; + } } } void nsHtml5Tokenizer::errBadCharBeforeAttributeNameOrNull(PRUnichar c) { - if (c == '<') { - mViewSource->AddErrorToCurrentNode("errBadCharBeforeAttributeNameLt"); - } else if (c == '=') { - errEqualsSignBeforeAttributeName(); - } else if (c != 0xFFFD) { - errQuoteBeforeAttributeName(c); + if (NS_LIKELY(mViewSource)) { + if (c == '<') { + mViewSource->AddErrorToCurrentNode("errBadCharBeforeAttributeNameLt"); + } else if (c == '=') { + errEqualsSignBeforeAttributeName(); + } else if (c != 0xFFFD) { + errQuoteBeforeAttributeName(c); + } } } void nsHtml5Tokenizer::errBadCharAfterLt(PRUnichar c) { - mViewSource->AddErrorToCurrentNode("errBadCharAfterLt"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errBadCharAfterLt"); + } } void nsHtml5Tokenizer::errQuoteOrLtInAttributeNameOrNull(PRUnichar c) { - if (c == '<') { - mViewSource->AddErrorToCurrentNode("errLtInAttributeName"); - } else if (c != 0xFFFD) { - mViewSource->AddErrorToCurrentNode("errQuoteInAttributeName"); + if (NS_LIKELY(mViewSource)) { + if (c == '<') { + mViewSource->AddErrorToCurrentNode("errLtInAttributeName"); + } else if (c != 0xFFFD) { + mViewSource->AddErrorToCurrentNode("errQuoteInAttributeName"); + } } } @@ -177,13 +189,17 @@ nsHtml5Tokenizer::errNcrControlChar(PRUnichar ch) void nsHtml5Tokenizer::errGarbageAfterLtSlash() { - mViewSource->AddErrorToCurrentNode("errGarbageAfterLtSlash"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errGarbageAfterLtSlash"); + } } void nsHtml5Tokenizer::errLtSlashGt() { - mViewSource->AddErrorToCurrentNode("errLtSlashGt"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errLtSlashGt"); + } } void @@ -205,19 +221,25 @@ nsHtml5Tokenizer::errNoDigitsInNCR() void nsHtml5Tokenizer::errGtInSystemId() { - mViewSource->AddErrorToCurrentNode("errGtInSystemId"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errGtInSystemId"); + } } void nsHtml5Tokenizer::errGtInPublicId() { - mViewSource->AddErrorToCurrentNode("errGtInPublicId"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errGtInPublicId"); + } } void nsHtml5Tokenizer::errNamelessDoctype() { - mViewSource->AddErrorToCurrentNode("errNamelessDoctype"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNamelessDoctype"); + } } void @@ -231,7 +253,9 @@ nsHtml5Tokenizer::errConsecutiveHyphens() void nsHtml5Tokenizer::errPrematureEndOfComment() { - mViewSource->AddErrorToCurrentNode("errPrematureEndOfComment"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errPrematureEndOfComment"); + } } void @@ -245,37 +269,49 @@ nsHtml5Tokenizer::errBogusComment() void nsHtml5Tokenizer::errSlashNotFollowedByGt() { - mViewSource->AddErrorToCurrentSlash("errSlashNotFollowedByGt"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentSlash("errSlashNotFollowedByGt"); + } } void nsHtml5Tokenizer::errNoSpaceBetweenAttributes() { - mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenAttributes"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenAttributes"); + } } void nsHtml5Tokenizer::errAttributeValueMissing() { - mViewSource->AddErrorToCurrentNode("errAttributeValueMissing"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errAttributeValueMissing"); + } } void nsHtml5Tokenizer::errEqualsSignBeforeAttributeName() { - mViewSource->AddErrorToCurrentNode("errEqualsSignBeforeAttributeName"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errEqualsSignBeforeAttributeName"); + } } void nsHtml5Tokenizer::errLtGt() { - mViewSource->AddErrorToCurrentNode("errLtGt"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errLtGt"); + } } void nsHtml5Tokenizer::errProcessingInstruction() { - mViewSource->AddErrorToCurrentNode("errProcessingInstruction"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errProcessingInstruction"); + } } void @@ -305,13 +341,17 @@ nsHtml5Tokenizer::errNoNamedCharacterMatch() void nsHtml5Tokenizer::errQuoteBeforeAttributeName(PRUnichar c) { - mViewSource->AddErrorToCurrentNode("errQuoteBeforeAttributeName"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errQuoteBeforeAttributeName"); + } } void nsHtml5Tokenizer::errExpectedPublicId() { - mViewSource->AddErrorToCurrentNode("errExpectedPublicId"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errExpectedPublicId"); + } } void @@ -453,19 +493,25 @@ nsHtml5Tokenizer::errEofInSystemId() void nsHtml5Tokenizer::errExpectedSystemId() { - mViewSource->AddErrorToCurrentNode("errExpectedSystemId"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errExpectedSystemId"); + } } void nsHtml5Tokenizer::errMissingSpaceBeforeDoctypeName() { - mViewSource->AddErrorToCurrentNode("errMissingSpaceBeforeDoctypeName"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errMissingSpaceBeforeDoctypeName"); + } } void nsHtml5Tokenizer::errHyphenHyphenBang() { - mViewSource->AddErrorToCurrentNode("errHyphenHyphenBang"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errHyphenHyphenBang"); + } } void @@ -487,17 +533,23 @@ nsHtml5Tokenizer::errNcrZero() void nsHtml5Tokenizer::errNoSpaceBetweenDoctypeSystemKeywordAndQuote() { - mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenDoctypeSystemKeywordAndQuote"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenDoctypeSystemKeywordAndQuote"); + } } void nsHtml5Tokenizer::errNoSpaceBetweenPublicAndSystemIds() { - mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenPublicAndSystemIds"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenPublicAndSystemIds"); + } } void nsHtml5Tokenizer::errNoSpaceBetweenDoctypePublicKeywordAndQuote() { - mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenDoctypePublicKeywordAndQuote"); + if (NS_LIKELY(mViewSource)) { + mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenDoctypePublicKeywordAndQuote"); + } } diff --git a/parser/html/nsHtml5TokenizerLoopPolicies.h b/parser/html/nsHtml5TokenizerLoopPolicies.h index b098029216f2..70fae2fa396b 100644 --- a/parser/html/nsHtml5TokenizerLoopPolicies.h +++ b/parser/html/nsHtml5TokenizerLoopPolicies.h @@ -38,9 +38,13 @@ #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 viewingSource = false; + static const bool reportErrors = false; static PRInt32 transition(nsHtml5Highlighter* aHighlighter, PRInt32 aState, bool aReconsume, @@ -51,9 +55,13 @@ struct nsHtml5SilentPolicy } }; +/** + * This policy reports the tokenizer transitions to a highlighter. To be used + * when viewing source. + */ struct nsHtml5ViewSourcePolicy { - static const bool viewingSource = true; + static const bool reportErrors = true; static PRInt32 transition(nsHtml5Highlighter* aHighlighter, PRInt32 aState, bool aReconsume, diff --git a/parser/html/nsHtml5TreeBuilderHSupplement.h b/parser/html/nsHtml5TreeBuilderHSupplement.h index c0b5501aa588..0614e7c61b4f 100644 --- a/parser/html/nsHtml5TreeBuilderHSupplement.h +++ b/parser/html/nsHtml5TreeBuilderHSupplement.h @@ -58,6 +58,29 @@ */ void documentMode(nsHtml5DocumentMode m); + /** + * 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 the same mechanism in order + * to avoid having to have duplicate code paths for on-the-main-thread and + * off-the-main-thread tree builder instances.) + */ nsIContent** AllocateContentHandle(); void accumulateCharactersForced(const PRUnichar* aBuf, PRInt32 aStart, PRInt32 aLength) diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index df3c0447473a..b85e960deab2 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -905,6 +905,8 @@ nsHtml5TreeOpExecutor::GetViewSourceBaseURI() 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; } } diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index 8507159a1d96..bfae5c444a6b 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -715,6 +715,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent* node = *(mOne.node); PRUnichar* str = mTwo.unicharPtr; nsDependentString depStr(str); + // See viewsource.css for the possible classes nsAutoString klass; node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass); if (!klass.IsEmpty()) { @@ -760,8 +761,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &openingExecutesScript); - NS_ENSURE_SUCCESS(rv, NS_OK); - if (openingExecutesScript) { + if (NS_FAILED(rv) || openingExecutesScript) { return NS_OK; } @@ -795,6 +795,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, char* msgId = mTwo.charPtr; nsCOMPtr atom = Reget(mThree.atom); nsCOMPtr otherAtom = Reget(mFour.atom); + // See viewsource.css for the possible classes in addition to "error". nsAutoString klass; node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass); if (!klass.IsEmpty()) {