Bug 1272409 part 4: Integrate ResizeObserver with Document and reflow. r?dholbert
MozReview-Commit-ID: F7KDJZxGnFO
--- a/dom/base/ResizeObserver.cpp
+++ b/dom/base/ResizeObserver.cpp
@@ -53,17 +53,17 @@ ResizeObserver::Constructor(const Global
nsCOMPtr<nsIDocument> document = window->GetExtantDoc();
if (!document) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<ResizeObserver> observer = new ResizeObserver(window.forget(), aCb);
- // TODO: Add the new ResizeObserver to document here in the later patch.
+ document->AddResizeObserver(observer);
return observer.forget();
}
void
ResizeObserver::Observe(Element* aTarget,
ErrorResult& aRv)
{
@@ -78,17 +78,17 @@ ResizeObserver::Observe(Element* aTarget
observation = new ResizeObservation(this, aTarget);
mObservationMap.Put(aTarget, observation);
mObservationList.insertBack(observation);
// Per the spec, we need to trigger notification in event loop that
// contains ResizeObserver observe call even when resize/reflow does
// not happen.
- // TODO: Implement the notification scheduling in the later patch.
+ aTarget->OwnerDoc()->ScheduleResizeObserversNotification();
}
}
void
ResizeObserver::Unobserve(Element* aTarget,
ErrorResult& aRv)
{
if (!aTarget) {
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1774,16 +1774,20 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
MediaQueryList *mql = static_cast<MediaQueryList*>(l);
if (mql->HasListeners()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
cb.NoteXPCOMChild(mql);
}
}
+
+ if (tmp->mResizeObserverController) {
+ tmp->mResizeObserverController->Traverse(cb);
+ }
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mInUnlinkOrDeletion = true;
@@ -1875,16 +1879,20 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
l != &tmp->mDOMMediaQueryLists; ) {
PRCList *next = PR_NEXT_LINK(l);
MediaQueryList *mql = static_cast<MediaQueryList*>(l);
mql->RemoveAllListeners();
l = next;
}
tmp->mInUnlinkOrDeletion = false;
+
+ if (tmp->mResizeObserverController) {
+ tmp->mResizeObserverController->Unlink();
+ }
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
nsresult
nsDocument::Init()
{
if (mCSSLoader || mStyleImageLoader || mNodeInfoManager || mScriptLoader) {
return NS_ERROR_ALREADY_INITIALIZED;
}
@@ -12275,16 +12283,34 @@ nsDocument::QuerySelector(const nsAStrin
}
NS_IMETHODIMP
nsDocument::QuerySelectorAll(const nsAString& aSelector, nsIDOMNodeList **aReturn)
{
return nsINode::QuerySelectorAll(aSelector, aReturn);
}
+void
+nsDocument::AddResizeObserver(ResizeObserver* aResizeObserver)
+{
+ if (!mResizeObserverController) {
+ mResizeObserverController = MakeUnique<ResizeObserverController>(this);
+ }
+
+ mResizeObserverController->AddResizeObserver(aResizeObserver);
+}
+
+void
+nsDocument::ScheduleResizeObserversNotification() const
+{
+ if (mResizeObserverController) {
+ mResizeObserverController->ScheduleNotification();
+ }
+}
+
already_AddRefed<nsIDocument>
nsIDocument::Constructor(const GlobalObject& aGlobal,
ErrorResult& rv)
{
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
if (!global) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -55,16 +55,17 @@
#include "nsISecurityEventSink.h"
#include "nsIChannelEventSink.h"
#include "imgIRequest.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStates.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/PendingAnimationTracker.h"
#include "mozilla/dom/DOMImplementation.h"
+#include "mozilla/dom/ResizeObserverController.h"
#include "mozilla/dom/StyleSheetList.h"
#include "nsDataHashtable.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Attributes.h"
#include "nsIDOMXPathEvaluator.h"
#include "jsfriendapi.h"
#include "ImportManager.h"
#include "mozilla/LinkedList.h"
@@ -1192,16 +1193,20 @@ public:
virtual nsINode* GetSubImportLink(uint32_t aIdx) override
{
return aIdx < mSubImportLinks.Length() ? mSubImportLinks[aIdx].get()
: nullptr;
}
virtual void UnblockDOMContentLoaded() override;
+ void AddResizeObserver(mozilla::dom::ResizeObserver* aResizeObserver) override;
+
+ void ScheduleResizeObserversNotification() const override;
+
protected:
friend class nsNodeUtils;
friend class nsDocumentOnStack;
void IncreaseStackRefCnt()
{
++mStackRefCnt;
}
@@ -1323,16 +1328,19 @@ protected:
// Apply the fullscreen state to the document, and trigger related
// events. It returns false if the fullscreen element ready check
// fails and nothing gets changed.
bool ApplyFullscreen(const FullscreenRequest& aRequest);
nsTArray<nsIObserver*> mCharSetObservers;
+ mozilla::UniquePtr<mozilla::dom::ResizeObserverController>
+ mResizeObserverController;
+
PLDHashTable *mSubDocuments;
// Array of owning references to all children
nsAttrAndChildArray mChildren;
// Pointer to our parser if we're currently in the process of being
// parsed into.
nsCOMPtr<nsIParser> mParser;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -131,16 +131,17 @@ struct LifecycleCallbackArgs;
class Link;
class MediaQueryList;
class GlobalObject;
class NodeFilter;
class NodeIterator;
enum class OrientationType : uint32_t;
class ProcessingInstruction;
class Promise;
+class ResizeObserver;
class StyleSheetList;
class SVGDocument;
class Touch;
class TouchList;
class TreeWalker;
class UndoManager;
class XPathEvaluator;
class XPathExpression;
@@ -2758,16 +2759,20 @@ public:
bool HasScriptsBlockedBySandbox();
void ReportHasScrollLinkedEffect();
bool HasScrollLinkedEffect() const
{
return mHasScrollLinkedEffect;
}
+ virtual void AddResizeObserver(mozilla::dom::ResizeObserver* aResizeObserver) = 0;
+
+ virtual void ScheduleResizeObserversNotification() const = 0;
+
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)
{
return mUseCounters[aUseCounter];
}
void SetChildDocumentUseCounter(mozilla::UseCounter aUseCounter)
{
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -9400,16 +9400,20 @@ PresShell::DidDoReflow(bool aInterruptib
HandlePostedReflowCallbacks(aInterruptible);
nsCOMPtr<nsIDocShell> docShell = mPresContext->GetDocShell();
if (docShell) {
DOMHighResTimeStamp now = GetPerformanceNow();
docShell->NotifyReflowObservers(aInterruptible, mLastReflowStart, now);
}
+ if (!mPresContext->HasPendingInterrupt()) {
+ mDocument->ScheduleResizeObserversNotification();
+ }
+
if (sSynthMouseMove) {
SynthesizeMouseMove(false);
}
mPresContext->NotifyMissingFonts();
}
DOMHighResTimeStamp