зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1410848 - Use RAII with nsHtml5TreeOpExecutor::mFlushState. r=smaug.
MozReview-Commit-ID: 3a1tyYGT8u5
This commit is contained in:
Родитель
45d7cc2fc4
Коммит
24aae439f6
|
@ -0,0 +1,30 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=78: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef nsHtml5AutoPauseUpdate_h
|
||||
#define nsHtml5AutoPauseUpdate_h
|
||||
|
||||
class MOZ_RAII nsHtml5AutoPauseUpdate final
|
||||
{
|
||||
private:
|
||||
RefPtr<nsHtml5DocumentBuilder> mBuilder;
|
||||
|
||||
public:
|
||||
explicit nsHtml5AutoPauseUpdate(nsHtml5DocumentBuilder* aBuilder)
|
||||
: mBuilder(aBuilder)
|
||||
{
|
||||
mBuilder->EndDocUpdate();
|
||||
}
|
||||
~nsHtml5AutoPauseUpdate()
|
||||
{
|
||||
// Something may have terminated the parser during the update pause.
|
||||
if (!mBuilder->IsComplete()) {
|
||||
mBuilder->BeginDocUpdate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // nsHtml5AutoPauseUpdate_h
|
|
@ -18,7 +18,6 @@ enum eHtml5FlushState {
|
|||
eNotFlushing = 0, // not flushing
|
||||
eInFlush = 1, // the Flush() method is on the call stack
|
||||
eInDocUpdate = 2, // inside an update batch on the document
|
||||
eNotifying = 3 // flushing pending append notifications
|
||||
};
|
||||
|
||||
class nsHtml5DocumentBuilder : public nsContentSink
|
||||
|
@ -67,28 +66,45 @@ public:
|
|||
return mBroken;
|
||||
}
|
||||
|
||||
inline bool IsComplete()
|
||||
{
|
||||
return !mParser;
|
||||
}
|
||||
|
||||
inline void BeginDocUpdate()
|
||||
{
|
||||
NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
|
||||
NS_PRECONDITION(mParser, "Started update without parser.");
|
||||
MOZ_RELEASE_ASSERT(IsInFlush(), "Tried to double-open doc update.");
|
||||
MOZ_RELEASE_ASSERT(mParser, "Started doc update without parser.");
|
||||
mFlushState = eInDocUpdate;
|
||||
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
inline void EndDocUpdate()
|
||||
{
|
||||
NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
|
||||
if (mFlushState == eInDocUpdate) {
|
||||
mFlushState = eInFlush;
|
||||
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(IsInDocUpdate(),
|
||||
"Tried to end doc update without one open.");
|
||||
mFlushState = eInFlush;
|
||||
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
bool IsInDocUpdate()
|
||||
inline void BeginFlush()
|
||||
{
|
||||
return mFlushState == eInDocUpdate;
|
||||
MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
|
||||
"Tried to start a flush when already flushing.");
|
||||
MOZ_RELEASE_ASSERT(mParser, "Started a flush without parser.");
|
||||
mFlushState = eInFlush;
|
||||
}
|
||||
|
||||
inline void EndFlush()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(IsInFlush(), "Tried to end flush when not flushing.");
|
||||
mFlushState = eNotFlushing;
|
||||
}
|
||||
|
||||
inline bool IsInDocUpdate() { return mFlushState == eInDocUpdate; }
|
||||
|
||||
inline bool IsInFlush() { return mFlushState == eInFlush; }
|
||||
|
||||
void SetDocumentCharsetAndSource(NotNull<const Encoding*> aEncoding,
|
||||
int32_t aCharsetSource);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ nsHtml5OplessBuilder::~nsHtml5OplessBuilder()
|
|||
void
|
||||
nsHtml5OplessBuilder::Start()
|
||||
{
|
||||
mFlushState = eInFlush;
|
||||
BeginFlush();
|
||||
BeginDocUpdate();
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ void
|
|||
nsHtml5OplessBuilder::Finish()
|
||||
{
|
||||
EndDocUpdate();
|
||||
EndFlush();
|
||||
DropParserAndPerfHint();
|
||||
mScriptLoader = nullptr;
|
||||
mDocument = nullptr;
|
||||
|
@ -39,7 +40,6 @@ nsHtml5OplessBuilder::Finish()
|
|||
mDocumentURI = nullptr;
|
||||
mDocShell = nullptr;
|
||||
mOwnedElements.Clear();
|
||||
mFlushState = eNotFlushing;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -226,6 +226,9 @@ class nsHtml5SpeculativeLoad {
|
|||
void Perform(nsHtml5TreeOpExecutor* aExecutor);
|
||||
|
||||
private:
|
||||
nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete;
|
||||
nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete;
|
||||
|
||||
eHtml5SpeculativeLoad mOpCode;
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "nsIViewSourceChannel.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "mozilla/IdleTaskRunner.h"
|
||||
#include "nsHtml5AutoPauseUpdate.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -57,6 +58,43 @@ class nsHtml5ExecutorReflusher : public Runnable
|
|||
}
|
||||
};
|
||||
|
||||
class MOZ_RAII nsHtml5AutoFlush final
|
||||
{
|
||||
private:
|
||||
RefPtr<nsHtml5TreeOpExecutor> mExecutor;
|
||||
size_t mOpsToRemove;
|
||||
|
||||
public:
|
||||
explicit nsHtml5AutoFlush(nsHtml5TreeOpExecutor* aExecutor)
|
||||
: mExecutor(aExecutor)
|
||||
, mOpsToRemove(aExecutor->OpQueueLength())
|
||||
{
|
||||
mExecutor->BeginFlush();
|
||||
mExecutor->BeginDocUpdate();
|
||||
}
|
||||
~nsHtml5AutoFlush()
|
||||
{
|
||||
if (mExecutor->IsInDocUpdate()) {
|
||||
mExecutor->EndDocUpdate();
|
||||
} else {
|
||||
// We aren't in an update if nsHtml5AutoPauseUpdate
|
||||
// caused something to terminate the parser.
|
||||
MOZ_RELEASE_ASSERT(
|
||||
mExecutor->IsComplete(),
|
||||
"How do we have mParser but the doc update isn't open?");
|
||||
}
|
||||
mExecutor->EndFlush();
|
||||
mExecutor->RemoveFromStartOfOpQueue(mOpsToRemove);
|
||||
}
|
||||
void SetNumberOfOpsToRemove(size_t aOpsToRemove)
|
||||
{
|
||||
MOZ_ASSERT(aOpsToRemove < mOpsToRemove,
|
||||
"Requested partial clearing of op queue but the number to clear "
|
||||
"wasn't less than the length of the queue.");
|
||||
mOpsToRemove = aOpsToRemove;
|
||||
}
|
||||
};
|
||||
|
||||
static mozilla::LinkedList<nsHtml5TreeOpExecutor>* gBackgroundFlushList = nullptr;
|
||||
StaticRefPtr<IdleTaskRunner> gBackgroundFlushRunner;
|
||||
|
||||
|
@ -77,7 +115,7 @@ nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor()
|
|||
nsHtml5TreeOpExecutor::~nsHtml5TreeOpExecutor()
|
||||
{
|
||||
if (gBackgroundFlushList && isInList()) {
|
||||
mOpQueue.Clear();
|
||||
ClearOpQueue();
|
||||
removeFrom(*gBackgroundFlushList);
|
||||
if (gBackgroundFlushList->isEmpty()) {
|
||||
delete gBackgroundFlushList;
|
||||
|
@ -298,9 +336,9 @@ nsHtml5TreeOpExecutor::FlushSpeculativeLoads()
|
|||
{
|
||||
nsTArray<nsHtml5SpeculativeLoad> speculativeLoadQueue;
|
||||
mStage.MoveSpeculativeLoadsTo(speculativeLoadQueue);
|
||||
const nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements();
|
||||
const nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length();
|
||||
for (nsHtml5SpeculativeLoad* iter = const_cast<nsHtml5SpeculativeLoad*>(start);
|
||||
nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements();
|
||||
nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length();
|
||||
for (nsHtml5SpeculativeLoad* iter = start;
|
||||
iter < end;
|
||||
++iter) {
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
|
@ -368,7 +406,7 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
|
|||
for (;;) {
|
||||
if (!mParser) {
|
||||
// Parse has terminated.
|
||||
mOpQueue.Clear(); // clear in order to be able to assert in destructor
|
||||
ClearOpQueue(); // clear in order to be able to assert in destructor
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -395,18 +433,20 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
|
|||
|
||||
if (mReadingFromStage) {
|
||||
nsTArray<nsHtml5SpeculativeLoad> speculativeLoadQueue;
|
||||
MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
|
||||
"mOpQueue modified during flush.");
|
||||
mStage.MoveOpsAndSpeculativeLoadsTo(mOpQueue, speculativeLoadQueue);
|
||||
// Make sure speculative loads never start after the corresponding
|
||||
// normal loads for the same URLs.
|
||||
const nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements();
|
||||
const nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length();
|
||||
for (nsHtml5SpeculativeLoad* iter = (nsHtml5SpeculativeLoad*)start;
|
||||
nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements();
|
||||
nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length();
|
||||
for (nsHtml5SpeculativeLoad* iter = start;
|
||||
iter < end;
|
||||
++iter) {
|
||||
iter->Perform(this);
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// An extension terminated the parser from a HTTP observer.
|
||||
mOpQueue.Clear(); // clear in order to be able to assert in destructor
|
||||
ClearOpQueue(); // clear in order to be able to assert in destructor
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -416,7 +456,7 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
|
|||
// URLs.
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// An extension terminated the parser from a HTTP observer.
|
||||
mOpQueue.Clear(); // clear in order to be able to assert in destructor
|
||||
ClearOpQueue(); // clear in order to be able to assert in destructor
|
||||
return;
|
||||
}
|
||||
// Not sure if this grip is still needed, but previously, the code
|
||||
|
@ -439,57 +479,46 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
|
|||
return;
|
||||
}
|
||||
|
||||
mFlushState = eInFlush;
|
||||
|
||||
nsIContent* scriptElement = nullptr;
|
||||
bool interrupted = false;
|
||||
|
||||
BeginDocUpdate();
|
||||
|
||||
uint32_t numberOfOpsToFlush = mOpQueue.Length();
|
||||
{
|
||||
// autoFlush clears mOpQueue in its destructor unless
|
||||
// SetNumberOfOpsToRemove is called first, in which case only
|
||||
// some ops from the start of the queue are cleared.
|
||||
nsHtml5AutoFlush autoFlush(this);
|
||||
|
||||
const nsHtml5TreeOperation* first = mOpQueue.Elements();
|
||||
const nsHtml5TreeOperation* last = first + numberOfOpsToFlush - 1;
|
||||
for (nsHtml5TreeOperation* iter = const_cast<nsHtml5TreeOperation*>(first);;) {
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// The previous tree op caused a call to nsIParser::Terminate().
|
||||
break;
|
||||
}
|
||||
NS_ASSERTION(mFlushState == eInDocUpdate,
|
||||
"Tried to perform tree op outside update batch.");
|
||||
nsresult rv = iter->Perform(this, &scriptElement, &interrupted);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBroken(rv);
|
||||
break;
|
||||
nsHtml5TreeOperation* first = mOpQueue.Elements();
|
||||
nsHtml5TreeOperation* last = first + mOpQueue.Length() - 1;
|
||||
for (nsHtml5TreeOperation* iter = first;; ++iter) {
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// The previous tree op caused a call to nsIParser::Terminate().
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(IsInDocUpdate(),
|
||||
"Tried to perform tree op outside update batch.");
|
||||
nsresult rv = iter->Perform(this, &scriptElement, &interrupted);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBroken(rv);
|
||||
break;
|
||||
}
|
||||
|
||||
// Be sure not to check the deadline if the last op was just performed.
|
||||
if (MOZ_UNLIKELY(iter == last)) {
|
||||
break;
|
||||
} else if (MOZ_UNLIKELY(interrupted) ||
|
||||
MOZ_UNLIKELY(nsContentSink::DidProcessATokenImpl() ==
|
||||
NS_ERROR_HTMLPARSER_INTERRUPTED)) {
|
||||
|
||||
autoFlush.SetNumberOfOpsToRemove((iter - first) + 1);
|
||||
|
||||
nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Be sure not to check the deadline if the last op was just performed.
|
||||
if (MOZ_UNLIKELY(iter == last)) {
|
||||
break;
|
||||
} else if (MOZ_UNLIKELY(interrupted) ||
|
||||
MOZ_UNLIKELY(nsContentSink::DidProcessATokenImpl() ==
|
||||
NS_ERROR_HTMLPARSER_INTERRUPTED)) {
|
||||
mOpQueue.RemoveElementsAt(0, (iter - first) + 1);
|
||||
|
||||
EndDocUpdate();
|
||||
|
||||
mFlushState = eNotFlushing;
|
||||
|
||||
#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
|
||||
printf("REFLUSH SCHEDULED (executing ops): %d\n",
|
||||
++sTimesFlushLoopInterrupted);
|
||||
#endif
|
||||
nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync();
|
||||
return;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
mOpQueue.Clear();
|
||||
|
||||
EndDocUpdate();
|
||||
|
||||
mFlushState = eNotFlushing;
|
||||
} // end autoFlush
|
||||
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// The parse ended already.
|
||||
|
@ -526,7 +555,7 @@ nsHtml5TreeOpExecutor::FlushDocumentWrite()
|
|||
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// The parse has ended.
|
||||
mOpQueue.Clear(); // clear in order to be able to assert in destructor
|
||||
ClearOpQueue(); // clear in order to be able to assert in destructor
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -535,15 +564,13 @@ nsHtml5TreeOpExecutor::FlushDocumentWrite()
|
|||
return rv;
|
||||
}
|
||||
|
||||
mFlushState = eInFlush;
|
||||
|
||||
// avoid crashing near EOF
|
||||
RefPtr<nsHtml5TreeOpExecutor> kungFuDeathGrip(this);
|
||||
RefPtr<nsParserBase> parserKungFuDeathGrip(mParser);
|
||||
mozilla::Unused << parserKungFuDeathGrip; // Intentionally not used within function
|
||||
|
||||
NS_ASSERTION(!mReadingFromStage,
|
||||
"Got doc write flush when reading from stage");
|
||||
MOZ_RELEASE_ASSERT(!mReadingFromStage,
|
||||
"Got doc write flush when reading from stage");
|
||||
|
||||
#ifdef DEBUG
|
||||
mStage.AssertEmpty();
|
||||
|
@ -551,34 +578,31 @@ nsHtml5TreeOpExecutor::FlushDocumentWrite()
|
|||
|
||||
nsIContent* scriptElement = nullptr;
|
||||
bool interrupted = false;
|
||||
|
||||
BeginDocUpdate();
|
||||
|
||||
uint32_t numberOfOpsToFlush = mOpQueue.Length();
|
||||
{
|
||||
// autoFlush clears mOpQueue in its destructor.
|
||||
nsHtml5AutoFlush autoFlush(this);
|
||||
|
||||
const nsHtml5TreeOperation* start = mOpQueue.Elements();
|
||||
const nsHtml5TreeOperation* end = start + numberOfOpsToFlush;
|
||||
for (nsHtml5TreeOperation* iter = const_cast<nsHtml5TreeOperation*>(start);
|
||||
|
||||
nsHtml5TreeOperation* start = mOpQueue.Elements();
|
||||
nsHtml5TreeOperation* end = start + mOpQueue.Length();
|
||||
for (nsHtml5TreeOperation* iter = start;
|
||||
iter < end;
|
||||
++iter) {
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// The previous tree op caused a call to nsIParser::Terminate().
|
||||
break;
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// The previous tree op caused a call to nsIParser::Terminate().
|
||||
return rv;
|
||||
}
|
||||
NS_ASSERTION(IsInDocUpdate(),
|
||||
"Tried to perform tree op outside update batch.");
|
||||
rv = iter->Perform(this, &scriptElement, &interrupted);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBroken(rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(mFlushState == eInDocUpdate,
|
||||
"Tried to perform tree op outside update batch.");
|
||||
rv = iter->Perform(this, &scriptElement, &interrupted);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBroken(rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mOpQueue.Clear();
|
||||
|
||||
EndDocUpdate();
|
||||
|
||||
mFlushState = eNotFlushing;
|
||||
} // autoFlush
|
||||
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// Ending the doc update caused a call to nsIParser::Terminate().
|
||||
|
@ -617,7 +641,7 @@ nsHtml5TreeOpExecutor::StartLayout(bool* aInterrupted) {
|
|||
return;
|
||||
}
|
||||
|
||||
EndDocUpdate();
|
||||
nsHtml5AutoPauseUpdate autoPause(this);
|
||||
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// got terminate
|
||||
|
@ -628,8 +652,6 @@ nsHtml5TreeOpExecutor::StartLayout(bool* aInterrupted) {
|
|||
|
||||
if (mParser) {
|
||||
*aInterrupted = !GetParser()->IsParserEnabled();
|
||||
|
||||
BeginDocUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -637,12 +659,10 @@ void
|
|||
nsHtml5TreeOpExecutor::PauseDocUpdate(bool* aInterrupted) {
|
||||
// Pausing the document update allows JS to run, and potentially block
|
||||
// further parsing.
|
||||
EndDocUpdate();
|
||||
nsHtml5AutoPauseUpdate autoPause(this);
|
||||
|
||||
if (MOZ_LIKELY(mParser)) {
|
||||
*aInterrupted = !GetParser()->IsParserEnabled();
|
||||
|
||||
BeginDocUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -687,8 +707,9 @@ nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement)
|
|||
NS_ASSERTION(!block, "Defer or async script tried to block.");
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mFlushState == eNotFlushing, "Tried to run script when flushing.");
|
||||
|
||||
MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
|
||||
"Tried to run script while flushing.");
|
||||
|
||||
mReadingFromStage = false;
|
||||
|
||||
|
@ -726,8 +747,7 @@ nsHtml5TreeOpExecutor::NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding,
|
|||
int32_t aSource,
|
||||
uint32_t aLineNumber)
|
||||
{
|
||||
EndDocUpdate();
|
||||
|
||||
nsHtml5AutoPauseUpdate autoPause(this);
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// got terminate
|
||||
return;
|
||||
|
@ -760,8 +780,6 @@ nsHtml5TreeOpExecutor::NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding,
|
|||
}
|
||||
|
||||
GetParser()->ContinueAfterFailedCharsetSwitch();
|
||||
|
||||
BeginDocUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -825,12 +843,31 @@ nsHtml5TreeOpExecutor::GetParser()
|
|||
void
|
||||
nsHtml5TreeOpExecutor::MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue)
|
||||
{
|
||||
NS_PRECONDITION(mFlushState == eNotFlushing, "mOpQueue modified during tree op execution.");
|
||||
MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
|
||||
"Ops added to mOpQueue during tree op execution.");
|
||||
mOpQueue.AppendElements(Move(aOpQueue));
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, int32_t aLine)
|
||||
nsHtml5TreeOpExecutor::ClearOpQueue()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
|
||||
"mOpQueue cleared during tree op execution.");
|
||||
mOpQueue.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::RemoveFromStartOfOpQueue(size_t aNumberOfOpsToRemove)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
|
||||
"Ops removed from mOpQueue during tree op execution.");
|
||||
mOpQueue.RemoveElementsAt(0, aNumberOfOpsToRemove);
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::InitializeDocWriteParserState(
|
||||
nsAHtml5TreeBuilderState* aState,
|
||||
int32_t aLine)
|
||||
{
|
||||
GetParser()->InitializeDocWriteParserState(aState, aLine);
|
||||
}
|
||||
|
|
|
@ -196,11 +196,6 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
|
|||
|
||||
void ComplainAboutBogusProtocolCharset(nsIDocument* aDoc);
|
||||
|
||||
bool IsComplete()
|
||||
{
|
||||
return !mParser;
|
||||
}
|
||||
|
||||
bool HasStarted()
|
||||
{
|
||||
return mStarted;
|
||||
|
@ -225,7 +220,13 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
|
|||
* queue unconditionally. (This is for the main thread case.)
|
||||
*/
|
||||
virtual void MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue) override;
|
||||
|
||||
|
||||
void ClearOpQueue();
|
||||
|
||||
void RemoveFromStartOfOpQueue(size_t aNumberOfOpsToRemove);
|
||||
|
||||
inline size_t OpQueueLength() { return mOpQueue.Length(); }
|
||||
|
||||
nsHtml5TreeOpStage* GetStage()
|
||||
{
|
||||
return &mStage;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "nsIHTMLDocument.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsTextNode.h"
|
||||
#include "nsHtml5AutoPauseUpdate.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -74,29 +75,6 @@ class MOZ_STACK_CLASS nsHtml5OtherDocUpdate {
|
|||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to temporary break out of the document update batch. Use this
|
||||
* with caution as this will cause blocked scripts to run.
|
||||
*/
|
||||
class MOZ_RAII mozAutoPauseContentUpdate final
|
||||
{
|
||||
public:
|
||||
explicit mozAutoPauseContentUpdate(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
{
|
||||
MOZ_ASSERT(mDocument);
|
||||
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
~mozAutoPauseContentUpdate()
|
||||
{
|
||||
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
nsHtml5TreeOperation::nsHtml5TreeOperation()
|
||||
: mOpCode(eTreeOpUninitialized)
|
||||
{
|
||||
|
@ -442,7 +420,7 @@ nsHtml5TreeOperation::CreateHTMLElement(
|
|||
if (willExecuteScript) { // This will cause custom element constructors to run
|
||||
AutoSetThrowOnDynamicMarkupInsertionCounter
|
||||
throwOnDynamicMarkupInsertionCounter(document);
|
||||
mozAutoPauseContentUpdate autoPauseContentUpdate(document);
|
||||
nsHtml5AutoPauseUpdate autoPauseContentUpdate(aBuilder);
|
||||
{
|
||||
nsAutoMicroTask mt;
|
||||
}
|
||||
|
|
|
@ -549,6 +549,9 @@ class nsHtml5TreeOperation final {
|
|||
bool* aInterrupted);
|
||||
|
||||
private:
|
||||
nsHtml5TreeOperation(const nsHtml5TreeOperation&) = delete;
|
||||
nsHtml5TreeOperation& operator=(const nsHtml5TreeOperation&) = delete;
|
||||
|
||||
// possible optimization:
|
||||
// Make the queue take items the size of pointer and make the op code
|
||||
// decide how many operands it dequeues after it.
|
||||
|
|
Загрузка…
Ссылка в новой задаче