Bug 551344 part 1 - Address sicking's review comments in nsHtml5Parser.cpp. r=jonas.

This commit is contained in:
Henri Sivonen 2010-03-15 14:04:41 +02:00
Родитель 21b6216e1b
Коммит 9986f24b36
4 изменённых файлов: 99 добавлений и 90 удалений

Просмотреть файл

@ -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) {