mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1398605, keep nsContentList objects alive for awhile when generating state keys so that new objects don't need to be created all the time, r=ehsan
--HG-- extra : rebase_source : 8ba989365f0c9b5fbacc9effd4a41b628614b788
This commit is contained in:
parent
a70175c241
commit
61679d58d1
@ -3054,33 +3054,10 @@ nsContentUtils::GenerateStateKey(nsIContent* aContent,
|
||||
|
||||
if (htmlDocument) {
|
||||
nsHTMLDocument* htmlDoc = static_cast<nsHTMLDocument*> (htmlDocument.get());
|
||||
// Flush our content model so it'll be up to date
|
||||
// If this becomes unnecessary and the following line is removed,
|
||||
// please also remove the corresponding flush operation from
|
||||
// nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
|
||||
aContent->GetUncomposedDoc()->FlushPendingNotifications(FlushType::Content);
|
||||
|
||||
RefPtr<nsContentList> htmlForms = htmlDoc->GetExistingForms();
|
||||
if (!htmlForms) {
|
||||
// If the document doesn't have an existing forms content list, create a
|
||||
// new one, but avoid creating a live list since we only need to use the
|
||||
// list here and it doesn't need to listen to mutation events.
|
||||
|
||||
// Please keep this in sync with nsHTMLDocument::GetForms().
|
||||
htmlForms = new nsContentList(aDocument, kNameSpaceID_XHTML,
|
||||
nsGkAtoms::form, nsGkAtoms::form,
|
||||
/* aDeep = */ true,
|
||||
/* aLiveList = */ false);
|
||||
}
|
||||
RefPtr<nsContentList> htmlFormControls =
|
||||
new nsContentList(aDocument,
|
||||
nsHTMLDocument::MatchFormControls,
|
||||
nullptr, nullptr,
|
||||
/* aDeep = */ true,
|
||||
/* aMatchAtom = */ nullptr,
|
||||
/* aMatchNameSpaceId = */ kNameSpaceID_None,
|
||||
/* aFuncMayDependOnAttr = */ true,
|
||||
/* aLiveList = */ false);
|
||||
RefPtr<nsContentList> htmlForms;
|
||||
RefPtr<nsContentList> htmlFormControls;
|
||||
htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
|
||||
getter_AddRefs(htmlFormControls));
|
||||
|
||||
// If we have a form control and can calculate form information, use that
|
||||
// as the key - it is more reliable than just recording position in the
|
||||
|
@ -174,6 +174,7 @@ NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
|
||||
|
||||
nsHTMLDocument::nsHTMLDocument()
|
||||
: nsDocument("text/html")
|
||||
, mContentListHolder(nullptr)
|
||||
, mNumForms(0)
|
||||
, mWriteLevel(0)
|
||||
, mLoadFlags(0)
|
||||
@ -3754,3 +3755,50 @@ nsHTMLDocument::WillIgnoreCharsetOverride()
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::GetFormsAndFormControls(nsContentList** aFormList,
|
||||
nsContentList** aFormControlList)
|
||||
{
|
||||
RefPtr<ContentListHolder> holder = mContentListHolder;
|
||||
if (!holder) {
|
||||
// Flush our content model so it'll be up to date
|
||||
// If this becomes unnecessary and the following line is removed,
|
||||
// please also remove the corresponding flush operation from
|
||||
// nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
|
||||
//XXXsmaug nsHtml5TreeBuilderCppSupplement doesn't seem to have such flush
|
||||
// anymore.
|
||||
FlushPendingNotifications(FlushType::Content);
|
||||
|
||||
RefPtr<nsContentList> htmlForms = GetExistingForms();
|
||||
if (!htmlForms) {
|
||||
// If the document doesn't have an existing forms content list, create a
|
||||
// new one which will be released soon by ContentListHolder.
|
||||
// Please keep this in sync with nsHTMLDocument::GetForms().
|
||||
htmlForms = new nsContentList(this, kNameSpaceID_XHTML,
|
||||
nsGkAtoms::form, nsGkAtoms::form,
|
||||
/* aDeep = */ true,
|
||||
/* aLiveList = */ true);
|
||||
}
|
||||
|
||||
RefPtr<nsContentList> htmlFormControls =
|
||||
new nsContentList(this,
|
||||
nsHTMLDocument::MatchFormControls,
|
||||
nullptr, nullptr,
|
||||
/* aDeep = */ true,
|
||||
/* aMatchAtom = */ nullptr,
|
||||
/* aMatchNameSpaceId = */ kNameSpaceID_None,
|
||||
/* aFuncMayDependOnAttr = */ true,
|
||||
/* aLiveList = */ true);
|
||||
|
||||
holder = new ContentListHolder(this, htmlForms, htmlFormControls);
|
||||
RefPtr<ContentListHolder> runnable = holder;
|
||||
if (NS_SUCCEEDED(Dispatch(TaskCategory::GarbageCollection,
|
||||
runnable.forget()))) {
|
||||
mContentListHolder = holder;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aFormList = holder->mFormList);
|
||||
NS_ADDREF(*aFormControlList = holder->mFormControlList);
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
#include "PLDHashTable.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsHTMLStyleSheet.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsICommandManager.h"
|
||||
#include "mozilla/dom/HTMLSharedElement.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
@ -266,6 +266,8 @@ public:
|
||||
static bool MatchFormControls(Element* aElement, int32_t aNamespaceID,
|
||||
nsIAtom* aAtom, void* aData);
|
||||
|
||||
void GetFormsAndFormControls(nsContentList** aFormList,
|
||||
nsContentList** aFormControlList);
|
||||
protected:
|
||||
~nsHTMLDocument();
|
||||
|
||||
@ -312,6 +314,37 @@ protected:
|
||||
|
||||
void *GenerateParserKey(void);
|
||||
|
||||
// A helper class to keep nsContentList objects alive for a short period of
|
||||
// time. Note, when the final Release is called on an nsContentList object, it
|
||||
// removes itself from MutationObserver list.
|
||||
class ContentListHolder : public mozilla::Runnable
|
||||
{
|
||||
public:
|
||||
ContentListHolder(nsHTMLDocument* aDocument,
|
||||
nsContentList* aFormList,
|
||||
nsContentList* aFormControlList)
|
||||
: mozilla::Runnable("ContentListHolder")
|
||||
, mDocument(aDocument)
|
||||
, mFormList(aFormList)
|
||||
, mFormControlList(aFormControlList)
|
||||
{
|
||||
}
|
||||
|
||||
~ContentListHolder()
|
||||
{
|
||||
MOZ_ASSERT(!mDocument->mContentListHolder ||
|
||||
mDocument->mContentListHolder == this);
|
||||
mDocument->mContentListHolder = nullptr;
|
||||
}
|
||||
|
||||
RefPtr<nsHTMLDocument> mDocument;
|
||||
RefPtr<nsContentList> mFormList;
|
||||
RefPtr<nsContentList> mFormControlList;
|
||||
};
|
||||
|
||||
friend class ContentListHolder;
|
||||
ContentListHolder* mContentListHolder;
|
||||
|
||||
RefPtr<nsContentList> mImages;
|
||||
RefPtr<nsEmptyContentList> mApplets;
|
||||
RefPtr<nsContentList> mEmbeds;
|
||||
|
Loading…
Reference in New Issue
Block a user