зеркало из https://github.com/mozilla/gecko-dev.git
Bug 765620 - When parsing from stream without executing scripts, avoid script execution-related tree ops. r=smaug
This commit is contained in:
Родитель
8b9c9fea4d
Коммит
4bffa39c21
|
@ -303,8 +303,6 @@ protected:
|
|||
// True if this is parser is a fragment parser or an HTML DOMParser.
|
||||
// XML DOMParser leaves this to false for now!
|
||||
PRUint8 mRunsToCompletion : 1;
|
||||
// True to call prevent script execution in the fragment mode.
|
||||
PRUint8 mPreventScriptExecution : 1;
|
||||
|
||||
//
|
||||
// -- Can interrupt parsing members --
|
||||
|
|
|
@ -182,6 +182,8 @@ protected:
|
|||
PRUint8 mPrettyPrintHasFactoredElements : 1;
|
||||
PRUint8 mPrettyPrinting : 1; // True if we called PrettyPrint() and it
|
||||
// decided we should in fact prettyprint.
|
||||
// True to call prevent script execution in the fragment mode.
|
||||
PRUint8 mPreventScriptExecution : 1;
|
||||
|
||||
nsTArray<StackNode> mContentStack;
|
||||
|
||||
|
|
|
@ -678,9 +678,7 @@ nsHtml5Parser::Initialize(nsIDocument* aDoc,
|
|||
|
||||
void
|
||||
nsHtml5Parser::StartTokenizer(bool aScriptingEnabled) {
|
||||
if (!aScriptingEnabled) {
|
||||
mExecutor->PreventScriptExecution();
|
||||
}
|
||||
mTreeBuilder->SetPreventScriptExecution(!aScriptingEnabled);
|
||||
mTreeBuilder->setScriptingEnabled(aScriptingEnabled);
|
||||
mTokenizer->start();
|
||||
}
|
||||
|
|
|
@ -899,6 +899,8 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
|||
false : mExecutor->IsScriptEnabled();
|
||||
mOwner->StartTokenizer(scriptingEnabled);
|
||||
mTreeBuilder->setScriptingEnabled(scriptingEnabled);
|
||||
mTreeBuilder->SetPreventScriptExecution(!((mMode == NORMAL) &&
|
||||
scriptingEnabled));
|
||||
mTokenizer->start();
|
||||
mExecutor->Start();
|
||||
mExecutor->StartReadingFromStage();
|
||||
|
@ -1360,7 +1362,10 @@ nsHtml5StreamParser::ParseAvailableData()
|
|||
// Terminate, but that never happens together with script.
|
||||
// Can't assert that here, though, because it's possible that the main
|
||||
// thread has called Terminate() while this thread was parsing.
|
||||
if (mMode == NORMAL && mTreeBuilder->HasScript()) {
|
||||
if (mTreeBuilder->HasScript()) {
|
||||
// HasScript() cannot return true if the tree builder is preventing
|
||||
// script execution.
|
||||
MOZ_ASSERT(mMode == NORMAL);
|
||||
mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex);
|
||||
nsHtml5Speculation* speculation =
|
||||
new nsHtml5Speculation(mFirstBuffer,
|
||||
|
|
|
@ -60,7 +60,7 @@ nsHtml5StringParser::ParseFragment(const nsAString& aSourceBuffer,
|
|||
}
|
||||
#endif
|
||||
|
||||
mExecutor->EnableFragmentMode(aPreventScriptExecution);
|
||||
mTreeBuilder->SetPreventScriptExecution(aPreventScriptExecution);
|
||||
|
||||
Tokenize(aSourceBuffer, doc, true);
|
||||
return NS_OK;
|
||||
|
@ -81,7 +81,7 @@ nsHtml5StringParser::ParseDocument(const nsAString& aSourceBuffer,
|
|||
nsnull,
|
||||
false);
|
||||
|
||||
mExecutor->PreventScriptExecution();
|
||||
mTreeBuilder->SetPreventScriptExecution(true);
|
||||
|
||||
Tokenize(aSourceBuffer, aTargetDoc, aScriptingEnabledForNoscriptParsing);
|
||||
return NS_OK;
|
||||
|
@ -113,8 +113,10 @@ nsHtml5StringParser::Tokenize(const nsAString& aSourceBuffer,
|
|||
if (buffer.hasMore()) {
|
||||
lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
|
||||
if (mTreeBuilder->HasScript()) {
|
||||
// Flush on each script, because the execution prevention code
|
||||
// can handle at most one script per flush.
|
||||
// If we come here, we are in createContextualFragment() or in the
|
||||
// upcoming document.parse(). It's unclear if it's really necessary
|
||||
// to flush here, but let's do so for consistency with other flushes
|
||||
// to avoid different code paths on the executor side.
|
||||
mTreeBuilder->Flush(); // Move ops to the executor
|
||||
mExecutor->FlushDocumentWrite(); // run the ops
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
|
|||
, mHandlesUsed(0)
|
||||
, mSpeculativeLoadStage(aStage)
|
||||
, mCurrentHtmlScriptIsAsyncOrDefer(false)
|
||||
, mPreventScriptExecution(false)
|
||||
#ifdef DEBUG
|
||||
, mActive(false)
|
||||
#endif
|
||||
|
@ -470,6 +471,10 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent
|
|||
}
|
||||
// we now have only SVG and HTML
|
||||
if (aName == nsHtml5Atoms::script) {
|
||||
if (mPreventScriptExecution) {
|
||||
mOpQueue.AppendElement()->Init(eTreeOpPreventScriptExecution, aElement);
|
||||
return;
|
||||
}
|
||||
if (mCurrentHtmlScriptIsAsyncOrDefer) {
|
||||
NS_ASSERTION(aNamespace == kNameSpaceID_XHTML,
|
||||
"Only HTML scripts may be async/defer.");
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
nsHtml5TreeOpStage* mSpeculativeLoadStage;
|
||||
nsIContent** mDeepTreeSurrogateParent;
|
||||
bool mCurrentHtmlScriptIsAsyncOrDefer;
|
||||
bool mPreventScriptExecution;
|
||||
#ifdef DEBUG
|
||||
bool mActive;
|
||||
#endif
|
||||
|
@ -96,6 +97,10 @@
|
|||
|
||||
void DropHandles();
|
||||
|
||||
void SetPreventScriptExecution(bool aPrevent) {
|
||||
mPreventScriptExecution = aPrevent;
|
||||
}
|
||||
|
||||
void EnableViewSource(nsHtml5Highlighter* aHighlighter);
|
||||
|
||||
void errStrayStartTag(nsIAtom* aName);
|
||||
|
|
|
@ -759,6 +759,13 @@ nsHtml5TreeOpExecutor::StartLayout() {
|
|||
void
|
||||
nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement)
|
||||
{
|
||||
if (mRunsToCompletion) {
|
||||
// We are in createContextualFragment() or in the upcoming document.parse().
|
||||
// Do nothing. Let's not even mark scripts malformed here, because that
|
||||
// could cause serialization weirdness later.
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(aScriptElement, "No script to run");
|
||||
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aScriptElement);
|
||||
|
||||
|
@ -770,13 +777,6 @@ nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement)
|
|||
return;
|
||||
}
|
||||
|
||||
if (mPreventScriptExecution) {
|
||||
sele->PreventExecution();
|
||||
}
|
||||
if (mRunsToCompletion) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sele->GetScriptDeferred() || sele->GetScriptAsync()) {
|
||||
DebugOnly<bool> block = sele->AttemptToExecute();
|
||||
NS_ASSERTION(!block, "Defer or async script tried to block.");
|
||||
|
|
|
@ -212,21 +212,6 @@ class nsHtml5TreeOpExecutor : public nsContentSink,
|
|||
|
||||
bool IsScriptEnabled();
|
||||
|
||||
/**
|
||||
* Enables the fragment mode.
|
||||
*
|
||||
* @param aPreventScriptExecution if true, scripts are prevented from
|
||||
* executing; don't set to false when parsing a fragment directly into
|
||||
* a document--only when parsing to an actual DOM fragment
|
||||
*/
|
||||
void EnableFragmentMode(bool aPreventScriptExecution) {
|
||||
mPreventScriptExecution = aPreventScriptExecution;
|
||||
}
|
||||
|
||||
void PreventScriptExecution() {
|
||||
mPreventScriptExecution = true;
|
||||
}
|
||||
|
||||
bool BelongsToStringParser() {
|
||||
return mRunsToCompletion;
|
||||
}
|
||||
|
|
|
@ -562,6 +562,13 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
|
|||
aBuilder->RunScript(node);
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpPreventScriptExecution: {
|
||||
nsIContent* node = *(mOne.node);
|
||||
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
|
||||
MOZ_ASSERT(sele);
|
||||
sele->PreventExecution();
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpDoneAddingChildren: {
|
||||
nsIContent* node = *(mOne.node);
|
||||
node->DoneAddingChildren(aBuilder->HaveNotified(node));
|
||||
|
|
|
@ -38,6 +38,7 @@ enum eHtml5TreeOperation {
|
|||
eTreeOpMarkAsBroken,
|
||||
eTreeOpRunScript,
|
||||
eTreeOpRunScriptAsyncDefer,
|
||||
eTreeOpPreventScriptExecution,
|
||||
eTreeOpDoneAddingChildren,
|
||||
eTreeOpDoneCreatingElement,
|
||||
eTreeOpFlushPendingAppendNotifications,
|
||||
|
|
Загрузка…
Ссылка в новой задаче