Bug 1422653: Compute whether XBL is involved in ChildIterator lazily. r=mats

The only thing that cares about it is the frame constructor, it's a shame that
everyone else (in particular, the style system) needs to pay this extra walk
over the DOM.

MozReview-Commit-ID: F7S5zx9KMlp
This commit is contained in:
Emilio Cobos Álvarez 2018-02-25 18:55:29 +01:00
Родитель bd1d30c860
Коммит c3209ce172
2 изменённых файлов: 43 добавлений и 27 удалений

Просмотреть файл

@ -124,6 +124,7 @@ void
FlattenedChildIterator::Init(bool aIgnoreXBL) FlattenedChildIterator::Init(bool aIgnoreXBL)
{ {
if (aIgnoreXBL) { if (aIgnoreXBL) {
mXBLInvolved = Some(false);
return; return;
} }
@ -132,7 +133,7 @@ FlattenedChildIterator::Init(bool aIgnoreXBL)
if (mParent->IsElement()) { if (mParent->IsElement()) {
if (ShadowRoot* shadow = mParent->AsElement()->GetShadowRoot()) { if (ShadowRoot* shadow = mParent->AsElement()->GetShadowRoot()) {
mParent = shadow; mParent = shadow;
mXBLInvolved = true; mXBLInvolved = Some(true);
return; return;
} }
} }
@ -143,25 +144,31 @@ FlattenedChildIterator::Init(bool aIgnoreXBL)
if (binding) { if (binding) {
MOZ_ASSERT(binding->GetAnonymousContent()); MOZ_ASSERT(binding->GetAnonymousContent());
mParent = binding->GetAnonymousContent(); mParent = binding->GetAnonymousContent();
mXBLInvolved = true; mXBLInvolved = Some(true);
}
}
bool
FlattenedChildIterator::ComputeWhetherXBLIsInvolved() const
{
MOZ_ASSERT(mXBLInvolved.isNothing());
// We set mXBLInvolved to true if either the node we're iterating has a
// binding with content attached to it (in which case it is handled in Init),
// or the node is generated XBL content and has an <xbl:children> child.
if (!mParent->GetBindingParent()) {
return false;
} }
// We set mXBLInvolved to true if either: for (nsIContent* child = mParent->GetFirstChild();
// - The node we're iterating has a binding with content attached to it. child;
// - The node is generated XBL content and has an <xbl:children> child. child = child->GetNextSibling()) {
// if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
// FIXME(emilio): This is very slow :( MOZ_ASSERT(child->GetBindingParent());
if (!mXBLInvolved && mParent->GetBindingParent()) { return true;
for (nsIContent* child = mParent->GetFirstChild();
child;
child = child->GetNextSibling()) {
if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
MOZ_ASSERT(child->GetBindingParent());
mXBLInvolved = true;
break;
}
} }
} }
return false;
} }
bool bool

Просмотреть файл

@ -134,7 +134,6 @@ public:
explicit FlattenedChildIterator(const nsIContent* aParent, explicit FlattenedChildIterator(const nsIContent* aParent,
bool aStartAtBeginning = true) bool aStartAtBeginning = true)
: ExplicitChildIterator(aParent, aStartAtBeginning) : ExplicitChildIterator(aParent, aStartAtBeginning)
, mXBLInvolved(false)
, mOriginalContent(aParent) , mOriginalContent(aParent)
{ {
Init(false); Init(false);
@ -142,20 +141,30 @@ public:
FlattenedChildIterator(FlattenedChildIterator&& aOther) FlattenedChildIterator(FlattenedChildIterator&& aOther)
: ExplicitChildIterator(Move(aOther)) : ExplicitChildIterator(Move(aOther))
, mXBLInvolved(aOther.mXBLInvolved)
, mOriginalContent(aOther.mOriginalContent) , mOriginalContent(aOther.mOriginalContent)
, mXBLInvolved(aOther.mXBLInvolved)
{} {}
FlattenedChildIterator(const FlattenedChildIterator& aOther) FlattenedChildIterator(const FlattenedChildIterator& aOther)
: ExplicitChildIterator(aOther) : ExplicitChildIterator(aOther)
, mXBLInvolved(aOther.mXBLInvolved)
, mOriginalContent(aOther.mOriginalContent) , mOriginalContent(aOther.mOriginalContent)
, mXBLInvolved(aOther.mXBLInvolved)
{} {}
bool XBLInvolved() { return mXBLInvolved; } bool XBLInvolved() {
if (mXBLInvolved.isNothing()) {
mXBLInvolved = Some(ComputeWhetherXBLIsInvolved());
}
return *mXBLInvolved;
}
const nsIContent* Parent() const { return mOriginalContent; } const nsIContent* Parent() const { return mOriginalContent; }
private:
bool ComputeWhetherXBLIsInvolved() const;
void Init(bool aIgnoreXBL);
protected: protected:
/** /**
* This constructor is a hack to help AllChildrenIterator which sometimes * This constructor is a hack to help AllChildrenIterator which sometimes
@ -164,20 +173,20 @@ protected:
FlattenedChildIterator(const nsIContent* aParent, uint32_t aFlags, FlattenedChildIterator(const nsIContent* aParent, uint32_t aFlags,
bool aStartAtBeginning = true) bool aStartAtBeginning = true)
: ExplicitChildIterator(aParent, aStartAtBeginning) : ExplicitChildIterator(aParent, aStartAtBeginning)
, mXBLInvolved(false)
, mOriginalContent(aParent) , mOriginalContent(aParent)
{ {
bool ignoreXBL = aFlags & nsIContent::eAllButXBL; bool ignoreXBL = aFlags & nsIContent::eAllButXBL;
Init(ignoreXBL); Init(ignoreXBL);
} }
void Init(bool aIgnoreXBL);
// For certain optimizations, nsCSSFrameConstructor needs to know if the
// child list of the element that we're iterating matches its .childNodes.
bool mXBLInvolved;
const nsIContent* mOriginalContent; const nsIContent* mOriginalContent;
private:
// For certain optimizations, nsCSSFrameConstructor needs to know if the child
// list of the element that we're iterating matches its .childNodes.
//
// This is lazily computed when asked for it.
Maybe<bool> mXBLInvolved;
}; };
/** /**