Bug 1316277 - Move intersection observer list from DOMSlots to a property. r=mrbkap

--HG--
extra : rebase_source : fcaa7d31e0a99ad666e0091c56cd9858e3afcc4b
This commit is contained in:
Tobias Schneider 2017-10-05 20:42:55 -07:00
parent 4e3feba463
commit 7c9837e0e8
6 changed files with 74 additions and 50 deletions

View File

@ -4194,13 +4194,6 @@ Element::ClearDataset()
slots->mDataset = nullptr;
}
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
Element::RegisteredIntersectionObservers()
{
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
return &slots->mRegisteredIntersectionObservers;
}
enum nsPreviousIntersectionThreshold {
eUninitialized = -2,
eNonIntersecting = -1
@ -4209,7 +4202,20 @@ enum nsPreviousIntersectionThreshold {
void
Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
RegisteredIntersectionObservers()->LookupForAdd(aObserver).OrInsert([]() {
IntersectionObserverList* observers =
static_cast<IntersectionObserverList*>(
GetProperty(nsGkAtoms::intersectionobserverlist)
);
if (!observers) {
observers = new IntersectionObserverList();
observers->Put(aObserver, eUninitialized);
SetProperty(nsGkAtoms::intersectionobserverlist, observers,
nsINode::DeleteProperty<IntersectionObserverList>);
return;
}
observers->LookupForAdd(aObserver).OrInsert([]() {
// Value can be:
// -2: Makes sure next calculated threshold always differs, leading to a
// notification task being scheduled.
@ -4222,14 +4228,44 @@ Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
void
Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
RegisteredIntersectionObservers()->Remove(aObserver);
IntersectionObserverList* observers =
static_cast<IntersectionObserverList*>(
GetProperty(nsGkAtoms::intersectionobserverlist)
);
if (observers) {
observers->Remove(aObserver);
}
}
void
Element::UnlinkIntersectionObservers()
{
IntersectionObserverList* observers =
static_cast<IntersectionObserverList*>(
GetProperty(nsGkAtoms::intersectionobserverlist)
);
if (!observers) {
return;
}
for (auto iter = observers->Iter(); !iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
observer->UnlinkTarget(*this);
}
observers->Clear();
}
bool
Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
{
IntersectionObserverList* observers =
static_cast<IntersectionObserverList*>(
GetProperty(nsGkAtoms::intersectionobserverlist)
);
if (!observers) {
return false;
}
bool updated = false;
if (auto entry = RegisteredIntersectionObservers()->Lookup(aObserver)) {
if (auto entry = observers->Lookup(aObserver)) {
updated = entry.Data() != aThreshold;
entry.Data() = aThreshold;
}

View File

@ -73,6 +73,8 @@ namespace dom {
class ElementOrCSSPseudoElement;
class UnrestrictedDoubleOrKeyframeAnimationOptions;
enum class CallerType : uint32_t;
typedef nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
IntersectionObserverList;
} // namespace dom
} // namespace mozilla
@ -1436,6 +1438,7 @@ public:
void RegisterIntersectionObserver(DOMIntersectionObserver* aObserver);
void UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver);
void UnlinkIntersectionObservers();
bool UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t threshold);
protected:
@ -1721,9 +1724,6 @@ protected:
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
RegisteredIntersectionObservers();
private:
/**
* Hook for implementing GetClasses. This is guaranteed to only be

View File

@ -816,14 +816,6 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
}
}
for (auto iter = mExtendedSlots->mRegisteredIntersectionObservers.Iter();
!iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mExtendedSlots->mRegisteredIntersectionObservers[i]");
cb.NoteXPCOMChild(observer);
}
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mFrameLoaderOrOpener");
cb.NoteXPCOMChild(mExtendedSlots->mFrameLoaderOrOpener);
}
@ -856,7 +848,6 @@ FragmentOrElement::nsDOMSlots::Unlink()
}
mExtendedSlots->mCustomElementData = nullptr;
}
mExtendedSlots->mRegisteredIntersectionObservers.Clear();
nsCOMPtr<nsIFrameLoader> frameLoader =
do_QueryInterface(mExtendedSlots->mFrameLoaderOrOpener);
if (frameLoader) {
@ -1563,6 +1554,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
// which is dispatched in UnbindFromTree.
if (tmp->HasProperties()) {
if (tmp->IsElement()) {
Element* elem = tmp->AsElement();
elem->UnlinkIntersectionObservers();
}
if (tmp->IsHTMLElement() || tmp->IsSVGElement()) {
nsIAtom*** props = Element::HTMLSVGPropertiesToTraverseAndUnlink();
for (uint32_t i = 0; props[i]; ++i) {
@ -1617,14 +1613,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) {
if (slots->mExtendedSlots && tmp->IsElement()) {
Element* elem = tmp->AsElement();
for (auto iter = slots->mExtendedSlots->mRegisteredIntersectionObservers.Iter();
!iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
observer->UnlinkTarget(*elem);
}
}
slots->Unlink();
}
}
@ -2145,6 +2133,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
#endif
if (tmp->HasProperties()) {
if (tmp->IsElement()) {
Element* elem = tmp->AsElement();
IntersectionObserverList* observers =
static_cast<IntersectionObserverList*>(
elem->GetProperty(nsGkAtoms::intersectionobserverlist)
);
if (observers) {
for (auto iter = observers->Iter(); !iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
cb.NoteXPCOMChild(observer);
}
}
}
if (tmp->IsHTMLElement() || tmp->IsSVGElement()) {
nsIAtom*** props = Element::HTMLSVGPropertiesToTraverseAndUnlink();
for (uint32_t i = 0; props[i]; ++i) {

View File

@ -40,7 +40,6 @@ namespace mozilla {
class DeclarationBlock;
namespace dom {
struct CustomElementData;
class DOMIntersectionObserver;
class Element;
} // namespace dom
} // namespace mozilla
@ -313,12 +312,6 @@ public:
*/
RefPtr<CustomElementData> mCustomElementData;
/**
* Registered Intersection Observers on the element.
*/
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
mRegisteredIntersectionObservers;
/**
* For XUL to hold either frameloader or opener.
*/

View File

@ -582,6 +582,7 @@ GK_ATOM(int64, "int64")
GK_ATOM(integer, "integer")
GK_ATOM(integrity, "integrity")
GK_ATOM(intersection, "intersection")
GK_ATOM(intersectionobserverlist, "intersectionobserverlist")
GK_ATOM(is, "is")
GK_ATOM(iscontainer, "iscontainer")
GK_ATOM(isempty, "isempty")

View File

@ -293,19 +293,6 @@ nsNodeUtils::LastRelease(nsINode* aNode)
NodeWillBeDestroyed, (aNode));
}
if (aNode->IsElement()) {
Element* elem = aNode->AsElement();
FragmentOrElement::nsDOMSlots* domSlots =
static_cast<FragmentOrElement::nsDOMSlots*>(slots);
if (domSlots->mExtendedSlots) {
for (auto iter = domSlots->mExtendedSlots->mRegisteredIntersectionObservers.Iter();
!iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
observer->UnlinkTarget(*elem);
}
}
}
delete slots;
aNode->mSlots = nullptr;
}
@ -320,6 +307,12 @@ nsNodeUtils::LastRelease(nsINode* aNode)
}
else {
if (aNode->HasProperties()) {
if (aNode->IsElement()) {
Element* elem = aNode->AsElement();
elem->UnlinkIntersectionObservers();
elem->DeleteProperty(nsGkAtoms::intersectionobserverlist);
}
// Strong reference to the document so that deleting properties can't
// delete the document.
nsCOMPtr<nsIDocument> document = aNode->OwnerDoc();