Bug 444322 - Ignore OnDataAvailable calls when we're executing a script. r+sr=bzbarsky/jst a=dveditz
git-svn-id: svn://10.0.0.236/trunk@255767 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -334,6 +334,10 @@ nsContentSink::ScriptAvailable(nsresult aResult,
|
||||
PRInt32 aLineNo)
|
||||
{
|
||||
PRUint32 count = mScriptElements.Count();
|
||||
if (mParser && NS_SUCCEEDED(aResult)) {
|
||||
// Only notify the parser about scripts that are actually going to run.
|
||||
mParser->ScriptExecuting();
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return NS_OK;
|
||||
@@ -385,13 +389,13 @@ nsContentSink::ScriptEvaluated(nsresult aResult,
|
||||
nsIScriptElement *aElement,
|
||||
PRBool aIsInline)
|
||||
{
|
||||
if (mParser) {
|
||||
mParser->ScriptDidExecute();
|
||||
}
|
||||
|
||||
// Check if this is the element we were waiting for
|
||||
PRInt32 count = mScriptElements.Count();
|
||||
if (count == 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aElement != mScriptElements[count - 1]) {
|
||||
if (count == 0 || aElement != mScriptElements[count - 1]) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1486,14 +1490,6 @@ nsContentSink::WillBuildModelImpl()
|
||||
mScrolledToRefAlready = PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentSink::ContinueInterruptedParsing()
|
||||
{
|
||||
if (mParser) {
|
||||
mParser->ContinueInterruptedParsing();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsContentSink::ContinueInterruptedParsingIfEnabled()
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ class nsIURI;
|
||||
class nsIChannel;
|
||||
class nsIDocShell;
|
||||
class nsICSSLoader;
|
||||
class nsIParser;
|
||||
class nsIParser_1_9_0_BRANCH;
|
||||
class nsIAtom;
|
||||
class nsIChannel;
|
||||
class nsIContent;
|
||||
@@ -225,10 +225,9 @@ protected:
|
||||
|
||||
void ContinueInterruptedParsingAsync();
|
||||
void ContinueInterruptedParsingIfEnabled();
|
||||
void ContinueInterruptedParsing();
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsIParser> mParser;
|
||||
nsCOMPtr<nsIParser_1_9_0_BRANCH>mParser;
|
||||
nsCOMPtr<nsIURI> mDocumentURI;
|
||||
nsCOMPtr<nsIURI> mDocumentBaseURI;
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
|
||||
@@ -189,6 +189,9 @@ _TEST_FILES = test_bug5141.html \
|
||||
file_bug458248.xml^headers^ \
|
||||
test_bug380418.html \
|
||||
test_bug380418.html^headers^ \
|
||||
test_bug444322.html \
|
||||
bug444322.txt \
|
||||
bug444322.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
||||
2589
mozilla/content/base/test/test_bug444322.html
Normal file
2589
mozilla/content/base/test/test_bug444322.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1852,7 +1852,7 @@ NS_IMETHODIMP
|
||||
HTMLContentSink::SetParser(nsIParser* aParser)
|
||||
{
|
||||
NS_PRECONDITION(aParser, "Should have a parser here!");
|
||||
mParser = aParser;
|
||||
mParser = do_QueryInterface(aParser);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ NS_IMETHODIMP
|
||||
nsXMLContentSink::SetParser(nsIParser* aParser)
|
||||
{
|
||||
NS_PRECONDITION(aParser, "Should have a parser here!");
|
||||
mParser = aParser;
|
||||
mParser = do_QueryInterface(aParser);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,10 @@
|
||||
{ 0x506527cc, 0xd832, 0x420b, \
|
||||
{ 0xba, 0x3a, 0x80, 0xc0, 0x5a, 0xa1, 0x05, 0xf4 } }
|
||||
|
||||
// 5FA66227-44CF-4572-9B5F-E9A357B67ED9
|
||||
#define NS_IPARSER_1_9_0_BRANCH \
|
||||
{ 0x5FA66227, 0x44CF, 0x4572, \
|
||||
{ 0x9B, 0x5F, 0xE9, 0xA3, 0x57, 0xB6, 0x7E, 0xD9 } }
|
||||
|
||||
// {41421C60-310A-11d4-816F-000064657374}
|
||||
#define NS_IDEBUG_DUMP_CONTENT_IID \
|
||||
@@ -291,6 +295,22 @@ class nsIParser : public nsISupports {
|
||||
virtual void Reset() = 0;
|
||||
};
|
||||
|
||||
class nsIParser_1_9_0_BRANCH : public nsIParser {
|
||||
public:
|
||||
/**
|
||||
* Tells the parser that a script is now executing. The only data we
|
||||
* should resume parsing for is document.written data. We'll deal with any
|
||||
* data that comes in over the network later.
|
||||
*/
|
||||
virtual void ScriptExecuting() = 0;
|
||||
|
||||
/**
|
||||
* Tells the parser that the script is done executing. We should now
|
||||
* continue the regular parsing process.
|
||||
*/
|
||||
virtual void ScriptDidExecute() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIParser, NS_IPARSER_IID)
|
||||
|
||||
/* ===========================================================*
|
||||
|
||||
@@ -281,6 +281,7 @@ nsParser::Initialize(PRBool aConstructor)
|
||||
mFlags = NS_PARSER_FLAG_OBSERVERS_ENABLED |
|
||||
NS_PARSER_FLAG_PARSER_ENABLED |
|
||||
NS_PARSER_FLAG_CAN_TOKENIZE;
|
||||
mScriptsExecuting = 0;
|
||||
|
||||
MOZ_TIMER_DEBUGLOG(("Reset: Parse Time: nsParser::nsParser(), this=%p\n", this));
|
||||
MOZ_TIMER_RESET(mParseTime);
|
||||
@@ -346,6 +347,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsParser, nsIParser)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsParser)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIParser)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIParser_1_9_0_BRANCH)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIParser)
|
||||
NS_INTERFACE_MAP_END
|
||||
@@ -1229,7 +1231,8 @@ nsParser::IsComplete()
|
||||
}
|
||||
|
||||
|
||||
void nsParser::HandleParserContinueEvent(nsParserContinueEvent *ev) {
|
||||
void nsParser::HandleParserContinueEvent(nsParserContinueEvent *ev)
|
||||
{
|
||||
// Ignore any revoked continue events...
|
||||
if (mContinueEvent != ev)
|
||||
return;
|
||||
@@ -1237,9 +1240,23 @@ void nsParser::HandleParserContinueEvent(nsParserContinueEvent *ev) {
|
||||
mFlags &= ~NS_PARSER_FLAG_PENDING_CONTINUE_EVENT;
|
||||
mContinueEvent = nsnull;
|
||||
|
||||
NS_ASSERTION(mScriptsExecuting == 0, "Interrupted in the middle of a script?");
|
||||
ContinueInterruptedParsing();
|
||||
}
|
||||
|
||||
void
|
||||
nsParser::ScriptExecuting()
|
||||
{
|
||||
++mScriptsExecuting;
|
||||
}
|
||||
|
||||
void
|
||||
nsParser::ScriptDidExecute()
|
||||
{
|
||||
NS_ASSERTION(mScriptsExecuting > 0, "Too many calls to ScriptDidExecute");
|
||||
--mScriptsExecuting;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsParser::DataAdded(const nsSubstring& aData, nsIRequest *aRequest)
|
||||
{
|
||||
@@ -2283,7 +2300,8 @@ nsParser::OnDataAvailable(nsIRequest *request, nsISupports* aContext,
|
||||
|
||||
// Don't bother to start parsing until we've seen some
|
||||
// non-whitespace data
|
||||
if (theContext->mScanner->FirstNonWhitespacePosition() >= 0) {
|
||||
if (mScriptsExecuting == 0 &&
|
||||
theContext->mScanner->FirstNonWhitespacePosition() >= 0) {
|
||||
rv = ResumeParse();
|
||||
}
|
||||
} else {
|
||||
@@ -2303,14 +2321,6 @@ nsParser::OnStopRequest(nsIRequest *request, nsISupports* aContext,
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (eOnStart == mParserContext->mStreamListenerState) {
|
||||
// If you're here, then OnDataAvailable() never got called. Prior
|
||||
// to necko, we never dealt with this case, but the problem may
|
||||
// have existed. Everybody can live with an empty input stream, so
|
||||
// just resume parsing.
|
||||
rv = ResumeParse(PR_TRUE, PR_TRUE);
|
||||
}
|
||||
|
||||
CParserContext *pc = mParserContext;
|
||||
while (pc) {
|
||||
if (pc->mRequest == request) {
|
||||
@@ -2327,7 +2337,7 @@ nsParser::OnStopRequest(nsIRequest *request, nsISupports* aContext,
|
||||
if (mParserFilter)
|
||||
mParserFilter->Finish();
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (mScriptsExecuting == 0 && NS_SUCCEEDED(rv)) {
|
||||
rv = ResumeParse(PR_TRUE, PR_TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ class nsIProgressEventSink;
|
||||
#endif
|
||||
|
||||
|
||||
class nsParser : public nsIParser,
|
||||
class nsParser : public nsIParser_1_9_0_BRANCH,
|
||||
public nsIStreamListener{
|
||||
|
||||
|
||||
@@ -386,6 +386,19 @@ class nsParser : public nsIParser,
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the parser that a script is now executing. The only data we
|
||||
* should resume parsing for is document.written data. We'll deal with any
|
||||
* data that comes in over the network later.
|
||||
*/
|
||||
virtual void ScriptExecuting();
|
||||
|
||||
/**
|
||||
* Tells the parser that the script is done executing. We should now
|
||||
* continue the regular parsing process.
|
||||
*/
|
||||
virtual void ScriptDidExecute();
|
||||
|
||||
protected:
|
||||
|
||||
void Initialize(PRBool aConstructor = PR_FALSE);
|
||||
@@ -467,6 +480,7 @@ protected:
|
||||
PRInt32 mCharsetSource;
|
||||
|
||||
PRUint16 mFlags;
|
||||
PRUint32 mScriptsExecuting;
|
||||
|
||||
nsString mUnusedInput;
|
||||
nsCString mCharset;
|
||||
|
||||
Reference in New Issue
Block a user