зеркало из https://github.com/mozilla/gecko-dev.git
Bug 551344 part 1 - Address sicking's review comments in nsHtml5Parser.cpp. r=jonas.
This commit is contained in:
Родитель
21b6216e1b
Коммит
9986f24b36
|
@ -75,8 +75,10 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5Parser)
|
|||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5Parser)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5Parser)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mExecutor, nsIContentSink)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mStreamParser, nsIStreamListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mExecutor,
|
||||
nsIContentSink)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mStreamParser,
|
||||
nsIStreamListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5Parser)
|
||||
|
@ -111,7 +113,7 @@ nsHtml5Parser::SetContentSink(nsIContentSink* aSink)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP_(nsIContentSink*)
|
||||
nsHtml5Parser::GetContentSink(void)
|
||||
nsHtml5Parser::GetContentSink()
|
||||
{
|
||||
return static_cast<nsIContentSink*> (mExecutor);
|
||||
}
|
||||
|
@ -136,13 +138,15 @@ nsHtml5Parser::SetCommand(eParserCommands aParserCommand)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsHtml5Parser::SetDocumentCharset(const nsACString& aCharset, PRInt32 aCharsetSource)
|
||||
nsHtml5Parser::SetDocumentCharset(const nsACString& aCharset,
|
||||
PRInt32 aCharsetSource)
|
||||
{
|
||||
NS_PRECONDITION(!mExecutor->HasStarted(),
|
||||
"Document charset set too late.");
|
||||
NS_PRECONDITION(mStreamParser, "Tried to set charset on a script-only parser.");
|
||||
NS_PRECONDITION(mStreamParser, "Setting charset on a script-only parser.");
|
||||
mStreamParser->SetDocumentCharset(aCharset, aCharsetSource);
|
||||
mExecutor->SetDocumentCharsetAndSource((nsACString&)aCharset, aCharsetSource);
|
||||
mExecutor->SetDocumentCharsetAndSource((nsACString&)aCharset,
|
||||
aCharsetSource);
|
||||
mCharsetSource = aCharsetSource; // used for the document.open() case only
|
||||
}
|
||||
|
||||
|
@ -218,9 +222,9 @@ nsHtml5Parser::Parse(nsIURI* aURL, // legacy parameter; ignored
|
|||
* The document won't be ready for it until OnStartRequest!
|
||||
*/
|
||||
NS_PRECONDITION(!mExecutor->HasStarted(),
|
||||
"Tried to start parse without initializing the parser properly.");
|
||||
"Tried to start parse without initializing the parser.");
|
||||
NS_PRECONDITION(mStreamParser,
|
||||
"Can't call this variant of Parse() on script-created parser");
|
||||
"Can't call this Parse() variant on script-created parser");
|
||||
mStreamParser->SetObserver(aObserver);
|
||||
mExecutor->SetStreamParser(mStreamParser);
|
||||
mExecutor->SetParser(this);
|
||||
|
@ -235,7 +239,8 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
|||
PRBool aLastCall,
|
||||
nsDTDMode aMode) // ignored
|
||||
{
|
||||
NS_PRECONDITION(!mExecutor->IsFragmentMode(), "Document.write called in fragment mode!");
|
||||
NS_PRECONDITION(!mExecutor->IsFragmentMode(),
|
||||
"Document.write called in fragment mode!");
|
||||
|
||||
// Maintain a reference to ourselves so we don't go away
|
||||
// till we're completely done. The old parser grips itself in this method.
|
||||
|
@ -246,7 +251,6 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
|||
nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(mStreamParser);
|
||||
nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor);
|
||||
|
||||
// Return early if the parser has processed EOF
|
||||
if (!mExecutor->HasStarted()) {
|
||||
NS_ASSERTION(!mStreamParser,
|
||||
"Had stream parser but document.write started life cycle.");
|
||||
|
@ -263,9 +267,12 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
|||
*/
|
||||
mExecutor->WillBuildModel(eDTDMode_unknown);
|
||||
}
|
||||
|
||||
// Return early if the parser has processed EOF
|
||||
if (mExecutor->IsComplete()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aLastCall && aSourceBuffer.IsEmpty() && aKey == GetRootContextKey()) {
|
||||
// document.close()
|
||||
NS_ASSERTION(!mStreamParser,
|
||||
|
@ -277,17 +284,21 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_PRECONDITION(IsInsertionPointDefined(),
|
||||
"Document.write called when insertion point not defined.");
|
||||
NS_ASSERTION(IsInsertionPointDefined(),
|
||||
"Doc.write reached parser with undefined insertion point.");
|
||||
|
||||
NS_PRECONDITION(!(mStreamParser && !aKey), "Got a null key in a non-script-created parser");
|
||||
NS_ASSERTION(!(mStreamParser && !aKey),
|
||||
"Got a null key in a non-script-created parser");
|
||||
|
||||
if (aSourceBuffer.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsHtml5UTF16Buffer> buffer = new nsHtml5UTF16Buffer(aSourceBuffer.Length());
|
||||
memcpy(buffer->getBuffer(), aSourceBuffer.BeginReading(), aSourceBuffer.Length() * sizeof(PRUnichar));
|
||||
nsRefPtr<nsHtml5UTF16Buffer> buffer =
|
||||
new nsHtml5UTF16Buffer(aSourceBuffer.Length());
|
||||
memcpy(buffer->getBuffer(),
|
||||
aSourceBuffer.BeginReading(),
|
||||
aSourceBuffer.Length() * sizeof(PRUnichar));
|
||||
buffer->setEnd(aSourceBuffer.Length());
|
||||
|
||||
// The buffer is inserted to the stream here in case it won't be parsed
|
||||
|
@ -300,7 +311,9 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
|||
// before the old key holder belonging to the same script.
|
||||
nsHtml5UTF16Buffer* prevSearchBuf = nsnull;
|
||||
nsHtml5UTF16Buffer* searchBuf = mFirstBuffer;
|
||||
if (aKey) { // after document.open, the first level of document.write has null key
|
||||
|
||||
// after document.open, the first level of document.write has null key
|
||||
if (aKey) {
|
||||
while (searchBuf != mLastBuffer) {
|
||||
if (searchBuf->key == aKey) {
|
||||
// found a key holder
|
||||
|
@ -339,47 +352,39 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
|||
}
|
||||
}
|
||||
|
||||
if (!mBlocked) {
|
||||
while (buffer->hasMore()) {
|
||||
buffer->adjust(mLastWasCR);
|
||||
mLastWasCR = PR_FALSE;
|
||||
if (buffer->hasMore()) {
|
||||
|
||||
PRInt32 lineNumberSave;
|
||||
PRBool inRootContext = (!mStreamParser && (aKey == mRootContextKey));
|
||||
if (inRootContext) {
|
||||
mTokenizer->setLineNumber(mRootContextLineNumber);
|
||||
} else {
|
||||
// we aren't the root context, so save the line number on the
|
||||
// *stack* so that we can restore it.
|
||||
lineNumberSave = mTokenizer->getLineNumber();
|
||||
}
|
||||
|
||||
mLastWasCR = mTokenizer->tokenizeBuffer(buffer);
|
||||
|
||||
if (inRootContext) {
|
||||
mRootContextLineNumber = mTokenizer->getLineNumber();
|
||||
} else {
|
||||
mTokenizer->setLineNumber(lineNumberSave);
|
||||
}
|
||||
|
||||
if (mTreeBuilder->HasScript()) {
|
||||
// No need to flush characters, because an end tag was tokenized last
|
||||
mTreeBuilder->Flush(); // Move ops to the executor
|
||||
mExecutor->FlushDocumentWrite(); // run the ops
|
||||
}
|
||||
if (mBlocked) {
|
||||
break;
|
||||
}
|
||||
// Ignore suspension requests
|
||||
while (!mBlocked && buffer->hasMore()) {
|
||||
buffer->adjust(mLastWasCR);
|
||||
mLastWasCR = PR_FALSE;
|
||||
if (buffer->hasMore()) {
|
||||
PRInt32 lineNumberSave;
|
||||
PRBool inRootContext = (!mStreamParser && (aKey == mRootContextKey));
|
||||
if (inRootContext) {
|
||||
mTokenizer->setLineNumber(mRootContextLineNumber);
|
||||
} else {
|
||||
// we aren't the root context, so save the line number on the
|
||||
// *stack* so that we can restore it.
|
||||
lineNumberSave = mTokenizer->getLineNumber();
|
||||
}
|
||||
|
||||
mLastWasCR = mTokenizer->tokenizeBuffer(buffer);
|
||||
|
||||
if (inRootContext) {
|
||||
mRootContextLineNumber = mTokenizer->getLineNumber();
|
||||
} else {
|
||||
mTokenizer->setLineNumber(lineNumberSave);
|
||||
}
|
||||
|
||||
if (mTreeBuilder->HasScript()) {
|
||||
mTreeBuilder->Flush(); // Move ops to the executor
|
||||
mExecutor->FlushDocumentWrite(); // run the ops
|
||||
}
|
||||
// Ignore suspension requests
|
||||
}
|
||||
}
|
||||
|
||||
if (!mBlocked) { // buffer was tokenized to completion
|
||||
NS_ASSERTION(!buffer->hasMore(), "Buffer wasn't tokenized to completion?");
|
||||
// Scripting semantics require a forced tree builder flush here
|
||||
mTreeBuilder->flushCharacters(); // Flush trailing characters
|
||||
mTreeBuilder->Flush(); // Move ops to the executor
|
||||
mExecutor->FlushDocumentWrite(); // run the ops
|
||||
}
|
||||
|
@ -397,7 +402,7 @@ nsHtml5Parser::GetRootContextKey()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHtml5Parser::Terminate(void)
|
||||
nsHtml5Parser::Terminate()
|
||||
{
|
||||
// We should only call DidBuildModel once, so don't do anything if this is
|
||||
// the second time that Terminate has been called.
|
||||
|
@ -442,28 +447,31 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer,
|
|||
nsIURI* uri = doc->GetDocumentURI();
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
||||
// Can be null if owner document is synthetic
|
||||
|
||||
Initialize(doc, uri, container, nsnull);
|
||||
Initialize(doc, uri, nsnull, nsnull);
|
||||
|
||||
// Initialize() doesn't deal with base URI
|
||||
mExecutor->SetBaseUriFromDocument();
|
||||
mExecutor->SetParser(this);
|
||||
mExecutor->SetNodeInfoManager(target->GetOwnerDoc()->NodeInfoManager());
|
||||
mExecutor->SetNodeInfoManager(doc->NodeInfoManager());
|
||||
|
||||
nsIContent* weakTarget = target;
|
||||
mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace, &weakTarget, aQuirks);
|
||||
mTreeBuilder->setFragmentContext(aContextLocalName,
|
||||
aContextNamespace,
|
||||
&weakTarget,
|
||||
aQuirks);
|
||||
mExecutor->EnableFragmentMode();
|
||||
|
||||
NS_PRECONDITION(!mExecutor->HasStarted(), "Tried to start parse without initializing the parser properly.");
|
||||
NS_PRECONDITION(!mExecutor->HasStarted(),
|
||||
"Tried to start parse without initializing the parser.");
|
||||
mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
|
||||
mTokenizer->start();
|
||||
mExecutor->Start(); // Don't call WillBuildModel in fragment case
|
||||
if (!aSourceBuffer.IsEmpty()) {
|
||||
PRBool lastWasCR = PR_FALSE;
|
||||
nsHtml5UTF16Buffer buffer(aSourceBuffer.Length());
|
||||
memcpy(buffer.getBuffer(), aSourceBuffer.BeginReading(), aSourceBuffer.Length() * sizeof(PRUnichar));
|
||||
memcpy(buffer.getBuffer(),
|
||||
aSourceBuffer.BeginReading(),
|
||||
aSourceBuffer.Length() * sizeof(PRUnichar));
|
||||
buffer.setEnd(aSourceBuffer.Length());
|
||||
while (buffer.hasMore()) {
|
||||
buffer.adjust(lastWasCR);
|
||||
|
@ -484,7 +492,7 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHtml5Parser::BuildModel(void)
|
||||
nsHtml5Parser::BuildModel()
|
||||
{
|
||||
NS_NOTREACHED("Don't call this!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
@ -518,7 +526,9 @@ nsHtml5Parser::Reset()
|
|||
PRBool
|
||||
nsHtml5Parser::CanInterrupt()
|
||||
{
|
||||
return !mExecutor->IsFragmentMode();
|
||||
// nsContentSink needs this to let nsContentSink::DidProcessATokenImpl
|
||||
// interrupt.
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -559,7 +569,8 @@ nsHtml5Parser::IsScriptCreated()
|
|||
void
|
||||
nsHtml5Parser::ParseUntilBlocked()
|
||||
{
|
||||
NS_PRECONDITION(!mExecutor->IsFragmentMode(), "ParseUntilBlocked called in fragment mode.");
|
||||
NS_PRECONDITION(!mExecutor->IsFragmentMode(),
|
||||
"ParseUntilBlocked called in fragment mode.");
|
||||
|
||||
if (mBlocked) {
|
||||
return;
|
||||
|
@ -586,28 +597,22 @@ nsHtml5Parser::ParseUntilBlocked()
|
|||
mExecutor->FlushDocumentWrite();
|
||||
mTokenizer->end();
|
||||
return;
|
||||
} else {
|
||||
// never release the last buffer.
|
||||
NS_ASSERTION(!mLastBuffer->getStart(),
|
||||
"Sentinel buffer had its indeces changed.");
|
||||
NS_ASSERTION(!mLastBuffer->getEnd(),
|
||||
"Sentinel buffer had its indeces changed.");
|
||||
if (mStreamParser &&
|
||||
mReturnToStreamParserPermitted &&
|
||||
!mExecutor->IsScriptExecuting()) {
|
||||
mTreeBuilder->flushCharacters();
|
||||
mTreeBuilder->Flush();
|
||||
mReturnToStreamParserPermitted = PR_FALSE;
|
||||
mStreamParser->ContinueAfterScripts(mTokenizer,
|
||||
mTreeBuilder,
|
||||
mLastWasCR);
|
||||
}
|
||||
return; // no more data for now but expecting more
|
||||
}
|
||||
} else {
|
||||
mFirstBuffer = mFirstBuffer->next;
|
||||
continue;
|
||||
// never release the last buffer.
|
||||
NS_ASSERTION(!mLastBuffer->getStart() && !mLastBuffer->getEnd(),
|
||||
"Sentinel buffer had its indeces changed.");
|
||||
if (mStreamParser && mReturnToStreamParserPermitted
|
||||
&& !mExecutor->IsScriptExecuting()) {
|
||||
mTreeBuilder->Flush();
|
||||
mReturnToStreamParserPermitted = PR_FALSE;
|
||||
mStreamParser->ContinueAfterScripts(mTokenizer,
|
||||
mTreeBuilder,
|
||||
mLastWasCR);
|
||||
}
|
||||
return; // no more data for now but expecting more
|
||||
}
|
||||
mFirstBuffer = mFirstBuffer->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mBlocked || mExecutor->IsComplete()) {
|
||||
|
@ -618,7 +623,8 @@ nsHtml5Parser::ParseUntilBlocked()
|
|||
mFirstBuffer->adjust(mLastWasCR);
|
||||
mLastWasCR = PR_FALSE;
|
||||
if (mFirstBuffer->hasMore()) {
|
||||
PRBool inRootContext = (!mStreamParser && (mFirstBuffer->key == mRootContextKey));
|
||||
PRBool inRootContext = (!mStreamParser &&
|
||||
(mFirstBuffer->key == mRootContextKey));
|
||||
if (inRootContext) {
|
||||
mTokenizer->setLineNumber(mRootContextLineNumber);
|
||||
}
|
||||
|
@ -654,7 +660,8 @@ nsHtml5Parser::StartTokenizer(PRBool aScriptingEnabled) {
|
|||
}
|
||||
|
||||
void
|
||||
nsHtml5Parser::InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, PRInt32 aLine)
|
||||
nsHtml5Parser::InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState,
|
||||
PRInt32 aLine)
|
||||
{
|
||||
mTokenizer->resetToDataState();
|
||||
mTokenizer->setLineNumber(aLine);
|
||||
|
@ -676,7 +683,9 @@ nsHtml5Parser::internalEncodingDeclaration(nsString* aEncoding)
|
|||
{
|
||||
// Note: This handler is only installed when parsing a document.open()ed doc
|
||||
// See bug 539887 and bug 255820.
|
||||
if (mCharsetSource >= kCharsetFromMetaTag) { // this threshold corresponds to "confident" in the HTML5 spec
|
||||
|
||||
// this threshold corresponds to "confident" in the HTML5 spec
|
||||
if (mCharsetSource >= kCharsetFromMetaTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,9 +84,9 @@ class nsHtml5Parser : public nsIParser,
|
|||
NS_IMETHOD_(void) SetContentSink(nsIContentSink* aSink);
|
||||
|
||||
/**
|
||||
* Returns |this| for backwards compat.
|
||||
* Returns the tree op executor for backwards compat.
|
||||
*/
|
||||
NS_IMETHOD_(nsIContentSink*) GetContentSink(void);
|
||||
NS_IMETHOD_(nsIContentSink*) GetContentSink();
|
||||
|
||||
/**
|
||||
* Always returns "view" for backwards compat.
|
||||
|
@ -203,7 +203,7 @@ class nsHtml5Parser : public nsIParser,
|
|||
/**
|
||||
* Stops the parser prematurely
|
||||
*/
|
||||
NS_IMETHOD Terminate(void);
|
||||
NS_IMETHOD Terminate();
|
||||
|
||||
/**
|
||||
* Don't call. For interface backwards compat only.
|
||||
|
@ -233,7 +233,7 @@ class nsHtml5Parser : public nsIParser,
|
|||
/**
|
||||
* Don't call. For interface compat only.
|
||||
*/
|
||||
NS_IMETHOD BuildModel(void);
|
||||
NS_IMETHOD BuildModel();
|
||||
|
||||
/**
|
||||
* Don't call. For interface compat only.
|
||||
|
|
|
@ -1024,7 +1024,6 @@ nsHtml5StreamParser::TimerFlush()
|
|||
// that case would make the tree shape dependent on where the flush points
|
||||
// fall.
|
||||
if (mTreeBuilder->IsDiscretionaryFlushSafe()) {
|
||||
mTreeBuilder->flushCharacters();
|
||||
if (mTreeBuilder->Flush()) {
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
|
|
|
@ -558,6 +558,7 @@ nsHtml5TreeBuilder::HasScript()
|
|||
PRBool
|
||||
nsHtml5TreeBuilder::Flush()
|
||||
{
|
||||
flushCharacters();
|
||||
FlushLoads();
|
||||
PRBool hasOps = !mOpQueue.IsEmpty();
|
||||
if (hasOps) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче