diff options
Diffstat (limited to 'parser/html/nsHtml5TokenizerCppSupplement.h')
-rw-r--r-- | parser/html/nsHtml5TokenizerCppSupplement.h | 500 |
1 files changed, 500 insertions, 0 deletions
diff --git a/parser/html/nsHtml5TokenizerCppSupplement.h b/parser/html/nsHtml5TokenizerCppSupplement.h new file mode 100644 index 0000000000..e85d70daab --- /dev/null +++ b/parser/html/nsHtml5TokenizerCppSupplement.h @@ -0,0 +1,500 @@ +/* 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 (attributes) { + // There is an open issue for properly specifying this: + // https://github.com/whatwg/html/issues/3257 + attributes->setDuplicateAttributeError(); + } + + 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"); + } +} |