mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 15:15:23 +00:00
Add notification batching to HTML5
This commit is contained in:
parent
fb89a672c3
commit
3e559d71fd
@ -85,6 +85,7 @@ CPPSRCS = \
|
||||
nsHtml5ReleasableElementName.cpp \
|
||||
nsHtml5MetaScanner.cpp \
|
||||
nsHtml5TreeOperation.cpp \
|
||||
nsHtml5PendingNotification.cpp \
|
||||
$(NULL)
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
45
content/html/parser/src/nsHtml5PendingNotification.cpp
Normal file
45
content/html/parser/src/nsHtml5PendingNotification.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is HTML Parser C++ Translator code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Henri Sivonen <hsivonen@iki.fi>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsHtml5TreeBuilder.h"
|
||||
#include "nsHtml5PendingNotification.h"
|
||||
|
||||
void
|
||||
nsHtml5PendingNotification::Fire(nsHtml5TreeBuilder* aBuilder)
|
||||
{
|
||||
aBuilder->NotifyAppend(mParent, mChildCount);
|
||||
}
|
63
content/html/parser/src/nsHtml5PendingNotification.h
Normal file
63
content/html/parser/src/nsHtml5PendingNotification.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is HTML Parser C++ Translator code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Henri Sivonen <hsivonen@iki.fi>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsHtml5PendingNotification_h__
|
||||
#define nsHtml5PendingNotification_h__
|
||||
|
||||
class nsHtml5TreeBuilder;
|
||||
|
||||
class nsHtml5PendingNotification {
|
||||
public:
|
||||
nsHtml5PendingNotification(nsIContent* aParent)
|
||||
: mParent(aParent),
|
||||
mChildCount(aParent->GetChildCount())
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsHtml5PendingNotification);
|
||||
}
|
||||
~nsHtml5PendingNotification() {
|
||||
MOZ_COUNT_DTOR(nsHtml5PendingNotification);
|
||||
}
|
||||
void Fire(nsHtml5TreeBuilder* aBuilder);
|
||||
inline PRBool Contains(nsIContent* aNode) {
|
||||
return !!(mParent == aNode);
|
||||
}
|
||||
private:
|
||||
nsIContent* mParent;
|
||||
PRUint32 mChildCount;
|
||||
};
|
||||
|
||||
#endif // nsHtml5PendingNotification_h__
|
@ -47,6 +47,7 @@
|
||||
#include "nsHtml5Atoms.h"
|
||||
#include "nsHtml5ByteReadable.h"
|
||||
#include "nsHtml5TreeOperation.h"
|
||||
#include "nsHtml5PendingNotification.h"
|
||||
|
||||
class nsHtml5Parser;
|
||||
|
||||
@ -59,6 +60,8 @@ class nsHtml5StackNode;
|
||||
class nsHtml5UTF16Buffer;
|
||||
class nsHtml5Portability;
|
||||
|
||||
typedef nsIContent* nsIContentPtr;
|
||||
|
||||
class nsHtml5TreeBuilder
|
||||
{
|
||||
private:
|
||||
|
@ -252,7 +252,7 @@ nsHtml5TreeBuilder::start(PRBool fragment)
|
||||
void
|
||||
nsHtml5TreeBuilder::end()
|
||||
{
|
||||
mOpQueue.Clear();
|
||||
Flush();
|
||||
}
|
||||
|
||||
void
|
||||
@ -441,9 +441,12 @@ nsHtml5TreeBuilder::Flush()
|
||||
{
|
||||
if (!mFlushing) {
|
||||
mFlushing = PR_TRUE;
|
||||
for (PRUint32 i = 0; i < mOpQueue.Length(); ++i) {
|
||||
mOpQueue[i].Perform(this);
|
||||
const nsHtml5TreeOperation* start = mOpQueue.Elements();
|
||||
const nsHtml5TreeOperation* end = start + mOpQueue.Length();
|
||||
for (nsHtml5TreeOperation* iter = (nsHtml5TreeOperation*)start; iter < end; ++iter) {
|
||||
iter->Perform(this);
|
||||
}
|
||||
FlushPendingAppendNotifications();
|
||||
mOpQueue.Clear();
|
||||
mFlushing = PR_FALSE;
|
||||
}
|
||||
|
@ -39,24 +39,76 @@
|
||||
nsHtml5Parser* mParser; // weak ref
|
||||
PRBool mHasProcessedBase;
|
||||
PRBool mFlushing;
|
||||
nsTArray<nsHtml5TreeOperation> mOpQueue;
|
||||
nsTArray<nsHtml5TreeOperation> mOpQueue;
|
||||
nsTArray<nsIContentPtr> mElementsSeenInThisAppendBatch;
|
||||
nsTArray<nsHtml5PendingNotification> mPendingNotifications;
|
||||
void MaybeFlushAndMaybeSuspend();
|
||||
public:
|
||||
nsHtml5TreeBuilder(nsHtml5Parser* aParser);
|
||||
~nsHtml5TreeBuilder();
|
||||
void Flush();
|
||||
|
||||
inline void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild) {
|
||||
nsIContent* parent = aParent; // this gets nulled when found
|
||||
nsIContent* child = aChild->IsNodeOfType(nsINode::eELEMENT) ? aChild : nsnull; // this gets nulled when found
|
||||
const nsIContentPtr* start = mElementsSeenInThisAppendBatch.Elements();
|
||||
const nsIContentPtr* end = start + mElementsSeenInThisAppendBatch.Length();
|
||||
// XXX backwards iterate
|
||||
for (const nsIContentPtr* iter = start; iter < end; ++iter) {
|
||||
if (*iter == parent) {
|
||||
parent = nsnull;
|
||||
}
|
||||
if (*iter == child) {
|
||||
child = nsnull;
|
||||
}
|
||||
if (!(parent || child)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (child) {
|
||||
mElementsSeenInThisAppendBatch.AppendElement(child);
|
||||
}
|
||||
if (parent) {
|
||||
// parents that are in mPendingNotifications don't need to be added to
|
||||
// mElementsSeenInThisAppendBatch
|
||||
const nsHtml5PendingNotification* startNotifications = mPendingNotifications.Elements();
|
||||
const nsHtml5PendingNotification* endNotifications = startNotifications + mPendingNotifications.Length();
|
||||
// XXX backwards iterate
|
||||
for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)startNotifications; iter < endNotifications; ++iter) {
|
||||
if (iter->Contains(parent)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mPendingNotifications.AppendElement(parent);
|
||||
}
|
||||
}
|
||||
|
||||
inline void FlushPendingAppendNotifications() {
|
||||
const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
|
||||
const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
|
||||
for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
|
||||
iter->Fire(this);
|
||||
}
|
||||
mPendingNotifications.Clear();
|
||||
mElementsSeenInThisAppendBatch.Clear();
|
||||
}
|
||||
|
||||
inline void NotifyAppend(nsIContent* aParent, PRUint32 aChildCount) {
|
||||
mParser->NotifyAppend(aParent, aChildCount);
|
||||
}
|
||||
|
||||
inline nsIDocument* GetDocument() {
|
||||
return mParser->GetDocument();
|
||||
}
|
||||
|
||||
inline void SetScriptElement(nsIContent* aScript) {
|
||||
mParser->SetScriptElement(aScript);
|
||||
}
|
||||
|
||||
inline void UpdateStyleSheet(nsIContent* aSheet) {
|
||||
mParser->UpdateStyleSheet(aSheet);
|
||||
}
|
||||
|
||||
inline nsresult ProcessBase(nsIContent* aBase) {
|
||||
if (!mHasProcessedBase) {
|
||||
nsresult rv = mParser->ProcessBASETag(aBase);
|
||||
@ -65,6 +117,7 @@
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
inline void StartLayout() {
|
||||
mParser->StartLayout(PR_FALSE);
|
||||
}
|
||||
|
@ -60,14 +60,12 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeBuilder* aBuilder)
|
||||
nsresult rv = NS_OK;
|
||||
switch(mOpCode) {
|
||||
case eTreeOpAppend: {
|
||||
PRUint32 childCount = mParent->GetChildCount();
|
||||
aBuilder->PostPendingAppendNotification(mParent, mNode);
|
||||
rv = mParent->AppendChildTo(mNode, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// XXX move notify away
|
||||
aBuilder->NotifyAppend(mParent, childCount);
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpDetach: {
|
||||
aBuilder->FlushPendingAppendNotifications();
|
||||
nsIContent* parent = mNode->GetParent();
|
||||
if (parent) {
|
||||
PRUint32 pos = parent->IndexOf(mNode);
|
||||
@ -79,14 +77,19 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeBuilder* aBuilder)
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpAppendChildrenToNewParent: {
|
||||
aBuilder->FlushPendingAppendNotifications();
|
||||
PRUint32 childCount = mParent->GetChildCount();
|
||||
PRBool didAppend = PR_FALSE;
|
||||
while (mNode->GetChildCount()) {
|
||||
nsCOMPtr<nsIContent> child = mNode->GetChildAt(0);
|
||||
rv = mNode->RemoveChildAt(0, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsNodeUtils::ContentRemoved(mNode, child, 0);
|
||||
PRUint32 childCount = mParent->GetChildCount();
|
||||
rv = mParent->AppendChildTo(child, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
didAppend = PR_TRUE;
|
||||
}
|
||||
if (didAppend) {
|
||||
aBuilder->NotifyAppend(mParent, childCount);
|
||||
}
|
||||
return rv;
|
||||
@ -94,19 +97,19 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeBuilder* aBuilder)
|
||||
case eTreeOpFosterParent: {
|
||||
nsIContent* parent = mTable->GetParent();
|
||||
if (parent && parent->IsNodeOfType(nsINode::eELEMENT)) {
|
||||
aBuilder->FlushPendingAppendNotifications();
|
||||
PRUint32 pos = parent->IndexOf(mTable);
|
||||
rv = parent->InsertChildAt(mNode, pos, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsNodeUtils::ContentInserted(parent, mNode, pos);
|
||||
} else {
|
||||
PRUint32 childCount = mParent->GetChildCount();
|
||||
aBuilder->PostPendingAppendNotification(mParent, mNode);
|
||||
rv = mParent->AppendChildTo(mNode, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aBuilder->NotifyAppend(mParent, childCount);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpAppendToDocument: {
|
||||
aBuilder->FlushPendingAppendNotifications();
|
||||
nsIDocument* doc = aBuilder->GetDocument();
|
||||
PRUint32 childCount = doc->GetChildCount();
|
||||
rv = doc->AppendChildTo(mNode, PR_FALSE);
|
||||
@ -135,18 +138,22 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeBuilder* aBuilder)
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpDoneAddingChildren: {
|
||||
mNode->DoneAddingChildren(PR_TRUE);
|
||||
// aBuilder->FlushPendingAppendNotifications();
|
||||
mNode->DoneAddingChildren(PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpUpdateStyleSheet: {
|
||||
// aBuilder->FlushPendingAppendNotifications();
|
||||
aBuilder->UpdateStyleSheet(mNode);
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpProcessBase: {
|
||||
// aBuilder->FlushPendingAppendNotifications();
|
||||
rv = aBuilder->ProcessBase(mNode);
|
||||
return rv;
|
||||
}
|
||||
case eTreeOpStartLayout: {
|
||||
aBuilder->FlushPendingAppendNotifications();
|
||||
aBuilder->StartLayout();
|
||||
return rv;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user