зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1445392: Make HTMLSlotElement slot change event stuff not linear. r=smaug
Also fix refcount churn in nsDOMMutationObserver and such. MozReview-Commit-ID: GwEB0LZY7Ss
This commit is contained in:
Родитель
21cb54ff16
Коммит
bc958c264f
|
@ -159,13 +159,10 @@ DocGroup::GetValidAccessPtr()
|
|||
}
|
||||
|
||||
void
|
||||
DocGroup::SignalSlotChange(const HTMLSlotElement* aSlot)
|
||||
DocGroup::SignalSlotChange(HTMLSlotElement& aSlot)
|
||||
{
|
||||
if (mSignalSlotList.Contains(aSlot)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSignalSlotList.AppendElement(const_cast<HTMLSlotElement*>(aSlot));
|
||||
MOZ_ASSERT(!mSignalSlotList.Contains(&aSlot));
|
||||
mSignalSlotList.AppendElement(&aSlot);
|
||||
|
||||
if (!sPendingDocGroups) {
|
||||
// Queue a mutation observer compound microtask.
|
||||
|
@ -176,5 +173,16 @@ DocGroup::SignalSlotChange(const HTMLSlotElement* aSlot)
|
|||
sPendingDocGroups->AppendElement(this);
|
||||
}
|
||||
|
||||
void
|
||||
DocGroup::MoveSignalSlotListTo(nsTArray<RefPtr<HTMLSlotElement>>& aDest)
|
||||
{
|
||||
aDest.SetCapacity(aDest.Length() + mSignalSlotList.Length());
|
||||
for (RefPtr<HTMLSlotElement>& slot : mSignalSlotList) {
|
||||
slot->RemovedFromSignalSlotList();
|
||||
aDest.AppendElement(Move(slot));
|
||||
}
|
||||
mSignalSlotList.Clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,19 +113,11 @@ public:
|
|||
// DocGroup.
|
||||
bool* GetValidAccessPtr();
|
||||
|
||||
// Append aSlot to the list of signal slot list, if it's not in it already
|
||||
// list, and queue a mutation observer microtask.
|
||||
void SignalSlotChange(const mozilla::dom::HTMLSlotElement* aSlot);
|
||||
// Append aSlot to the list of signal slot list, and queue a mutation observer
|
||||
// microtask.
|
||||
void SignalSlotChange(HTMLSlotElement& aSlot);
|
||||
|
||||
const nsTArray<RefPtr<HTMLSlotElement>>& SignalSlotList() const
|
||||
{
|
||||
return mSignalSlotList;
|
||||
}
|
||||
|
||||
void ClearSignalSlotList()
|
||||
{
|
||||
mSignalSlotList.Clear();
|
||||
}
|
||||
void MoveSignalSlotListTo(nsTArray<RefPtr<HTMLSlotElement>>& aDest);
|
||||
|
||||
// List of DocGroups that has non-empty signal slot list.
|
||||
static AutoTArray<RefPtr<DocGroup>, 2>* sPendingDocGroups;
|
||||
|
|
|
@ -900,17 +900,15 @@ nsDOMMutationObserver::HandleMutationsInternal(AutoSlowOperation& aAso)
|
|||
{
|
||||
nsTArray<RefPtr<nsDOMMutationObserver> >* suppressedObservers = nullptr;
|
||||
|
||||
// Let signalList be a copy of unit of related similar-origin browsing
|
||||
// contexts' signal slot list.
|
||||
// This loop implements:
|
||||
// * Let signalList be a copy of unit of related similar-origin browsing
|
||||
// contexts' signal slot list.
|
||||
// * Empty unit of related similar-origin browsing contexts' signal slot
|
||||
// list.
|
||||
nsTArray<RefPtr<HTMLSlotElement>> signalList;
|
||||
if (DocGroup::sPendingDocGroups) {
|
||||
for (uint32_t i = 0; i < DocGroup::sPendingDocGroups->Length(); ++i) {
|
||||
DocGroup* docGroup = DocGroup::sPendingDocGroups->ElementAt(i);
|
||||
signalList.AppendElements(docGroup->SignalSlotList());
|
||||
|
||||
// Empty unit of related similar-origin browsing contexts' signal slot
|
||||
// list.
|
||||
docGroup->ClearSignalSlotList();
|
||||
for (DocGroup* docGroup : *DocGroup::sPendingDocGroups) {
|
||||
docGroup->MoveSignalSlotListTo(signalList);
|
||||
}
|
||||
delete DocGroup::sPendingDocGroups;
|
||||
DocGroup::sPendingDocGroups = nullptr;
|
||||
|
|
|
@ -34,9 +34,7 @@ HTMLSlotElement::HTMLSlotElement(already_AddRefed<mozilla::dom::NodeInfo>& aNode
|
|||
{
|
||||
}
|
||||
|
||||
HTMLSlotElement::~HTMLSlotElement()
|
||||
{
|
||||
}
|
||||
HTMLSlotElement::~HTMLSlotElement() = default;
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(HTMLSlotElement, nsGenericHTMLElement)
|
||||
NS_IMPL_RELEASE_INHERITED(HTMLSlotElement, nsGenericHTMLElement)
|
||||
|
@ -216,14 +214,19 @@ HTMLSlotElement::ClearAssignedNodes()
|
|||
}
|
||||
|
||||
void
|
||||
HTMLSlotElement::EnqueueSlotChangeEvent() const
|
||||
HTMLSlotElement::EnqueueSlotChangeEvent()
|
||||
{
|
||||
if (mInSignalSlotList) {
|
||||
return;
|
||||
}
|
||||
|
||||
DocGroup* docGroup = OwnerDoc()->GetDocGroup();
|
||||
if (!docGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
docGroup->SignalSlotChange(this);
|
||||
mInSignalSlotList = true;
|
||||
docGroup->SignalSlotChange(*this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -63,15 +63,26 @@ public:
|
|||
void RemoveAssignedNode(nsINode* aNode);
|
||||
void ClearAssignedNodes();
|
||||
|
||||
void EnqueueSlotChangeEvent() const;
|
||||
void EnqueueSlotChangeEvent();
|
||||
void RemovedFromSignalSlotList()
|
||||
{
|
||||
MOZ_ASSERT(mInSignalSlotList);
|
||||
mInSignalSlotList = false;
|
||||
}
|
||||
|
||||
void FireSlotChangeEvent();
|
||||
|
||||
protected:
|
||||
virtual ~HTMLSlotElement();
|
||||
virtual JSObject*
|
||||
WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
|
||||
|
||||
nsTArray<RefPtr<nsINode>> mAssignedNodes;
|
||||
|
||||
// Whether we're in the signal slot list of our unit of related similar-origin
|
||||
// browsing contexts.
|
||||
//
|
||||
// https://dom.spec.whatwg.org/#signal-slot-list
|
||||
bool mInSignalSlotList = false;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
Загрузка…
Ссылка в новой задаче