mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 959150 part 4 - Avoid using tree ops when parsing with nsHtml5StringParser. r=smaug.
This commit is contained in:
parent
128e0f3424
commit
2fc6c1b93a
@ -5137,6 +5137,9 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
|
||||
// ]NOCPP]
|
||||
// This method can't be called for custom elements
|
||||
HtmlAttributes clone = attributes.cloneAttributes(null);
|
||||
// Attributes must not be read after calling createElement, because
|
||||
// createElement may delete attributes in C++.
|
||||
T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
|
||||
StackNode<T> current = stack[currentPtr];
|
||||
if (current.isFosterParenting()) {
|
||||
@ -5145,7 +5148,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
} else {
|
||||
appendElement(elt, current.node);
|
||||
}
|
||||
StackNode<T> node = new StackNode<T>(elementName, elt, attributes.cloneAttributes(null)
|
||||
StackNode<T> node = new StackNode<T>(elementName, elt, clone
|
||||
// [NOCPP[
|
||||
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
|
||||
// ]NOCPP]
|
||||
@ -5211,6 +5214,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
popName = checkPopName(popName);
|
||||
}
|
||||
// ]NOCPP]
|
||||
boolean markAsHtmlIntegrationPoint = false;
|
||||
if (ElementName.ANNOTATION_XML == elementName
|
||||
&& annotationXmlEncodingPermitsHtml(attributes)) {
|
||||
markAsHtmlIntegrationPoint = true;
|
||||
}
|
||||
// Attributes must not be read after calling createElement(), since
|
||||
// createElement may delete the object in C++.
|
||||
T elt = createElement("http://www.w3.org/1998/Math/MathML", popName,
|
||||
attributes);
|
||||
StackNode<T> current = stack[currentPtr];
|
||||
@ -5220,11 +5230,6 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
} else {
|
||||
appendElement(elt, current.node);
|
||||
}
|
||||
boolean markAsHtmlIntegrationPoint = false;
|
||||
if (ElementName.ANNOTATION_XML == elementName
|
||||
&& annotationXmlEncodingPermitsHtml(attributes)) {
|
||||
markAsHtmlIntegrationPoint = true;
|
||||
}
|
||||
StackNode<T> node = new StackNode<T>(elementName, elt, popName,
|
||||
markAsHtmlIntegrationPoint
|
||||
// [NOCPP[
|
||||
|
@ -30,6 +30,7 @@ EXPORTS += [
|
||||
'nsHtml5Module.h',
|
||||
'nsHtml5NamedCharacters.h',
|
||||
'nsHtml5NamedCharactersAccel.h',
|
||||
'nsHtml5OplessBuilder.h',
|
||||
'nsHtml5OwningUTF16Buffer.h',
|
||||
'nsHtml5Parser.h',
|
||||
'nsHtml5PendingNotification.h',
|
||||
@ -63,6 +64,7 @@ UNIFIED_SOURCES += [
|
||||
'nsHtml5Module.cpp',
|
||||
'nsHtml5NamedCharacters.cpp',
|
||||
'nsHtml5NamedCharactersAccel.cpp',
|
||||
'nsHtml5OplessBuilder.cpp',
|
||||
'nsHtml5OwningUTF16Buffer.cpp',
|
||||
'nsHtml5Parser.cpp',
|
||||
'nsHtml5PlainTextUtils.cpp',
|
||||
|
@ -6,9 +6,10 @@
|
||||
|
||||
#include "nsHtml5DocumentBuilder.h"
|
||||
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "nsStyleLinkElement.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "mozilla/css/Loader.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(nsHtml5DocumentBuilder, nsContentSink,
|
||||
mOwnedElements)
|
||||
@ -19,15 +20,125 @@ NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
|
||||
NS_IMPL_ADDREF_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
|
||||
NS_IMPL_RELEASE_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
|
||||
|
||||
void
|
||||
nsHtml5DocumentBuilder::DropHeldElements()
|
||||
nsHtml5DocumentBuilder::nsHtml5DocumentBuilder(bool aRunsToCompletion)
|
||||
{
|
||||
mScriptLoader = nullptr;
|
||||
mDocument = nullptr;
|
||||
mNodeInfoManager = nullptr;
|
||||
mCSSLoader = nullptr;
|
||||
mDocumentURI = nullptr;
|
||||
mDocShell = nullptr;
|
||||
mOwnedElements.Clear();
|
||||
mRunsToCompletion = aRunsToCompletion;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHtml5DocumentBuilder::Init(nsIDocument* aDoc,
|
||||
nsIURI* aURI,
|
||||
nsISupports* aContainer,
|
||||
nsIChannel* aChannel)
|
||||
{
|
||||
return nsContentSink::Init(aDoc, aURI, aContainer, aChannel);
|
||||
}
|
||||
|
||||
nsHtml5DocumentBuilder::~nsHtml5DocumentBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHtml5DocumentBuilder::MarkAsBroken(nsresult aReason)
|
||||
{
|
||||
mBroken = aReason;
|
||||
return aReason;
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5DocumentBuilder::SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource)
|
||||
{
|
||||
if (mDocument) {
|
||||
mDocument->SetDocumentCharacterSetSource(aCharsetSource);
|
||||
mDocument->SetDocumentCharacterSet(aCharset);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement)
|
||||
{
|
||||
// Break out of the doc update created by Flush() to zap a runnable
|
||||
// waiting to call UpdateStyleSheet without the right observer
|
||||
EndDocUpdate();
|
||||
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// EndDocUpdate ran stuff that called nsIParser::Terminate()
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aElement));
|
||||
NS_ASSERTION(ssle, "Node didn't QI to style.");
|
||||
|
||||
ssle->SetEnableUpdates(true);
|
||||
|
||||
bool willNotify;
|
||||
bool isAlternate;
|
||||
nsresult rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this,
|
||||
&willNotify,
|
||||
&isAlternate);
|
||||
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) {
|
||||
++mPendingSheetCount;
|
||||
mScriptLoader->AddExecuteBlocker();
|
||||
}
|
||||
|
||||
if (aElement->IsHTML(nsGkAtoms::link)) {
|
||||
// look for <link rel="next" href="url">
|
||||
nsAutoString relVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
|
||||
if (!relVal.IsEmpty()) {
|
||||
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
|
||||
bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
|
||||
if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
|
||||
nsAutoString hrefVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchHref(hrefVal, aElement, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-open update
|
||||
BeginDocUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5DocumentBuilder::SetDocumentMode(nsHtml5DocumentMode m)
|
||||
{
|
||||
nsCompatibility mode = eCompatibility_NavQuirks;
|
||||
switch (m) {
|
||||
case STANDARDS_MODE:
|
||||
mode = eCompatibility_FullStandards;
|
||||
break;
|
||||
case ALMOST_STANDARDS_MODE:
|
||||
mode = eCompatibility_AlmostStandards;
|
||||
break;
|
||||
case QUIRKS_MODE:
|
||||
mode = eCompatibility_NavQuirks;
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(mDocument);
|
||||
NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document.");
|
||||
htmlDocument->SetCompatibilityMode(mode);
|
||||
}
|
||||
|
||||
// nsContentSink overrides
|
||||
|
||||
void
|
||||
nsHtml5DocumentBuilder::UpdateChildCounts()
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHtml5DocumentBuilder::FlushTags()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -8,6 +8,9 @@
|
||||
#define nsHtml5DocumentBuilder_h
|
||||
|
||||
#include "nsHtml5PendingNotification.h"
|
||||
#include "nsContentSink.h"
|
||||
#include "nsHtml5DocumentMode.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
typedef nsIContent* nsIContentPtr;
|
||||
|
||||
@ -92,7 +95,8 @@ public:
|
||||
mFlushState = eInDocUpdate;
|
||||
}
|
||||
|
||||
void DropHeldElements();
|
||||
nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
|
||||
nsISupports* aContainer, nsIChannel* aChannel);
|
||||
|
||||
// Getters and setters for fields from nsContentSink
|
||||
nsIDocument* GetDocument() {
|
||||
@ -102,7 +106,54 @@ public:
|
||||
return mNodeInfoManager;
|
||||
}
|
||||
|
||||
virtual bool BelongsToStringParser() = 0;
|
||||
/**
|
||||
* Marks this parser as broken and tells the stream parser (if any) to
|
||||
* terminate.
|
||||
*
|
||||
* @return aReason for convenience
|
||||
*/
|
||||
virtual nsresult MarkAsBroken(nsresult aReason);
|
||||
|
||||
/**
|
||||
* Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
|
||||
* value if broken.
|
||||
*/
|
||||
inline nsresult IsBroken() {
|
||||
return mBroken;
|
||||
}
|
||||
|
||||
inline void BeginDocUpdate() {
|
||||
NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
|
||||
NS_PRECONDITION(mParser, "Started update without parser.");
|
||||
mFlushState = eInDocUpdate;
|
||||
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
inline void EndDocUpdate() {
|
||||
NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
|
||||
if (mFlushState == eInDocUpdate) {
|
||||
FlushPendingAppendNotifications();
|
||||
mFlushState = eInFlush;
|
||||
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource);
|
||||
|
||||
/**
|
||||
* Sets up style sheet load / parse
|
||||
*/
|
||||
void UpdateStyleSheet(nsIContent* aElement);
|
||||
|
||||
void SetDocumentMode(nsHtml5DocumentMode m);
|
||||
|
||||
void SetNodeInfoManager(nsNodeInfoManager* aManager) {
|
||||
mNodeInfoManager = aManager;
|
||||
}
|
||||
|
||||
// nsContentSink methods
|
||||
virtual void UpdateChildCounts();
|
||||
virtual nsresult FlushTags();
|
||||
|
||||
protected:
|
||||
inline void SetAppendBatchCapacity(uint32_t aCapacity)
|
||||
@ -110,11 +161,26 @@ protected:
|
||||
mElementsSeenInThisAppendBatch.SetCapacity(aCapacity);
|
||||
}
|
||||
|
||||
nsHtml5DocumentBuilder(bool aRunsToCompletion);
|
||||
virtual ~nsHtml5DocumentBuilder();
|
||||
|
||||
private:
|
||||
nsTArray<nsHtml5PendingNotification> mPendingNotifications;
|
||||
nsTArray<nsCOMPtr<nsIContent> > mOwnedElements;
|
||||
nsTArray<nsIContentPtr> mElementsSeenInThisAppendBatch;
|
||||
protected:
|
||||
nsTArray<nsCOMPtr<nsIContent> > mOwnedElements;
|
||||
/**
|
||||
* Non-NS_OK if this parser should refuse to process any more input.
|
||||
* For example, the parser needs to be marked as broken if it drops some
|
||||
* input due to a memory allocation failure. In such a case, the whole
|
||||
* parser needs to be marked as broken, because some input has been lost
|
||||
* and parsing more input could lead to a DOM where pieces of HTML source
|
||||
* that weren't supposed to become scripts become scripts.
|
||||
*
|
||||
* Since NS_OK is actually 0, zeroing operator new takes care of
|
||||
* initializing this.
|
||||
*/
|
||||
nsresult mBroken;
|
||||
eHtml5FlushState mFlushState;
|
||||
};
|
||||
|
||||
|
49
parser/html/nsHtml5OplessBuilder.cpp
Normal file
49
parser/html/nsHtml5OplessBuilder.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "nsHtml5OplessBuilder.h"
|
||||
|
||||
#include "nsScriptLoader.h"
|
||||
#include "mozilla/css/Loader.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
|
||||
nsHtml5OplessBuilder::nsHtml5OplessBuilder()
|
||||
: nsHtml5DocumentBuilder(true)
|
||||
{
|
||||
}
|
||||
|
||||
nsHtml5OplessBuilder::~nsHtml5OplessBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5OplessBuilder::Start()
|
||||
{
|
||||
mFlushState = eInFlush;
|
||||
BeginDocUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5OplessBuilder::Finish()
|
||||
{
|
||||
EndDocUpdate();
|
||||
DropParserAndPerfHint();
|
||||
mScriptLoader = nullptr;
|
||||
mDocument = nullptr;
|
||||
mNodeInfoManager = nullptr;
|
||||
mCSSLoader = nullptr;
|
||||
mDocumentURI = nullptr;
|
||||
mDocShell = nullptr;
|
||||
mOwnedElements.Clear();
|
||||
mFlushState = eNotFlushing;
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5OplessBuilder::SetParser(nsParserBase* aParser)
|
||||
{
|
||||
mParser = aParser;
|
||||
}
|
26
parser/html/nsHtml5OplessBuilder.h
Normal file
26
parser/html/nsHtml5OplessBuilder.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* -*- 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 nsHtml5OplessBuilder_h
|
||||
#define nsHtml5OplessBuilder_h
|
||||
|
||||
#include "nsHtml5DocumentBuilder.h"
|
||||
|
||||
class nsParserBase;
|
||||
|
||||
class nsHtml5OplessBuilder : public nsHtml5DocumentBuilder
|
||||
{
|
||||
public:
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
nsHtml5OplessBuilder();
|
||||
~nsHtml5OplessBuilder();
|
||||
void Start();
|
||||
void Finish();
|
||||
void SetParser(nsParserBase* aParser);
|
||||
};
|
||||
|
||||
#endif // nsHtml5OplessBuilder_h
|
@ -14,8 +14,8 @@
|
||||
NS_IMPL_ISUPPORTS0(nsHtml5StringParser)
|
||||
|
||||
nsHtml5StringParser::nsHtml5StringParser()
|
||||
: mExecutor(new nsHtml5TreeOpExecutor(true))
|
||||
, mTreeBuilder(new nsHtml5TreeBuilder(mExecutor, nullptr))
|
||||
: mBuilder(new nsHtml5OplessBuilder())
|
||||
, mTreeBuilder(new nsHtml5TreeBuilder(mBuilder))
|
||||
, mTokenizer(new nsHtml5Tokenizer(mTreeBuilder, false))
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsHtml5StringParser);
|
||||
@ -42,10 +42,9 @@ nsHtml5StringParser::ParseFragment(const nsAString& aSourceBuffer,
|
||||
nsIURI* uri = doc->GetDocumentURI();
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsIContent* target = aTargetNode;
|
||||
mTreeBuilder->setFragmentContext(aContextLocalName,
|
||||
aContextNamespace,
|
||||
&target,
|
||||
aTargetNode,
|
||||
aQuirks);
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -61,8 +60,7 @@ nsHtml5StringParser::ParseFragment(const nsAString& aSourceBuffer,
|
||||
|
||||
mTreeBuilder->SetPreventScriptExecution(aPreventScriptExecution);
|
||||
|
||||
Tokenize(aSourceBuffer, doc, true);
|
||||
return NS_OK;
|
||||
return Tokenize(aSourceBuffer, doc, true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -82,28 +80,28 @@ nsHtml5StringParser::ParseDocument(const nsAString& aSourceBuffer,
|
||||
|
||||
mTreeBuilder->SetPreventScriptExecution(true);
|
||||
|
||||
Tokenize(aSourceBuffer, aTargetDoc, aScriptingEnabledForNoscriptParsing);
|
||||
return NS_OK;
|
||||
return Tokenize(aSourceBuffer, aTargetDoc, aScriptingEnabledForNoscriptParsing);
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
nsHtml5StringParser::Tokenize(const nsAString& aSourceBuffer,
|
||||
nsIDocument* aDocument,
|
||||
bool aScriptingEnabledForNoscriptParsing) {
|
||||
|
||||
nsIURI* uri = aDocument->GetDocumentURI();
|
||||
|
||||
mExecutor->Init(aDocument, uri, nullptr, nullptr);
|
||||
mBuilder->Init(aDocument, uri, nullptr, nullptr);
|
||||
|
||||
mExecutor->SetParser(this);
|
||||
mExecutor->SetNodeInfoManager(aDocument->NodeInfoManager());
|
||||
mBuilder->SetParser(this);
|
||||
mBuilder->SetNodeInfoManager(aDocument->NodeInfoManager());
|
||||
|
||||
// Mark the parser as *not* broken by passing NS_OK
|
||||
nsresult rv = mBuilder->MarkAsBroken(NS_OK);
|
||||
|
||||
NS_PRECONDITION(!mExecutor->HasStarted(),
|
||||
"Tried to start parse without initializing the parser.");
|
||||
mTreeBuilder->setScriptingEnabled(aScriptingEnabledForNoscriptParsing);
|
||||
mTreeBuilder->setIsSrcdocDocument(aDocument->IsSrcdocDocument());
|
||||
mBuilder->Start();
|
||||
mTokenizer->start();
|
||||
mExecutor->Start(); // Don't call WillBuildModel in fragment case
|
||||
if (!aSourceBuffer.IsEmpty()) {
|
||||
bool lastWasCR = false;
|
||||
nsHtml5DependentUTF16Buffer buffer(aSourceBuffer);
|
||||
@ -112,25 +110,15 @@ nsHtml5StringParser::Tokenize(const nsAString& aSourceBuffer,
|
||||
lastWasCR = false;
|
||||
if (buffer.hasMore()) {
|
||||
lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
|
||||
if (mTreeBuilder->HasScript()) {
|
||||
// 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
|
||||
if (NS_FAILED(rv = mBuilder->IsBroken())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mTokenizer->eof();
|
||||
mTreeBuilder->StreamEnded();
|
||||
mTreeBuilder->Flush();
|
||||
mExecutor->FlushDocumentWrite();
|
||||
mTokenizer->end();
|
||||
mExecutor->DropParserAndPerfHint();
|
||||
mExecutor->DropHeldElements();
|
||||
mTreeBuilder->DropHandles();
|
||||
mBuilder->Finish();
|
||||
mAtomTable.Clear();
|
||||
mExecutor->Reset();
|
||||
return rv;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "nsHtml5AtomTable.h"
|
||||
#include "nsParserBase.h"
|
||||
|
||||
class nsHtml5TreeOpExecutor;
|
||||
class nsHtml5OplessBuilder;
|
||||
class nsHtml5TreeBuilder;
|
||||
class nsHtml5Tokenizer;
|
||||
class nsIContent;
|
||||
@ -58,14 +58,14 @@ class nsHtml5StringParser : public nsParserBase
|
||||
|
||||
private:
|
||||
|
||||
void Tokenize(const nsAString& aSourceBuffer,
|
||||
nsIDocument* aDocument,
|
||||
bool aScriptingEnabledForNoscriptParsing);
|
||||
nsresult Tokenize(const nsAString& aSourceBuffer,
|
||||
nsIDocument* aDocument,
|
||||
bool aScriptingEnabledForNoscriptParsing);
|
||||
|
||||
/**
|
||||
* The tree operation executor
|
||||
*/
|
||||
nsRefPtr<nsHtml5TreeOpExecutor> mExecutor;
|
||||
nsRefPtr<nsHtml5OplessBuilder> mBuilder;
|
||||
|
||||
/**
|
||||
* The HTML5 tree builder
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#define nsHtml5TreeBuilder_cpp__
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsHtml5AtomTable.h"
|
||||
#include "nsITimer.h"
|
||||
@ -54,6 +55,7 @@
|
||||
#include "nsHtml5ViewSourceUtils.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsIContentHandle.h"
|
||||
#include "nsHtml5OplessBuilder.h"
|
||||
|
||||
#include "nsHtml5Tokenizer.h"
|
||||
#include "nsHtml5MetaScanner.h"
|
||||
@ -3899,6 +3901,7 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAt
|
||||
void
|
||||
nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
|
||||
{
|
||||
nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr);
|
||||
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
|
||||
nsHtml5StackNode* current = stack[currentPtr];
|
||||
if (current->isFosterParenting()) {
|
||||
@ -3907,7 +3910,7 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5
|
||||
} else {
|
||||
appendElement(elt, current->node);
|
||||
}
|
||||
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, attributes->cloneAttributes(nullptr));
|
||||
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone);
|
||||
push(node);
|
||||
append(node);
|
||||
node->retain();
|
||||
@ -3945,6 +3948,10 @@ void
|
||||
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
|
||||
{
|
||||
nsIAtom* popName = elementName->name;
|
||||
bool markAsHtmlIntegrationPoint = false;
|
||||
if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) {
|
||||
markAsHtmlIntegrationPoint = true;
|
||||
}
|
||||
nsIContentHandle* elt = createElement(kNameSpaceID_MathML, popName, attributes);
|
||||
nsHtml5StackNode* current = stack[currentPtr];
|
||||
if (current->isFosterParenting()) {
|
||||
@ -3953,10 +3960,6 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5Elem
|
||||
} else {
|
||||
appendElement(elt, current->node);
|
||||
}
|
||||
bool markAsHtmlIntegrationPoint = false;
|
||||
if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) {
|
||||
markAsHtmlIntegrationPoint = true;
|
||||
}
|
||||
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
|
||||
push(node);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifndef nsHtml5TreeBuilder_h
|
||||
#define nsHtml5TreeBuilder_h
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsHtml5AtomTable.h"
|
||||
#include "nsITimer.h"
|
||||
@ -55,6 +56,7 @@
|
||||
#include "nsHtml5ViewSourceUtils.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsIContentHandle.h"
|
||||
#include "nsHtml5OplessBuilder.h"
|
||||
|
||||
class nsHtml5StreamParser;
|
||||
|
||||
|
@ -13,6 +13,27 @@
|
||||
|
||||
class nsPresContext;
|
||||
|
||||
nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
|
||||
: scriptingEnabled(false)
|
||||
, fragment(false)
|
||||
, contextNode(nullptr)
|
||||
, formPointer(nullptr)
|
||||
, headPointer(nullptr)
|
||||
, mBuilder(aBuilder)
|
||||
, mViewSource(nullptr)
|
||||
, mOpSink(nullptr)
|
||||
, mHandles(nullptr)
|
||||
, mHandlesUsed(0)
|
||||
, mSpeculativeLoadStage(nullptr)
|
||||
, mCurrentHtmlScriptIsAsyncOrDefer(false)
|
||||
, mPreventScriptExecution(false)
|
||||
#ifdef DEBUG
|
||||
, mActive(false)
|
||||
#endif
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
|
||||
}
|
||||
|
||||
nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
|
||||
nsHtml5TreeOpStage* aStage)
|
||||
: scriptingEnabled(false)
|
||||
@ -20,6 +41,7 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
|
||||
, contextNode(nullptr)
|
||||
, formPointer(nullptr)
|
||||
, headPointer(nullptr)
|
||||
, mBuilder(nullptr)
|
||||
, mViewSource(nullptr)
|
||||
, mOpSink(aOpSink)
|
||||
, mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH])
|
||||
@ -51,6 +73,20 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
|
||||
aNamespace == kNameSpaceID_MathML,
|
||||
"Bogus namespace.");
|
||||
|
||||
if (mBuilder) {
|
||||
nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName);
|
||||
nsIContent* elem =
|
||||
nsHtml5TreeOperation::CreateElement(aNamespace,
|
||||
name,
|
||||
aAttributes,
|
||||
mozilla::dom::FROM_PARSER_FRAGMENT,
|
||||
mBuilder);
|
||||
if (aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
|
||||
delete aAttributes;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
nsIContentHandle* content = AllocateContentHandle();
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
@ -214,9 +250,14 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
|
||||
{
|
||||
nsIContentHandle* content = createElement(aNamespace, aName, aAttributes);
|
||||
if (aFormElement) {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpSetFormElement, content, aFormElement);
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::SetFormElement(static_cast<nsIContent*>(content),
|
||||
static_cast<nsIContent*>(aFormElement));
|
||||
} else {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpSetFormElement, content, aFormElement);
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
@ -225,9 +266,17 @@ nsIContentHandle*
|
||||
nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes)
|
||||
{
|
||||
nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes);
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpAppendToDocument, content);
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::AppendToDocument(static_cast<nsIContent*>(content),
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
} else {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpAppendToDocument, content);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
@ -236,6 +285,12 @@ nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement, "Null element");
|
||||
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement),
|
||||
mBuilder);
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpDetach, aElement);
|
||||
@ -249,6 +304,17 @@ nsHtml5TreeBuilder::appendElement(nsIContentHandle* aChild, nsIContentHandle* aP
|
||||
if (deepTreeSurrogateParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::Append(static_cast<nsIContent*>(aChild),
|
||||
static_cast<nsIContent*>(aParent),
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpAppend, aChild, aParent);
|
||||
@ -260,6 +326,17 @@ nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContentHandle* aOldParent, nsIC
|
||||
NS_PRECONDITION(aOldParent, "Null old parent");
|
||||
NS_PRECONDITION(aNewParent, "Null new parent");
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::AppendChildrenToNewParent(
|
||||
static_cast<nsIContent*>(aOldParent),
|
||||
static_cast<nsIContent*>(aNewParent),
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpAppendChildrenToNewParent, aOldParent, aNewParent);
|
||||
@ -271,6 +348,20 @@ nsHtml5TreeBuilder::insertFosterParentedCharacters(char16_t* aBuffer, int32_t aS
|
||||
NS_PRECONDITION(aBuffer, "Null buffer");
|
||||
NS_PRECONDITION(aTable, "Null table");
|
||||
NS_PRECONDITION(aStackParent, "Null stack parent");
|
||||
MOZ_ASSERT(!aStart, "aStart must always be zero.");
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::FosterParentText(
|
||||
static_cast<nsIContent*>(aStackParent),
|
||||
aBuffer, // XXX aStart always ignored???
|
||||
aLength,
|
||||
static_cast<nsIContent*>(aTable),
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
@ -287,6 +378,18 @@ nsHtml5TreeBuilder::insertFosterParentedChild(nsIContentHandle* aChild, nsIConte
|
||||
NS_PRECONDITION(aTable, "Null table");
|
||||
NS_PRECONDITION(aStackParent, "Null stack parent");
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::FosterParent(
|
||||
static_cast<nsIContent*>(aChild),
|
||||
static_cast<nsIContent*>(aStackParent),
|
||||
static_cast<nsIContent*>(aTable),
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpFosterParent, aChild, aStackParent, aTable);
|
||||
@ -297,6 +400,20 @@ nsHtml5TreeBuilder::appendCharacters(nsIContentHandle* aParent, char16_t* aBuffe
|
||||
{
|
||||
NS_PRECONDITION(aBuffer, "Null buffer");
|
||||
NS_PRECONDITION(aParent, "Null parent");
|
||||
MOZ_ASSERT(!aStart, "aStart must always be zero.");
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::AppendText(
|
||||
aBuffer, // XXX aStart always ignored???
|
||||
aLength,
|
||||
static_cast<nsIContent*>(deepTreeSurrogateParent ?
|
||||
deepTreeSurrogateParent : aParent),
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
@ -312,6 +429,16 @@ nsHtml5TreeBuilder::appendIsindexPrompt(nsIContentHandle* aParent)
|
||||
{
|
||||
NS_PRECONDITION(aParent, "Null parent");
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::AppendIsindexPrompt(
|
||||
static_cast<nsIContent*>(aParent),
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpAppendIsindexPrompt, aParent);
|
||||
@ -322,10 +449,24 @@ nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent, char16_t* aBuffer,
|
||||
{
|
||||
NS_PRECONDITION(aBuffer, "Null buffer");
|
||||
NS_PRECONDITION(aParent, "Null parent");
|
||||
MOZ_ASSERT(!aStart, "aStart must always be zero.");
|
||||
|
||||
if (deepTreeSurrogateParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::AppendComment(
|
||||
static_cast<nsIContent*>(aParent),
|
||||
aBuffer, // XXX aStart always ignored???
|
||||
aLength,
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
|
||||
@ -338,6 +479,18 @@ void
|
||||
nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer, int32_t aStart, int32_t aLength)
|
||||
{
|
||||
NS_PRECONDITION(aBuffer, "Null buffer");
|
||||
MOZ_ASSERT(!aStart, "aStart must always be zero.");
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::AppendCommentToDocument(
|
||||
aBuffer, // XXX aStart always ignored???
|
||||
aLength,
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
@ -356,6 +509,18 @@ nsHtml5TreeBuilder::addAttributesToElement(nsIContentHandle* aElement, nsHtml5Ht
|
||||
if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBuilder) {
|
||||
nsresult rv = nsHtml5TreeOperation::AddAttributes(
|
||||
static_cast<nsIContent*>(aElement),
|
||||
aAttributes,
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(aElement, aAttributes);
|
||||
@ -366,6 +531,11 @@ nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement, "Null element");
|
||||
|
||||
if (mBuilder) {
|
||||
// XXX innerHTML
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpMarkMalformedIfScript, aElement);
|
||||
@ -395,6 +565,19 @@ nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, nsString* aPublicId,
|
||||
{
|
||||
NS_PRECONDITION(aName, "Null name");
|
||||
|
||||
if (mBuilder) {
|
||||
nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName);
|
||||
nsresult rv =
|
||||
nsHtml5TreeOperation::AppendDoctypeToDocument(name,
|
||||
*aPublicId,
|
||||
*aSystemId,
|
||||
mBuilder);
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBrokenAndRequestSuspension(rv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(aName, *aPublicId, *aSystemId);
|
||||
@ -442,6 +625,10 @@ nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsIAtom* aName, nsIContent
|
||||
return;
|
||||
}
|
||||
if (aName == nsHtml5Atoms::body || aName == nsHtml5Atoms::frameset) {
|
||||
if (mBuilder) {
|
||||
// InnerHTML and DOMParser shouldn't start layout anyway
|
||||
return;
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpStartLayout);
|
||||
@ -453,15 +640,27 @@ nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsIAtom* aName, nsIContent
|
||||
// If form inputs don't belong to a form, their state preservation
|
||||
// won't work right without an append notification flush at this
|
||||
// point. See bug 497861.
|
||||
mOpQueue.AppendElement()->Init(eTreeOpFlushPendingAppendNotifications);
|
||||
if (mBuilder) {
|
||||
mBuilder->FlushPendingAppendNotifications();
|
||||
} else {
|
||||
mOpQueue.AppendElement()->Init(eTreeOpFlushPendingAppendNotifications);
|
||||
}
|
||||
}
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent*>(aElement));
|
||||
} else {
|
||||
mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
|
||||
}
|
||||
mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
|
||||
return;
|
||||
}
|
||||
if (aName == nsHtml5Atoms::audio ||
|
||||
aName == nsHtml5Atoms::video ||
|
||||
aName == nsHtml5Atoms::menuitem) {
|
||||
mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent*>(aElement));
|
||||
} else {
|
||||
mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -481,9 +680,16 @@ nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsIAtom* aName, nsIContent
|
||||
// we now have only SVG and HTML
|
||||
if (aName == nsHtml5Atoms::script) {
|
||||
if (mPreventScriptExecution) {
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::PreventScriptExecution(static_cast<nsIContent*>(aElement));
|
||||
return;
|
||||
}
|
||||
mOpQueue.AppendElement()->Init(eTreeOpPreventScriptExecution, aElement);
|
||||
return;
|
||||
}
|
||||
if (mBuilder) {
|
||||
return;
|
||||
}
|
||||
if (mCurrentHtmlScriptIsAsyncOrDefer) {
|
||||
NS_ASSERTION(aNamespace == kNameSpaceID_XHTML,
|
||||
"Only HTML scripts may be async/defer.");
|
||||
@ -500,18 +706,34 @@ nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsIAtom* aName, nsIContent
|
||||
return;
|
||||
}
|
||||
if (aName == nsHtml5Atoms::title) {
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement), mBuilder);
|
||||
return;
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpDoneAddingChildren, aElement);
|
||||
return;
|
||||
}
|
||||
if (aName == nsHtml5Atoms::style || (aNamespace == kNameSpaceID_XHTML && aName == nsHtml5Atoms::link)) {
|
||||
if (mBuilder) {
|
||||
MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
|
||||
"Scripts must be blocked.");
|
||||
mBuilder->FlushPendingAppendNotifications();
|
||||
mBuilder->UpdateStyleSheet(static_cast<nsIContent*>(aElement));
|
||||
return;
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpUpdateStyleSheet, aElement);
|
||||
return;
|
||||
}
|
||||
if (aNamespace == kNameSpaceID_SVG) {
|
||||
if (mBuilder) {
|
||||
// XXX innerHTML
|
||||
// is this ever needed for the on-the-main-thread case
|
||||
return;
|
||||
}
|
||||
if (aName == nsHtml5Atoms::svg) {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
@ -525,6 +747,10 @@ nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsIAtom* aName, nsIContent
|
||||
// XXX expose ElementName group here and do switch
|
||||
if (aName == nsHtml5Atoms::object ||
|
||||
aName == nsHtml5Atoms::applet) {
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement), mBuilder);
|
||||
return;
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpDoneAddingChildren, aElement);
|
||||
@ -536,16 +762,24 @@ nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsIAtom* aName, nsIContent
|
||||
// If form inputs don't belong to a form, their state preservation
|
||||
// won't work right without an append notification flush at this
|
||||
// point. See bug 497861 and bug 539895.
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpFlushPendingAppendNotifications);
|
||||
if (mBuilder) {
|
||||
mBuilder->FlushPendingAppendNotifications();
|
||||
} else {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpFlushPendingAppendNotifications);
|
||||
}
|
||||
}
|
||||
if (mBuilder) {
|
||||
nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement), mBuilder);
|
||||
return;
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpDoneAddingChildren, aElement);
|
||||
return;
|
||||
}
|
||||
if (aName == nsHtml5Atoms::meta && !fragment) {
|
||||
if (aName == nsHtml5Atoms::meta && !fragment && !mBuilder) {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpProcessMeta, aElement);
|
||||
@ -571,6 +805,10 @@ nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf, int32_t aStart, i
|
||||
nsIContentHandle*
|
||||
nsHtml5TreeBuilder::AllocateContentHandle()
|
||||
{
|
||||
if (MOZ_UNLIKELY(mBuilder)) {
|
||||
MOZ_ASSUME_UNREACHABLE("Must never allocate a handle with builder.");
|
||||
return nullptr;
|
||||
}
|
||||
if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
|
||||
mOldHandles.AppendElement(mHandles.forget());
|
||||
mHandles = new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH];
|
||||
@ -595,6 +833,10 @@ nsHtml5TreeBuilder::HasScript()
|
||||
bool
|
||||
nsHtml5TreeBuilder::Flush(bool aDiscretionary)
|
||||
{
|
||||
if (MOZ_UNLIKELY(mBuilder)) {
|
||||
MOZ_ASSUME_UNREACHABLE("Must never flush with builder.");
|
||||
return false;
|
||||
}
|
||||
if (!aDiscretionary ||
|
||||
!(charBufferLen &&
|
||||
currentPtr >= 0 &&
|
||||
@ -621,6 +863,10 @@ nsHtml5TreeBuilder::Flush(bool aDiscretionary)
|
||||
void
|
||||
nsHtml5TreeBuilder::FlushLoads()
|
||||
{
|
||||
if (MOZ_UNLIKELY(mBuilder)) {
|
||||
MOZ_ASSUME_UNREACHABLE("Must never flush loads with builder.");
|
||||
return;
|
||||
}
|
||||
if (!mSpeculativeLoadQueue.IsEmpty()) {
|
||||
mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue);
|
||||
}
|
||||
@ -630,7 +876,9 @@ void
|
||||
nsHtml5TreeBuilder::SetDocumentCharset(nsACString& aCharset,
|
||||
int32_t aCharsetSource)
|
||||
{
|
||||
if (mSpeculativeLoadStage) {
|
||||
if (mBuilder) {
|
||||
mBuilder->SetDocumentCharsetAndSource(aCharset, aCharsetSource);
|
||||
} else if (mSpeculativeLoadStage) {
|
||||
mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset(
|
||||
aCharset, aCharsetSource);
|
||||
} else {
|
||||
@ -642,16 +890,11 @@ nsHtml5TreeBuilder::SetDocumentCharset(nsACString& aCharset,
|
||||
void
|
||||
nsHtml5TreeBuilder::StreamEnded()
|
||||
{
|
||||
// The fragment mode calls DidBuildModel from nsHtml5Parser.
|
||||
// Letting DidBuildModel be called from the executor in the fragment case
|
||||
// confuses the EndLoad logic of nsHTMLDocument, since nsHTMLDocument
|
||||
// thinks it is dealing with document.written content as opposed to
|
||||
// innerHTML content.
|
||||
if (!fragment) {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpStreamEnded);
|
||||
}
|
||||
MOZ_ASSERT(!mBuilder, "Must not call StreamEnded with builder.");
|
||||
MOZ_ASSERT(!fragment, "Must not parse fragments off the main thread.");
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpStreamEnded);
|
||||
}
|
||||
|
||||
void
|
||||
@ -659,6 +902,10 @@ nsHtml5TreeBuilder::NeedsCharsetSwitchTo(const nsACString& aCharset,
|
||||
int32_t aCharsetSource,
|
||||
int32_t aLineNumber)
|
||||
{
|
||||
if (MOZ_UNLIKELY(mBuilder)) {
|
||||
MOZ_ASSUME_UNREACHABLE("Must never switch charset with builder.");
|
||||
return;
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(eTreeOpNeedsCharsetSwitchTo,
|
||||
@ -672,12 +919,20 @@ nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId,
|
||||
bool aError,
|
||||
int32_t aLineNumber)
|
||||
{
|
||||
if (MOZ_UNLIKELY(mBuilder)) {
|
||||
MOZ_ASSUME_UNREACHABLE("Must never complain about charset with builder.");
|
||||
return;
|
||||
}
|
||||
mOpQueue.AppendElement()->Init(aMsgId, aError, aLineNumber);
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeBuilder::AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine)
|
||||
{
|
||||
if (MOZ_UNLIKELY(mBuilder)) {
|
||||
MOZ_ASSUME_UNREACHABLE("Must never use snapshots with builder.");
|
||||
return;
|
||||
}
|
||||
NS_PRECONDITION(HasScript(), "No script to add a snapshot to!");
|
||||
NS_PRECONDITION(aSnapshot, "Got null snapshot.");
|
||||
mOpQueue.ElementAt(mOpQueue.Length() - 1).SetSnapshot(aSnapshot, aLine);
|
||||
@ -686,6 +941,7 @@ nsHtml5TreeBuilder::AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int
|
||||
void
|
||||
nsHtml5TreeBuilder::DropHandles()
|
||||
{
|
||||
MOZ_ASSERT(!mBuilder, "Must not drop handles with builder.");
|
||||
mOldHandles.Clear();
|
||||
mHandlesUsed = 0;
|
||||
}
|
||||
@ -693,6 +949,10 @@ nsHtml5TreeBuilder::DropHandles()
|
||||
void
|
||||
nsHtml5TreeBuilder::MarkAsBroken()
|
||||
{
|
||||
if (MOZ_UNLIKELY(mBuilder)) {
|
||||
MOZ_ASSUME_UNREACHABLE("Must not call this with builder.");
|
||||
return;
|
||||
}
|
||||
mOpQueue.Clear(); // Previous ops don't matter anymore
|
||||
mOpQueue.AppendElement()->Init(eTreeOpMarkAsBroken);
|
||||
}
|
||||
@ -700,6 +960,7 @@ nsHtml5TreeBuilder::MarkAsBroken()
|
||||
void
|
||||
nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle)
|
||||
{
|
||||
MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
|
||||
startTag(nsHtml5ElementName::ELT_TITLE,
|
||||
nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
|
||||
false);
|
||||
@ -726,6 +987,7 @@ nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle)
|
||||
void
|
||||
nsHtml5TreeBuilder::StartPlainText()
|
||||
{
|
||||
MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
|
||||
startTag(nsHtml5ElementName::ELT_LINK,
|
||||
nsHtml5PlainTextUtils::NewLinkAttributes(),
|
||||
false);
|
||||
@ -736,6 +998,7 @@ nsHtml5TreeBuilder::StartPlainText()
|
||||
void
|
||||
nsHtml5TreeBuilder::StartPlainTextBody()
|
||||
{
|
||||
MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
|
||||
startTag(nsHtml5ElementName::ELT_PRE,
|
||||
nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
|
||||
false);
|
||||
@ -746,6 +1009,10 @@ nsHtml5TreeBuilder::StartPlainTextBody()
|
||||
void
|
||||
nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m)
|
||||
{
|
||||
if (mBuilder) {
|
||||
mBuilder->SetDocumentMode(m);
|
||||
return;
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
treeOp->Init(m);
|
||||
@ -754,6 +1021,9 @@ nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m)
|
||||
nsIContentHandle*
|
||||
nsHtml5TreeBuilder::getDocumentFragmentForTemplate(nsIContentHandle* aTemplate)
|
||||
{
|
||||
if (mBuilder) {
|
||||
return nsHtml5TreeOperation::GetDocumentFragmentForTemplate(static_cast<nsIContent*>(aTemplate));
|
||||
}
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||
nsIContentHandle* fragHandle = AllocateContentHandle();
|
||||
@ -764,15 +1034,16 @@ nsHtml5TreeBuilder::getDocumentFragmentForTemplate(nsIContentHandle* aTemplate)
|
||||
nsIContentHandle*
|
||||
nsHtml5TreeBuilder::getFormPointerForContext(nsIContentHandle* aContext)
|
||||
{
|
||||
MOZ_ASSERT(mBuilder, "Must have builder.");
|
||||
if (!aContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// aContext must always be a handle to an element that already exists
|
||||
// in the document. It must never be an empty handle.
|
||||
nsIContent* contextNode = *(static_cast<nsIContent**>(aContext));
|
||||
// aContext must always be an element that already exists
|
||||
// in the document.
|
||||
nsIContent* contextNode = static_cast<nsIContent*>(aContext);
|
||||
nsIContent* currentAncestor = contextNode;
|
||||
|
||||
// We traverse the ancestors of the context node to find the nearest
|
||||
@ -790,9 +1061,7 @@ nsHtml5TreeBuilder::getFormPointerForContext(nsIContentHandle* aContext)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIContentHandle* formPointer = AllocateContentHandle();
|
||||
*(static_cast<nsIContent**>(formPointer)) = nearestForm;
|
||||
return formPointer;
|
||||
return nearestForm;
|
||||
}
|
||||
|
||||
// Error reporting
|
||||
@ -800,6 +1069,7 @@ nsHtml5TreeBuilder::getFormPointerForContext(nsIContentHandle* aContext)
|
||||
void
|
||||
nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter* aHighlighter)
|
||||
{
|
||||
MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
|
||||
mViewSource = aHighlighter;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,11 @@
|
||||
#define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512
|
||||
|
||||
private:
|
||||
nsHtml5OplessBuilder* mBuilder;
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// If mBuilder is not null, the tree op machinery is not in use and
|
||||
// the fields below aren't in use, either.
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
nsHtml5Highlighter* mViewSource;
|
||||
nsTArray<nsHtml5TreeOperation> mOpQueue;
|
||||
nsTArray<nsHtml5SpeculativeLoad> mSpeculativeLoadQueue;
|
||||
@ -13,7 +18,6 @@
|
||||
int32_t mHandlesUsed;
|
||||
nsTArray<nsAutoArrayPtr<nsIContent*> > mOldHandles;
|
||||
nsHtml5TreeOpStage* mSpeculativeLoadStage;
|
||||
nsIContent** mDeepTreeSurrogateParent;
|
||||
bool mCurrentHtmlScriptIsAsyncOrDefer;
|
||||
bool mPreventScriptExecution;
|
||||
#ifdef DEBUG
|
||||
@ -60,8 +64,16 @@
|
||||
accumulateCharacters(aBuf, aStart, aLength);
|
||||
}
|
||||
|
||||
void MarkAsBrokenAndRequestSuspension(nsresult aRv)
|
||||
{
|
||||
mBuilder->MarkAsBroken(aRv);
|
||||
requestSuspension();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder);
|
||||
|
||||
nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
|
||||
nsHtml5TreeOpStage* aStage);
|
||||
|
||||
|
@ -13,8 +13,6 @@
|
||||
#include "nsIMarkupDocumentViewer.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "nsStyleLinkElement.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
@ -62,10 +60,10 @@ class nsHtml5ExecutorReflusher : public nsRunnable
|
||||
static mozilla::LinkedList<nsHtml5TreeOpExecutor>* gBackgroundFlushList = nullptr;
|
||||
static nsITimer* gFlushTimer = nullptr;
|
||||
|
||||
nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor(bool aRunsToCompletion)
|
||||
: mPreloadedURLs(23) // Mean # of preloadable resources per page on dmoz
|
||||
nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor()
|
||||
: nsHtml5DocumentBuilder(false)
|
||||
, mPreloadedURLs(23) // Mean # of preloadable resources per page on dmoz
|
||||
{
|
||||
mRunsToCompletion = aRunsToCompletion;
|
||||
// zeroing operator new for everything else
|
||||
}
|
||||
|
||||
@ -210,34 +208,16 @@ nsHtml5TreeOpExecutor::FlushPendingNotifications(mozFlushType aType)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource)
|
||||
{
|
||||
if (mDocument) {
|
||||
mDocument->SetDocumentCharacterSetSource(aCharsetSource);
|
||||
mDocument->SetDocumentCharacterSet(aCharset);
|
||||
}
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
nsHtml5TreeOpExecutor::GetTarget()
|
||||
{
|
||||
return mDocument;
|
||||
}
|
||||
|
||||
// nsContentSink overrides
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::UpdateChildCounts()
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHtml5TreeOpExecutor::MarkAsBroken(nsresult aReason)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!mRunsToCompletion, "Fragment parsers can't be broken!");
|
||||
mBroken = aReason;
|
||||
if (mStreamParser) {
|
||||
mStreamParser->Terminate();
|
||||
@ -255,12 +235,6 @@ nsHtml5TreeOpExecutor::MarkAsBroken(nsresult aReason)
|
||||
return aReason;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHtml5TreeOpExecutor::FlushTags()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FlushTimerCallback(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
@ -303,61 +277,6 @@ nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::UpdateStyleSheet(nsIContent* aElement)
|
||||
{
|
||||
// Break out of the doc update created by Flush() to zap a runnable
|
||||
// waiting to call UpdateStyleSheet without the right observer
|
||||
EndDocUpdate();
|
||||
|
||||
if (MOZ_UNLIKELY(!mParser)) {
|
||||
// EndDocUpdate ran stuff that called nsIParser::Terminate()
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aElement));
|
||||
NS_ASSERTION(ssle, "Node didn't QI to style.");
|
||||
|
||||
ssle->SetEnableUpdates(true);
|
||||
|
||||
bool willNotify;
|
||||
bool isAlternate;
|
||||
nsresult rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this,
|
||||
&willNotify,
|
||||
&isAlternate);
|
||||
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) {
|
||||
++mPendingSheetCount;
|
||||
mScriptLoader->AddExecuteBlocker();
|
||||
}
|
||||
|
||||
if (aElement->IsHTML(nsGkAtoms::link)) {
|
||||
// look for <link rel="next" href="url">
|
||||
nsAutoString relVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
|
||||
if (!relVal.IsEmpty()) {
|
||||
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
|
||||
bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
|
||||
if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
|
||||
nsAutoString hrefVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchHref(hrefVal, aElement, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-open update
|
||||
BeginDocUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::FlushSpeculativeLoads()
|
||||
{
|
||||
@ -665,26 +584,6 @@ nsHtml5TreeOpExecutor::IsScriptEnabled()
|
||||
ScriptAllowed(globalObject->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::SetDocumentMode(nsHtml5DocumentMode m)
|
||||
{
|
||||
nsCompatibility mode = eCompatibility_NavQuirks;
|
||||
switch (m) {
|
||||
case STANDARDS_MODE:
|
||||
mode = eCompatibility_FullStandards;
|
||||
break;
|
||||
case ALMOST_STANDARDS_MODE:
|
||||
mode = eCompatibility_AlmostStandards;
|
||||
break;
|
||||
case QUIRKS_MODE:
|
||||
mode = eCompatibility_NavQuirks;
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(mDocument);
|
||||
NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document.");
|
||||
htmlDocument->SetCompatibilityMode(mode);
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::StartLayout() {
|
||||
if (mLayoutStarted || !mDocument) {
|
||||
@ -767,15 +666,6 @@ nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHtml5TreeOpExecutor::Init(nsIDocument* aDoc,
|
||||
nsIURI* aURI,
|
||||
nsISupports* aContainer,
|
||||
nsIChannel* aChannel)
|
||||
{
|
||||
return nsContentSink::Init(aDoc, aURI, aContainer, aChannel);
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::Start()
|
||||
{
|
||||
@ -882,19 +772,6 @@ nsHtml5TreeOpExecutor::GetParser()
|
||||
return static_cast<nsHtml5Parser*>(mParser.get());
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::Reset()
|
||||
{
|
||||
MOZ_ASSERT(mRunsToCompletion);
|
||||
DropHeldElements();
|
||||
mOpQueue.Clear();
|
||||
mStarted = false;
|
||||
mFlushState = eNotFlushing;
|
||||
mRunFlushLoopOnStack = false;
|
||||
MOZ_ASSERT(!mReadingFromStage);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(mBroken));
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOpExecutor::MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue)
|
||||
{
|
||||
|
@ -80,19 +80,6 @@ class nsHtml5TreeOpExecutor : public nsHtml5DocumentBuilder,
|
||||
|
||||
bool mCallContinueInterruptedParsingIfEnabled;
|
||||
|
||||
/**
|
||||
* Non-NS_OK if this parser should refuse to process any more input.
|
||||
* For example, the parser needs to be marked as broken if it drops some
|
||||
* input due to a memory allocation failure. In such a case, the whole
|
||||
* parser needs to be marked as broken, because some input has been lost
|
||||
* and parsing more input could lead to a DOM where pieces of HTML source
|
||||
* that weren't supposed to become scripts become scripts.
|
||||
*
|
||||
* Since NS_OK is actually 0, zeroing operator new takes care of
|
||||
* initializing this.
|
||||
*/
|
||||
nsresult mBroken;
|
||||
|
||||
/**
|
||||
* Whether this executor has already complained about matters related
|
||||
* to character encoding declarations.
|
||||
@ -101,7 +88,7 @@ class nsHtml5TreeOpExecutor : public nsHtml5DocumentBuilder,
|
||||
|
||||
public:
|
||||
|
||||
nsHtml5TreeOpExecutor(bool aRunsToCompletion = false);
|
||||
nsHtml5TreeOpExecutor();
|
||||
virtual ~nsHtml5TreeOpExecutor();
|
||||
|
||||
// nsIContentSink
|
||||
@ -154,16 +141,8 @@ class nsHtml5TreeOpExecutor : public nsHtml5DocumentBuilder,
|
||||
*/
|
||||
virtual nsISupports *GetTarget();
|
||||
|
||||
// nsContentSink methods
|
||||
virtual void UpdateChildCounts();
|
||||
virtual nsresult FlushTags();
|
||||
virtual void ContinueInterruptedParsingAsync();
|
||||
|
||||
/**
|
||||
* Sets up style sheet load / parse
|
||||
*/
|
||||
void UpdateStyleSheet(nsIContent* aElement);
|
||||
|
||||
// XXX Does anyone need this?
|
||||
nsIDocShell* GetDocShell() {
|
||||
return mDocShell;
|
||||
@ -172,14 +151,8 @@ class nsHtml5TreeOpExecutor : public nsHtml5DocumentBuilder,
|
||||
bool IsScriptExecuting() {
|
||||
return IsScriptExecutingImpl();
|
||||
}
|
||||
|
||||
void SetNodeInfoManager(nsNodeInfoManager* aManager) {
|
||||
mNodeInfoManager = aManager;
|
||||
}
|
||||
|
||||
// Not from interface
|
||||
|
||||
void SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource);
|
||||
// Not from interface
|
||||
|
||||
void SetStreamParser(nsHtml5StreamParser* aStreamParser) {
|
||||
mStreamParser = aStreamParser;
|
||||
@ -189,50 +162,10 @@ class nsHtml5TreeOpExecutor : public nsHtml5DocumentBuilder,
|
||||
|
||||
bool IsScriptEnabled();
|
||||
|
||||
bool BelongsToStringParser() {
|
||||
return mRunsToCompletion;
|
||||
}
|
||||
virtual nsresult MarkAsBroken(nsresult aReason);
|
||||
|
||||
/**
|
||||
* Marks this parser as broken and tells the stream parser (if any) to
|
||||
* terminate.
|
||||
*
|
||||
* @return aReason for convenience
|
||||
*/
|
||||
nsresult MarkAsBroken(nsresult aReason);
|
||||
|
||||
/**
|
||||
* Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
|
||||
* value if broken.
|
||||
*/
|
||||
inline nsresult IsBroken() {
|
||||
return mBroken;
|
||||
}
|
||||
|
||||
inline void BeginDocUpdate() {
|
||||
NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
|
||||
NS_PRECONDITION(mParser, "Started update without parser.");
|
||||
mFlushState = eInDocUpdate;
|
||||
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
inline void EndDocUpdate() {
|
||||
NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
|
||||
if (mFlushState == eInDocUpdate) {
|
||||
FlushPendingAppendNotifications();
|
||||
mFlushState = eInFlush;
|
||||
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StartLayout();
|
||||
|
||||
void SetDocumentMode(nsHtml5DocumentMode m);
|
||||
|
||||
nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
|
||||
nsISupports* aContainer, nsIChannel* aChannel);
|
||||
|
||||
void FlushSpeculativeLoads();
|
||||
|
||||
void RunFlushLoop();
|
||||
@ -273,8 +206,6 @@ class nsHtml5TreeOpExecutor : public nsHtml5DocumentBuilder,
|
||||
|
||||
void RunScript(nsIContent* aScriptElement);
|
||||
|
||||
void Reset();
|
||||
|
||||
/**
|
||||
* Flush the operations from the tree operations from the argument
|
||||
* queue unconditionally. (This is for the main thread case.)
|
||||
|
@ -344,7 +344,7 @@ nsIContent*
|
||||
nsHtml5TreeOperation::CreateElement(int32_t aNs,
|
||||
nsIAtom* aName,
|
||||
nsHtml5HtmlAttributes* aAttributes,
|
||||
bool aFromNetwork,
|
||||
mozilla::dom::FromParser aFromParser,
|
||||
nsHtml5DocumentBuilder* aBuilder)
|
||||
{
|
||||
bool isKeygen = (aName == nsHtml5Atoms::keygen && aNs == kNameSpaceID_XHTML);
|
||||
@ -358,11 +358,7 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
|
||||
NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
|
||||
NS_NewElement(getter_AddRefs(newContent),
|
||||
nodeInfo.forget(),
|
||||
(aFromNetwork ?
|
||||
dom::FROM_PARSER_NETWORK
|
||||
: (aBuilder->BelongsToStringParser() ?
|
||||
dom::FROM_PARSER_FRAGMENT :
|
||||
dom::FROM_PARSER_DOCUMENT_WRITE)));
|
||||
aFromParser);
|
||||
NS_ASSERTION(newContent, "Element creation created null pointer.");
|
||||
|
||||
aBuilder->HoldElement(newContent);
|
||||
@ -406,11 +402,7 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
|
||||
nsCOMPtr<nsINodeInfo> ni = optionNodeInfo;
|
||||
NS_NewElement(getter_AddRefs(optionElt),
|
||||
ni.forget(),
|
||||
(aFromNetwork ?
|
||||
dom::FROM_PARSER_NETWORK
|
||||
: (aBuilder->BelongsToStringParser() ?
|
||||
dom::FROM_PARSER_FRAGMENT :
|
||||
dom::FROM_PARSER_DOCUMENT_WRITE)));
|
||||
aFromParser);
|
||||
nsRefPtr<nsTextNode> optionText =
|
||||
new nsTextNode(aBuilder->GetNodeInfoManager());
|
||||
(void) optionText->SetText(theContent[i], false);
|
||||
@ -674,7 +666,9 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
|
||||
*target = CreateElement(ns,
|
||||
name,
|
||||
attributes,
|
||||
mOpCode == eTreeOpCreateElementNetwork,
|
||||
mOpCode == eTreeOpCreateElementNetwork ?
|
||||
dom::FROM_PARSER_NETWORK :
|
||||
dom::FROM_PARSER_DOCUMENT_WRITE,
|
||||
aBuilder);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "nsHtml5DocumentMode.h"
|
||||
#include "nsHtml5HtmlAttributes.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
#include "mozilla/dom/FromParser.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsHtml5TreeOpExecutor;
|
||||
@ -146,7 +147,7 @@ class nsHtml5TreeOperation {
|
||||
static nsIContent* CreateElement(int32_t aNs,
|
||||
nsIAtom* aName,
|
||||
nsHtml5HtmlAttributes* aAttributes,
|
||||
bool aFromNetwork,
|
||||
mozilla::dom::FromParser aFromParser,
|
||||
nsHtml5DocumentBuilder* aBuilder);
|
||||
|
||||
static void SetFormElement(nsIContent* aNode, nsIContent* aParent);
|
||||
|
Loading…
Reference in New Issue
Block a user