Backed out changeset aa30bc1b369b (bug 1763076) for causing assertion failure in parser/html/nsHtml5TreeOpExecutor.cpp CLOSED TREE

This commit is contained in:
Molnar Sandor
2022-04-19 14:41:03 +03:00
parent 68cac12581
commit fc629f63f4
16 changed files with 81 additions and 293 deletions

View File

@@ -12,7 +12,6 @@
#include <new>
#include <type_traits>
#include <utility>
#include "ErrorList.h"
#include "GeckoProfiler.h"
#include "js/GCAPI.h"
#include "mozilla/ArrayIterator.h"
@@ -776,15 +775,9 @@ nsresult nsHtml5StreamParser::SniffStreamBytes(Span<const uint8_t> aFromSegment,
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();
mTokenizer->FlushViewSource();
}
mTreeBuilder->Flush();
// Encoding committer flushes the ops on the main thread.
mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex);
@@ -930,16 +923,10 @@ nsresult nsHtml5StreamParser::WriteStreamBytes(
mCharsetSource = source;
if (encoding != mEncoding) {
mEncoding = encoding;
nsresult rv = ReDecodeLocalFile();
if (NS_FAILED(rv)) {
return rv;
}
ReDecodeLocalFile();
} else {
MOZ_ASSERT(mEncoding == UTF_8_ENCODING);
nsresult rv = CommitLocalFileToEncoding();
if (NS_FAILED(rv)) {
return rv;
}
CommitLocalFileToEncoding();
}
}
return NS_OK;
@@ -947,7 +934,7 @@ nsresult nsHtml5StreamParser::WriteStreamBytes(
}
}
[[nodiscard]] nsresult nsHtml5StreamParser::ReDecodeLocalFile() {
void nsHtml5StreamParser::ReDecodeLocalFile() {
MOZ_ASSERT(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset);
MOZ_ASSERT(mFirstBufferOfMetaScan);
MOZ_ASSERT(mCharsetSource == kCharsetFromFinalAutoDetectionFile ||
@@ -981,19 +968,12 @@ nsresult nsHtml5StreamParser::WriteStreamBytes(
}
if (mMode == VIEW_SOURCE_HTML) {
auto r = mTokenizer->FlushViewSource();
if (r.isErr()) {
return r.unwrapErr();
}
mTokenizer->FlushViewSource();
}
auto r = mTreeBuilder->Flush();
if (r.isErr()) {
return r.unwrapErr();
}
return NS_OK;
mTreeBuilder->Flush();
}
[[nodiscard]] nsresult nsHtml5StreamParser::CommitLocalFileToEncoding() {
void nsHtml5StreamParser::CommitLocalFileToEncoding() {
MOZ_ASSERT(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset);
MOZ_ASSERT(mFirstBufferOfMetaScan);
mDecodingLocalFileWithoutTokenizing = false;
@@ -1019,16 +999,9 @@ nsresult nsHtml5StreamParser::WriteStreamBytes(
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();
}
mTokenizer->FlushViewSource();
}
auto r = mTreeBuilder->Flush();
if (r.isErr()) {
return r.unwrapErr();
}
return NS_OK;
mTreeBuilder->Flush();
}
class MaybeRunCollector : public Runnable {
@@ -1136,10 +1109,7 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) {
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());
}
mTreeBuilder->Flush();
} else if (mMode == VIEW_SOURCE_PLAIN) {
nsAutoString viewSourceTitle;
CopyUTF8toUTF16(mViewSourceTitle, viewSourceTitle);
@@ -1150,10 +1120,7 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) {
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());
}
mTreeBuilder->Flush();
} 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.
@@ -1163,10 +1130,7 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) {
}
// Flush the ops to put them where ContinueAfterScriptsOrEncodingCommitment
// can find them.
auto r = mTokenizer->FlushViewSource();
if (r.isErr()) {
return mExecutor->MarkAsBroken(r.unwrapErr());
}
mTokenizer->FlushViewSource();
}
/*
@@ -1292,11 +1256,7 @@ void nsHtml5StreamParser::DoStopRequest() {
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false);
for (auto&& buffer : mBufferedBytes) {
nsresult rv = WriteStreamBytes(buffer);
if (NS_FAILED(rv)) {
MarkAsBroken(rv);
return;
}
Unused << WriteStreamBytes(buffer);
}
} else if (!mUnicodeDecoder) {
nsresult rv;
@@ -1356,20 +1316,12 @@ void nsHtml5StreamParser::DoStopRequest() {
mCharsetSource = source;
if (encoding != mEncoding) {
mEncoding = encoding;
nsresult rv = ReDecodeLocalFile();
if (NS_FAILED(rv)) {
MarkAsBroken(rv);
return;
}
ReDecodeLocalFile();
DoStopRequest();
return;
}
MOZ_ASSERT(mEncoding == UTF_8_ENCODING);
nsresult rv = CommitLocalFileToEncoding();
if (NS_FAILED(rv)) {
MarkAsBroken(rv);
return;
}
CommitLocalFileToEncoding();
}
break;
}
@@ -1781,23 +1733,6 @@ void nsHtml5StreamParser::PostLoadFlusher() {
if (NS_FAILED(DispatchToMain(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() {
@@ -1812,15 +1747,9 @@ void nsHtml5StreamParser::FlushTreeOpsAndDisarmTimer() {
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());
mTokenizer->FlushViewSource();
}
mTreeBuilder->Flush();
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
if (NS_FAILED(DispatchToMain(runnable.forget()))) {
NS_WARNING("failed to dispatch executor flush event");
@@ -2235,17 +2164,9 @@ bool nsHtml5StreamParser::ProcessLookingForMetaCharset(bool aEof) {
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;
mTokenizer->FlushViewSource();
}
mTreeBuilder->Flush();
if (mEncoding != needsEncodingSwitchTo) {
// Speculation failed
@@ -2284,11 +2205,7 @@ bool nsHtml5StreamParser::ProcessLookingForMetaCharset(bool aEof) {
"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;
}
WriteStreamBytes(buffer);
}
}
} else if (!mLookingForMetaCharset && !mDecodingLocalFileWithoutTokenizing) {
@@ -2313,17 +2230,9 @@ bool nsHtml5StreamParser::ProcessLookingForMetaCharset(bool aEof) {
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;
mTokenizer->FlushViewSource();
}
mTreeBuilder->Flush();
}
}
return rewound;
@@ -2446,9 +2355,7 @@ void nsHtml5StreamParser::ParseAvailableData() {
} else {
mTreeBuilder->StreamEnded();
if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
if (!mTokenizer->EndViewSource()) {
MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
}
mTokenizer->EndViewSource();
}
}
}
@@ -2489,17 +2396,9 @@ void nsHtml5StreamParser::ParseAvailableData() {
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;
mTokenizer->FlushViewSource();
}
mTreeBuilder->Flush();
} else {
FlushTreeOpsAndDisarmTimer();
}
@@ -2559,10 +2458,7 @@ void nsHtml5StreamParser::ContinueAfterScriptsOrEncodingCommitment(
// 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;
}
mExecutor->TakeOpsFromStage();
} else {
#ifdef DEBUG
mExecutor->AssertStageEmpty();
@@ -2599,10 +2495,7 @@ void nsHtml5StreamParser::ContinueAfterScriptsOrEncodingCommitment(
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;
}
speculation->FlushToSink(mExecutor);
MOZ_ASSERT(!mExecutor->IsScriptExecuting(),
"ParseUntilBlocked() was supposed to ensure we don't come "
"here when scripts are executing.");
@@ -2677,10 +2570,7 @@ void nsHtml5StreamParser::ContinueAfterScriptsOrEncodingCommitment(
} 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;
}
mSpeculations.ElementAt(0)->FlushToSink(mExecutor);
MOZ_ASSERT(!mExecutor->IsScriptExecuting(),
"ParseUntilBlocked() was supposed to ensure we don't come "
"here when scripts are executing.");
@@ -2699,11 +2589,7 @@ void nsHtml5StreamParser::ContinueAfterScriptsOrEncodingCommitment(
// 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->Flush(true);
mTreeBuilder->SetOpSink(mExecutor->GetStage());
}
mExecutor->StartReadingFromStage();
@@ -2799,17 +2685,8 @@ void nsHtml5StreamParser::TimerFlush() {
}
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()) {
mTreeBuilder->Flush(); // delete useless ops
if (mTokenizer->FlushViewSource()) {
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
if (NS_FAILED(DispatchToMain(runnable.forget()))) {
NS_WARNING("failed to dispatch executor flush event");
@@ -2818,12 +2695,7 @@ void nsHtml5StreamParser::TimerFlush() {
} 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()) {
if (mTreeBuilder->Flush(true)) {
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
if (NS_FAILED(DispatchToMain(runnable.forget()))) {
NS_WARNING("failed to dispatch executor flush event");
@@ -2838,12 +2710,8 @@ void nsHtml5StreamParser::MarkAsBroken(nsresult aRv) {
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");
}
mozilla::DebugOnly<bool> hadOps = mTreeBuilder->Flush(false);
MOZ_ASSERT(hadOps, "Should have had the markAsBroken op!");
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
if (NS_FAILED(DispatchToMain(runnable.forget()))) {
NS_WARNING("failed to dispatch executor flush event");