summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dom/base/ResizeObserver.cpp752
-rw-r--r--dom/base/ResizeObserver.h624
-rw-r--r--dom/base/ResizeObserverController.h6
3 files changed, 691 insertions, 691 deletions
diff --git a/dom/base/ResizeObserver.cpp b/dom/base/ResizeObserver.cpp
index f168b87c55..51fd603217 100644
--- a/dom/base/ResizeObserver.cpp
+++ b/dom/base/ResizeObserver.cpp
@@ -1,376 +1,376 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/ResizeObserver.h"
-
-#include "mozilla/dom/DOMRect.h"
-#include "nsIContentInlines.h"
-#include "nsIFrame.h"
-#include "nsSVGUtils.h"
-
-namespace mozilla {
-namespace dom {
-
-/**
- * Returns the length of the parent-traversal path (in terms of the number of
- * nodes) to an unparented/root node from aNode. An unparented/root node is
- * considered to have a depth of 1, its children have a depth of 2, etc.
- * aNode is expected to be non-null.
- * Note: The shadow root is not part of the calculation because the caller,
- * ResizeObserver, doesn't observe the shadow root, and only needs relative
- * depths among all the observed targets. In other words, we calculate the
- * depth of the flattened tree.
- *
- * Note: these is a spec issue about how to handle shadow DOM case. We
- * may need to update this function later.
- *
- *
- * https://drafts.csswg.org/resize-observer/#calculate-depth-for-node-h
- */
-static uint32_t
-GetNodeDepth(nsINode* aNode) {
- uint32_t depth = 1;
-
- MOZ_ASSERT(aNode, "Node shouldn't be null");
-
- // Use GetFlattenedTreeParentNode to bypass the shadow root and cross the
- // shadow boundary to calculate the node depth without the shadow root.
- while ((aNode = aNode->GetFlattenedTreeParentNode())) {
- ++depth;
- }
-
- return depth;
-}
-
-/**
- * Returns |aTarget|'s size in the form of an nsSize.
- * If the target is an SVG, width and height are determined from the bounding box.
- */
-static nsSize
-GetTargetSize(Element* aTarget, ResizeObserverBoxOptions aBox) {
- nsSize size;
- nsIFrame* frame = aTarget->GetPrimaryFrame();
-
- if (!frame) {
- return size;
- }
-
- if (aTarget->IsSVGElement()) {
- // Per the spec, an SVG size is always its bounding box size, no matter what
- // box option you choose, because SVG elements do not use the standard CSS box
- // model.
- gfxRect bbox = nsSVGUtils::GetBBox(frame);
- size.width = NSFloatPixelsToAppUnits(bbox.width, AppUnitsPerCSSPixel());
- size.height = NSFloatPixelsToAppUnits(bbox.height, AppUnitsPerCSSPixel());
- } else {
- // Per the spec, non-replaced inline Elements will always have an empty
- // content rect. We therefore always use the same empty size for
- // non-replaced inline elements here, and their IsActive() will
- // always return false. (So its observation won't be fired.)
- if (!frame->IsFrameOfType(nsIFrame::eReplaced) &&
- frame->IsFrameOfType(nsIFrame::eLineParticipant)) {
- return size;
- }
-
- switch (aBox) {
- case ResizeObserverBoxOptions::Border_box:
- // GetSize() includes the content area, borders, and padding.
- size = frame->GetSize();
- break;
- case ResizeObserverBoxOptions::Content_box:
- default:
- size = frame->GetContentRectRelativeToSelf().Size();
- }
- }
-
- return size;
-}
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserver)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserver)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserver)
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(ResizeObserver)
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResizeObserver)
- NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ResizeObserver)
- NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservationMap)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ResizeObserver)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservationMap)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-already_AddRefed<ResizeObserver>
-ResizeObserver::Constructor(const GlobalObject& aGlobal,
- ResizeObserverCallback& aCb,
- ErrorResult& aRv)
-{
- nsCOMPtr<nsPIDOMWindowInner> window =
- do_QueryInterface(aGlobal.GetAsSupports());
-
- if (!window) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- nsCOMPtr<nsIDocument> document = window->GetExtantDoc();
-
- if (!document) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- RefPtr<ResizeObserver> observer = new ResizeObserver(window.forget(), aCb);
- document->AddResizeObserver(observer);
-
- return observer.forget();
-}
-
-void
-ResizeObserver::Observe(Element* aTarget,
- const ResizeObserverOptions& aOptions,
- ErrorResult& aRv)
-{
- if (!aTarget) {
- aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
- return;
- }
-
- RefPtr<ResizeObservation> observation;
-
- if (!mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
- nsIFrame* frame = aTarget->GetPrimaryFrame();
- WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
- observation = new ResizeObservation(aTarget->OwnerDoc(), aTarget, aOptions.mBox, wm);
-
- 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.
- aTarget->OwnerDoc()->ScheduleResizeObserversNotification();
- }
-}
-
-void
-ResizeObserver::Unobserve(Element* aTarget,
- ErrorResult& aRv)
-{
- if (!aTarget) {
- aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
- return;
- }
-
- RefPtr<ResizeObservation> observation;
-
- if (mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
- mObservationMap.Remove(aTarget);
-
- MOZ_ASSERT(!mObservationList.isEmpty(),
- "If ResizeObservation found for an element, observation list "
- "must be not empty.");
-
- observation->remove();
- }
-}
-
-void
-ResizeObserver::Disconnect()
-{
- mObservationMap.Clear();
- mObservationList.clear();
- mActiveTargets.Clear();
-}
-
-void
-ResizeObserver::GatherActiveObservations(uint32_t aDepth)
-{
- mActiveTargets.Clear();
- mHasSkippedTargets = false;
-
- for (auto observation : mObservationList) {
- if (observation->IsActive()) {
- uint32_t targetDepth = GetNodeDepth(observation->Target());
-
- if (targetDepth > aDepth) {
- mActiveTargets.AppendElement(observation);
- } else {
- mHasSkippedTargets = true;
- }
- }
- }
-}
-
-bool
-ResizeObserver::HasActiveObservations() const
-{
- return !mActiveTargets.IsEmpty();
-}
-
-bool
-ResizeObserver::HasSkippedObservations() const
-{
- return mHasSkippedTargets;
-}
-
-uint32_t
-ResizeObserver::BroadcastActiveObservations()
-{
- uint32_t shallowestTargetDepth = UINT32_MAX;
-
- if (HasActiveObservations()) {
- Sequence<OwningNonNull<ResizeObserverEntry>> entries;
-
- for (auto observation : mActiveTargets) {
- Element* target = observation->Target();
- RefPtr<ResizeObserverEntry> entry = new ResizeObserverEntry(this, target);
-
- nsSize borderBoxSize = GetTargetSize(target, ResizeObserverBoxOptions::Border_box);
- entry->SetBorderBoxSize(borderBoxSize);
-
- nsSize contentBoxSize = GetTargetSize(target, ResizeObserverBoxOptions::Content_box);
- entry->SetContentRectAndSize(contentBoxSize);
-
- if (!entries.AppendElement(entry.forget(), fallible)) {
- // Out of memory.
- break;
- }
-
- // Sync the broadcast size of observation so the next size inspection
- // will be based on the updated size from last delivered observations.
- switch (observation->BoxOptions()) {
- case ResizeObserverBoxOptions::Border_box:
- observation->UpdateLastReportedSize(borderBoxSize);
- break;
- case ResizeObserverBoxOptions::Content_box:
- default:
- observation->UpdateLastReportedSize(contentBoxSize);
- }
-
- uint32_t targetDepth = GetNodeDepth(observation->Target());
-
- if (targetDepth < shallowestTargetDepth) {
- shallowestTargetDepth = targetDepth;
- }
- }
-
- mCallback->Call(this, entries, *this);
- mActiveTargets.Clear();
- mHasSkippedTargets = false;
- }
-
- return shallowestTargetDepth;
-}
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserverEntry)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserverEntry)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserverEntry)
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObserverEntry,
- mOwner,
- mTarget,
- mContentRect,
- mBorderBoxSize,
- mContentBoxSize)
-
-already_AddRefed<ResizeObserverEntry>
-ResizeObserverEntry::Constructor(const GlobalObject& aGlobal,
- Element* aTarget,
- ErrorResult& aRv)
-{
- RefPtr<ResizeObserverEntry> observerEntry =
- new ResizeObserverEntry(aGlobal.GetAsSupports(), aTarget);
- return observerEntry.forget();
-}
-
-void
-ResizeObserverEntry::SetBorderBoxSize(const nsSize& aSize) {
- nsIFrame* frame = mTarget->GetPrimaryFrame();
- WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
- mBorderBoxSize = new ResizeObserverSize(this, aSize, wm);
-}
-
-void
-ResizeObserverEntry::SetContentRectAndSize(const nsSize& aSize) {
- nsIFrame* frame = mTarget->GetPrimaryFrame();
-
- // Update mContentRect.
- nsMargin padding = frame ? frame->GetUsedPadding(): nsMargin();
- // Per the spec, we need to use the top-left padding offset as the origin of
- // our contentRect.
- nsRect rect(nsPoint(padding.left, padding.top), aSize);
- RefPtr<DOMRect> contentRect = new DOMRect(mTarget);
- contentRect->SetLayoutRect(rect);
- mContentRect = contentRect.forget();
-
- // Update mContentBoxSize.
- WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
- mContentBoxSize = new ResizeObserverSize(this, aSize, wm);
-}
-
-ResizeObserverEntry::~ResizeObserverEntry()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObserverSize, mOwner)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserverSize)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserverSize)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserverSize)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObservation)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObservation)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObservation)
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObservation,
- mTarget, mOwner)
-
-bool
-ResizeObservation::IsActive() const
-{
- nsIFrame* frame = mTarget->GetPrimaryFrame();
- WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
- LogicalSize size(wm, GetTargetSize(mTarget, mObservedBox));
- return mLastReportedSize.ISize(mLastReportedWM) != size.ISize(wm) ||
- mLastReportedSize.BSize(mLastReportedWM) != size.BSize(wm);
-}
-
-void
-ResizeObservation::UpdateLastReportedSize(const nsSize& aSize) {
- nsIFrame* frame = mTarget->GetPrimaryFrame();
- mLastReportedWM = frame ? frame->GetWritingMode() : WritingMode();
- mLastReportedSize = LogicalSize(mLastReportedWM, aSize);
-}
-
-ResizeObservation::~ResizeObservation()
-{
-}
-
-} // namespace dom
-} // namespace mozilla
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ResizeObserver.h"
+
+#include "mozilla/dom/DOMRect.h"
+#include "nsIContentInlines.h"
+#include "nsIFrame.h"
+#include "nsSVGUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+/**
+ * Returns the length of the parent-traversal path (in terms of the number of
+ * nodes) to an unparented/root node from aNode. An unparented/root node is
+ * considered to have a depth of 1, its children have a depth of 2, etc.
+ * aNode is expected to be non-null.
+ * Note: The shadow root is not part of the calculation because the caller,
+ * ResizeObserver, doesn't observe the shadow root, and only needs relative
+ * depths among all the observed targets. In other words, we calculate the
+ * depth of the flattened tree.
+ *
+ * Note: these is a spec issue about how to handle shadow DOM case. We
+ * may need to update this function later.
+ *
+ *
+ * https://drafts.csswg.org/resize-observer/#calculate-depth-for-node-h
+ */
+static uint32_t
+GetNodeDepth(nsINode* aNode) {
+ uint32_t depth = 1;
+
+ MOZ_ASSERT(aNode, "Node shouldn't be null");
+
+ // Use GetFlattenedTreeParentNode to bypass the shadow root and cross the
+ // shadow boundary to calculate the node depth without the shadow root.
+ while ((aNode = aNode->GetFlattenedTreeParentNode())) {
+ ++depth;
+ }
+
+ return depth;
+}
+
+/**
+ * Returns |aTarget|'s size in the form of an nsSize.
+ * If the target is an SVG, width and height are determined from the bounding box.
+ */
+static nsSize
+GetTargetSize(Element* aTarget, ResizeObserverBoxOptions aBox) {
+ nsSize size;
+ nsIFrame* frame = aTarget->GetPrimaryFrame();
+
+ if (!frame) {
+ return size;
+ }
+
+ if (aTarget->IsSVGElement()) {
+ // Per the spec, an SVG size is always its bounding box size, no matter what
+ // box option you choose, because SVG elements do not use the standard CSS box
+ // model.
+ gfxRect bbox = nsSVGUtils::GetBBox(frame);
+ size.width = NSFloatPixelsToAppUnits(bbox.width, AppUnitsPerCSSPixel());
+ size.height = NSFloatPixelsToAppUnits(bbox.height, AppUnitsPerCSSPixel());
+ } else {
+ // Per the spec, non-replaced inline Elements will always have an empty
+ // content rect. We therefore always use the same empty size for
+ // non-replaced inline elements here, and their IsActive() will
+ // always return false. (So its observation won't be fired.)
+ if (!frame->IsFrameOfType(nsIFrame::eReplaced) &&
+ frame->IsFrameOfType(nsIFrame::eLineParticipant)) {
+ return size;
+ }
+
+ switch (aBox) {
+ case ResizeObserverBoxOptions::Border_box:
+ // GetSize() includes the content area, borders, and padding.
+ size = frame->GetSize();
+ break;
+ case ResizeObserverBoxOptions::Content_box:
+ default:
+ size = frame->GetContentRectRelativeToSelf().Size();
+ }
+ }
+
+ return size;
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserver)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserver)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserver)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ResizeObserver)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResizeObserver)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ResizeObserver)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservationMap)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ResizeObserver)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservationMap)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+already_AddRefed<ResizeObserver>
+ResizeObserver::Constructor(const GlobalObject& aGlobal,
+ ResizeObserverCallback& aCb,
+ ErrorResult& aRv)
+{
+ nsCOMPtr<nsPIDOMWindowInner> window =
+ do_QueryInterface(aGlobal.GetAsSupports());
+
+ if (!window) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ nsCOMPtr<nsIDocument> document = window->GetExtantDoc();
+
+ if (!document) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ RefPtr<ResizeObserver> observer = new ResizeObserver(window.forget(), aCb);
+ document->AddResizeObserver(observer);
+
+ return observer.forget();
+}
+
+void
+ResizeObserver::Observe(Element* aTarget,
+ const ResizeObserverOptions& aOptions,
+ ErrorResult& aRv)
+{
+ if (!aTarget) {
+ aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
+ return;
+ }
+
+ RefPtr<ResizeObservation> observation;
+
+ if (!mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
+ nsIFrame* frame = aTarget->GetPrimaryFrame();
+ WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
+ observation = new ResizeObservation(aTarget->OwnerDoc(), aTarget, aOptions.mBox, wm);
+
+ 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.
+ aTarget->OwnerDoc()->ScheduleResizeObserversNotification();
+ }
+}
+
+void
+ResizeObserver::Unobserve(Element* aTarget,
+ ErrorResult& aRv)
+{
+ if (!aTarget) {
+ aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
+ return;
+ }
+
+ RefPtr<ResizeObservation> observation;
+
+ if (mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
+ mObservationMap.Remove(aTarget);
+
+ MOZ_ASSERT(!mObservationList.isEmpty(),
+ "If ResizeObservation found for an element, observation list "
+ "must be not empty.");
+
+ observation->remove();
+ }
+}
+
+void
+ResizeObserver::Disconnect()
+{
+ mObservationMap.Clear();
+ mObservationList.clear();
+ mActiveTargets.Clear();
+}
+
+void
+ResizeObserver::GatherActiveObservations(uint32_t aDepth)
+{
+ mActiveTargets.Clear();
+ mHasSkippedTargets = false;
+
+ for (auto observation : mObservationList) {
+ if (observation->IsActive()) {
+ uint32_t targetDepth = GetNodeDepth(observation->Target());
+
+ if (targetDepth > aDepth) {
+ mActiveTargets.AppendElement(observation);
+ } else {
+ mHasSkippedTargets = true;
+ }
+ }
+ }
+}
+
+bool
+ResizeObserver::HasActiveObservations() const
+{
+ return !mActiveTargets.IsEmpty();
+}
+
+bool
+ResizeObserver::HasSkippedObservations() const
+{
+ return mHasSkippedTargets;
+}
+
+uint32_t
+ResizeObserver::BroadcastActiveObservations()
+{
+ uint32_t shallowestTargetDepth = UINT32_MAX;
+
+ if (HasActiveObservations()) {
+ Sequence<OwningNonNull<ResizeObserverEntry>> entries;
+
+ for (auto observation : mActiveTargets) {
+ Element* target = observation->Target();
+ RefPtr<ResizeObserverEntry> entry = new ResizeObserverEntry(this, target);
+
+ nsSize borderBoxSize = GetTargetSize(target, ResizeObserverBoxOptions::Border_box);
+ entry->SetBorderBoxSize(borderBoxSize);
+
+ nsSize contentBoxSize = GetTargetSize(target, ResizeObserverBoxOptions::Content_box);
+ entry->SetContentRectAndSize(contentBoxSize);
+
+ if (!entries.AppendElement(entry.forget(), fallible)) {
+ // Out of memory.
+ break;
+ }
+
+ // Sync the broadcast size of observation so the next size inspection
+ // will be based on the updated size from last delivered observations.
+ switch (observation->BoxOptions()) {
+ case ResizeObserverBoxOptions::Border_box:
+ observation->UpdateLastReportedSize(borderBoxSize);
+ break;
+ case ResizeObserverBoxOptions::Content_box:
+ default:
+ observation->UpdateLastReportedSize(contentBoxSize);
+ }
+
+ uint32_t targetDepth = GetNodeDepth(observation->Target());
+
+ if (targetDepth < shallowestTargetDepth) {
+ shallowestTargetDepth = targetDepth;
+ }
+ }
+
+ mCallback->Call(this, entries, *this);
+ mActiveTargets.Clear();
+ mHasSkippedTargets = false;
+ }
+
+ return shallowestTargetDepth;
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserverEntry)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserverEntry)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserverEntry)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObserverEntry,
+ mOwner,
+ mTarget,
+ mContentRect,
+ mBorderBoxSize,
+ mContentBoxSize)
+
+already_AddRefed<ResizeObserverEntry>
+ResizeObserverEntry::Constructor(const GlobalObject& aGlobal,
+ Element* aTarget,
+ ErrorResult& aRv)
+{
+ RefPtr<ResizeObserverEntry> observerEntry =
+ new ResizeObserverEntry(aGlobal.GetAsSupports(), aTarget);
+ return observerEntry.forget();
+}
+
+void
+ResizeObserverEntry::SetBorderBoxSize(const nsSize& aSize) {
+ nsIFrame* frame = mTarget->GetPrimaryFrame();
+ WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
+ mBorderBoxSize = new ResizeObserverSize(this, aSize, wm);
+}
+
+void
+ResizeObserverEntry::SetContentRectAndSize(const nsSize& aSize) {
+ nsIFrame* frame = mTarget->GetPrimaryFrame();
+
+ // Update mContentRect.
+ nsMargin padding = frame ? frame->GetUsedPadding(): nsMargin();
+ // Per the spec, we need to use the top-left padding offset as the origin of
+ // our contentRect.
+ nsRect rect(nsPoint(padding.left, padding.top), aSize);
+ RefPtr<DOMRect> contentRect = new DOMRect(mTarget);
+ contentRect->SetLayoutRect(rect);
+ mContentRect = contentRect.forget();
+
+ // Update mContentBoxSize.
+ WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
+ mContentBoxSize = new ResizeObserverSize(this, aSize, wm);
+}
+
+ResizeObserverEntry::~ResizeObserverEntry()
+{
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObserverSize, mOwner)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserverSize)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserverSize)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserverSize)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObservation)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObservation)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObservation)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObservation,
+ mTarget, mOwner)
+
+bool
+ResizeObservation::IsActive() const
+{
+ nsIFrame* frame = mTarget->GetPrimaryFrame();
+ WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
+ LogicalSize size(wm, GetTargetSize(mTarget, mObservedBox));
+ return mLastReportedSize.ISize(mLastReportedWM) != size.ISize(wm) ||
+ mLastReportedSize.BSize(mLastReportedWM) != size.BSize(wm);
+}
+
+void
+ResizeObservation::UpdateLastReportedSize(const nsSize& aSize) {
+ nsIFrame* frame = mTarget->GetPrimaryFrame();
+ mLastReportedWM = frame ? frame->GetWritingMode() : WritingMode();
+ mLastReportedSize = LogicalSize(mLastReportedWM, aSize);
+}
+
+ResizeObservation::~ResizeObservation()
+{
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/base/ResizeObserver.h b/dom/base/ResizeObserver.h
index 92a7ee08cc..56675693ce 100644
--- a/dom/base/ResizeObserver.h
+++ b/dom/base/ResizeObserver.h
@@ -1,312 +1,312 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_ResizeObserver_h
-#define mozilla_dom_ResizeObserver_h
-
-#include "mozilla/AppUnits.h"
-#include "mozilla/WritingModes.h"
-#include "mozilla/dom/ResizeObserverBinding.h"
-#include "nsCoord.h"
-
-namespace mozilla {
-namespace dom {
-
-/**
- * ResizeObserver interfaces and algorithms are based on
- * https://wicg.github.io/ResizeObserver/#api
- */
-class ResizeObserver final
- : public nsISupports
- , public nsWrapperCache
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserver)
-
- ResizeObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
- ResizeObserverCallback& aCb)
- : mOwner(aOwner)
- , mCallback(&aCb)
- {
- MOZ_ASSERT(mOwner, "Need a non-null owner window");
- }
-
- static already_AddRefed<ResizeObserver>
- Constructor(const GlobalObject& aGlobal,
- ResizeObserverCallback& aCb,
- ErrorResult& aRv);
-
- JSObject* WrapObject(JSContext* aCx,
- JS::Handle<JSObject*> aGivenProto) override
- {
- return ResizeObserverBinding::Wrap(aCx, this, aGivenProto);
- }
-
- nsISupports* GetParentObject() const
- {
- return mOwner;
- }
-
- void Observe(Element* aTarget, const ResizeObserverOptions& aOptions, ErrorResult& aRv);
-
- void Unobserve(Element* aTarget, ErrorResult& aRv);
-
- void Disconnect();
-
- /*
- * Gather all observations which have an observed target with size changed
- * since last BroadcastActiveObservations() in this ResizeObserver.
- * An observation will be skipped if the depth of its observed target is less
- * or equal than aDepth. All gathered observations will be added to
- * mActiveTargets.
- */
- void GatherActiveObservations(uint32_t aDepth);
-
- /*
- * Returns whether this ResizeObserver has any active observations
- * since last GatherActiveObservations().
- */
- bool HasActiveObservations() const;
-
- /*
- * Returns whether this ResizeObserver has any skipped observations
- * since last GatherActiveObservations().
- */
- bool HasSkippedObservations() const;
-
- /*
- * Deliver the callback function in JavaScript for all active observations
- * and pass the sequence of ResizeObserverEntry so JavaScript can access them.
- * The active observations' mLastReportedSize fields will be updated, and
- * mActiveTargets will be cleared. It also returns the shallowest depth of
- * elements from active observations or numeric_limits<uint32_t>::max() if
- * there are not any active observations.
- */
- uint32_t BroadcastActiveObservations();
-
-protected:
- ~ResizeObserver()
- {
- mObservationList.clear();
- }
-
- nsCOMPtr<nsPIDOMWindowInner> mOwner;
- RefPtr<ResizeObserverCallback> mCallback;
- nsTArray<RefPtr<ResizeObservation>> mActiveTargets;
- // The spec uses a list to store the skipped targets. However, it seems what
- // we want is to check if there are any skipped targets (i.e. existence).
- // Therefore, we use a boolean value to represent the existence of skipped
- // targets.
- bool mHasSkippedTargets;
-
- // Combination of HashTable and LinkedList so we can iterate through
- // the elements of HashTable in order of insertion time.
- // Will be nice if we have our own data structure for this in the future.
- nsRefPtrHashtable<nsPtrHashKey<Element>, ResizeObservation> mObservationMap;
- LinkedList<ResizeObservation> mObservationList;
-};
-
-/**
- * ResizeObserverEntry is the entry that contains the information for observed
- * elements. This object is the one that visible to JavaScript in callback
- * function that is fired by ResizeObserver.
- */
-class ResizeObserverEntry final
- : public nsISupports
- , public nsWrapperCache
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverEntry)
-
- ResizeObserverEntry(nsISupports* aOwner, Element* aTarget)
- : mOwner(aOwner)
- , mTarget(aTarget)
- {
- MOZ_ASSERT(mOwner, "Need a non-null owner");
- MOZ_ASSERT(mTarget, "Need a non-null target element");
- }
-
- static already_AddRefed<ResizeObserverEntry>
- Constructor(const GlobalObject& aGlobal,
- Element* aTarget,
- ErrorResult& aRv);
-
- JSObject* WrapObject(JSContext* aCx,
- JS::Handle<JSObject*> aGivenProto) override
- {
- return ResizeObserverEntryBinding::Wrap(aCx, this,
- aGivenProto);
- }
-
- nsISupports* GetParentObject() const
- {
- return mOwner;
- }
-
- Element* Target() const
- {
- return mTarget;
- }
-
- /*
- * Returns the DOMRectReadOnly of target's content rect so it can be
- * accessed from JavaScript in callback function of ResizeObserver.
- */
- DOMRectReadOnly* GetContentRect() const
- {
- return mContentRect;
- }
-
- /**
- * Returns target's logical border-box size and content-box size as
- * ResizeObserverSize.
- */
- ResizeObserverSize* BorderBoxSize() const {
- return mBorderBoxSize;
- }
- ResizeObserverSize* ContentBoxSize() const {
- return mContentBoxSize;
- }
-
- // Set borderBoxSize.
- void SetBorderBoxSize(const nsSize& aSize);
- // Set contentRect and contentBoxSize.
- void SetContentRectAndSize(const nsSize& aSize);
-
-protected:
- ~ResizeObserverEntry();
-
- nsCOMPtr<nsISupports> mOwner;
- nsCOMPtr<Element> mTarget;
-
- RefPtr<DOMRectReadOnly> mContentRect;
- RefPtr<ResizeObserverSize> mBorderBoxSize;
- RefPtr<ResizeObserverSize> mContentBoxSize;
-};
-
-class ResizeObserverSize final : public nsISupports, public nsWrapperCache {
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverSize)
-
- // Note: the unit of |aSize| is app unit, and we convert it into css pixel in
- // the public JS APIs.
- ResizeObserverSize(nsISupports* aOwner, const nsSize& aSize,
- const WritingMode aWM)
- : mOwner(aOwner), mSize(aWM, aSize), mWM(aWM) {
- MOZ_ASSERT(mOwner, "Need a non-null owner");
- }
-
- nsISupports* GetParentObject() const { return mOwner; }
-
- JSObject* WrapObject(JSContext* aCx,
- JS::Handle<JSObject*> aGivenProto) override {
- return ResizeObserverSizeBinding::Wrap(aCx, this, aGivenProto);
- }
-
- double InlineSize() const {
- return NSAppUnitsToDoublePixels(mSize.ISize(mWM), AppUnitsPerCSSPixel());
- }
-
- double BlockSize() const {
- return NSAppUnitsToDoublePixels(mSize.BSize(mWM), AppUnitsPerCSSPixel());
- }
-
-protected:
- ~ResizeObserverSize() = default;
-
- nsCOMPtr<nsISupports> mOwner;
- const LogicalSize mSize;
- const WritingMode mWM;
-};
-
-/**
- * We use ResizeObservation to store and sync the size information of one
- * observed element so we can decide whether an observation should be fired
- * or not.
- */
-class ResizeObservation final
- : public nsISupports
- , public nsWrapperCache
- , public LinkedListElement<ResizeObservation>
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObservation)
-
- ResizeObservation(nsISupports* aOwner,
- Element* aTarget,
- ResizeObserverBoxOptions aBox,
- const WritingMode aWM)
- : mOwner(aOwner)
- , mTarget(aTarget)
- , mObservedBox(aBox)
- , mLastReportedSize(aWM)
- , mLastReportedWM(aWM)
- {
- MOZ_ASSERT(mOwner, "Need a non-null owner");
- MOZ_ASSERT(mTarget, "Need a non-null target element");
- }
-
- static already_AddRefed<ResizeObservation>
- Constructor(const GlobalObject& aGlobal,
- Element* aTarget,
- ErrorResult& aRv);
-
- JSObject* WrapObject(JSContext* aCx,
- JS::Handle<JSObject*> aGivenProto) override
- {
- return ResizeObservationBinding::Wrap(aCx, this, aGivenProto);
- }
-
- nsISupports* GetParentObject() const
- {
- return mOwner;
- }
-
- Element* Target() const
- {
- return mTarget;
- }
-
- ResizeObserverBoxOptions BoxOptions() const
- {
- return mObservedBox;
- }
-
- /*
- * Returns whether the observed target element size differs from the saved
- * mLastReportedSize.
- */
- bool IsActive() const;
-
- /*
- * Update current mLastReportedSize with size from aSize.
- */
- void UpdateLastReportedSize(const nsSize& aSize);
-
-protected:
- ~ResizeObservation();
-
- nsCOMPtr<nsISupports> mOwner;
- nsCOMPtr<Element> mTarget;
-
- const ResizeObserverBoxOptions mObservedBox;
-
- // The latest recorded size of observed target.
- // Per the spec, observation.lastReportedSize should be entry.borderBoxSize
- // or entry.contentBoxSize (i.e. logical size), instead of entry.contentRect
- // (i.e. physical rect), so we store this as LogicalSize.
- LogicalSize mLastReportedSize;
- WritingMode mLastReportedWM;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_ResizeObserver_h
-
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_ResizeObserver_h
+#define mozilla_dom_ResizeObserver_h
+
+#include "mozilla/AppUnits.h"
+#include "mozilla/WritingModes.h"
+#include "mozilla/dom/ResizeObserverBinding.h"
+#include "nsCoord.h"
+
+namespace mozilla {
+namespace dom {
+
+/**
+ * ResizeObserver interfaces and algorithms are based on
+ * https://wicg.github.io/ResizeObserver/#api
+ */
+class ResizeObserver final
+ : public nsISupports
+ , public nsWrapperCache
+{
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserver)
+
+ ResizeObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
+ ResizeObserverCallback& aCb)
+ : mOwner(aOwner)
+ , mCallback(&aCb)
+ {
+ MOZ_ASSERT(mOwner, "Need a non-null owner window");
+ }
+
+ static already_AddRefed<ResizeObserver>
+ Constructor(const GlobalObject& aGlobal,
+ ResizeObserverCallback& aCb,
+ ErrorResult& aRv);
+
+ JSObject* WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override
+ {
+ return ResizeObserverBinding::Wrap(aCx, this, aGivenProto);
+ }
+
+ nsISupports* GetParentObject() const
+ {
+ return mOwner;
+ }
+
+ void Observe(Element* aTarget, const ResizeObserverOptions& aOptions, ErrorResult& aRv);
+
+ void Unobserve(Element* aTarget, ErrorResult& aRv);
+
+ void Disconnect();
+
+ /*
+ * Gather all observations which have an observed target with size changed
+ * since last BroadcastActiveObservations() in this ResizeObserver.
+ * An observation will be skipped if the depth of its observed target is less
+ * or equal than aDepth. All gathered observations will be added to
+ * mActiveTargets.
+ */
+ void GatherActiveObservations(uint32_t aDepth);
+
+ /*
+ * Returns whether this ResizeObserver has any active observations
+ * since last GatherActiveObservations().
+ */
+ bool HasActiveObservations() const;
+
+ /*
+ * Returns whether this ResizeObserver has any skipped observations
+ * since last GatherActiveObservations().
+ */
+ bool HasSkippedObservations() const;
+
+ /*
+ * Deliver the callback function in JavaScript for all active observations
+ * and pass the sequence of ResizeObserverEntry so JavaScript can access them.
+ * The active observations' mLastReportedSize fields will be updated, and
+ * mActiveTargets will be cleared. It also returns the shallowest depth of
+ * elements from active observations or numeric_limits<uint32_t>::max() if
+ * there are not any active observations.
+ */
+ uint32_t BroadcastActiveObservations();
+
+protected:
+ ~ResizeObserver()
+ {
+ mObservationList.clear();
+ }
+
+ nsCOMPtr<nsPIDOMWindowInner> mOwner;
+ RefPtr<ResizeObserverCallback> mCallback;
+ nsTArray<RefPtr<ResizeObservation>> mActiveTargets;
+ // The spec uses a list to store the skipped targets. However, it seems what
+ // we want is to check if there are any skipped targets (i.e. existence).
+ // Therefore, we use a boolean value to represent the existence of skipped
+ // targets.
+ bool mHasSkippedTargets;
+
+ // Combination of HashTable and LinkedList so we can iterate through
+ // the elements of HashTable in order of insertion time.
+ // Will be nice if we have our own data structure for this in the future.
+ nsRefPtrHashtable<nsPtrHashKey<Element>, ResizeObservation> mObservationMap;
+ LinkedList<ResizeObservation> mObservationList;
+};
+
+/**
+ * ResizeObserverEntry is the entry that contains the information for observed
+ * elements. This object is the one that visible to JavaScript in callback
+ * function that is fired by ResizeObserver.
+ */
+class ResizeObserverEntry final
+ : public nsISupports
+ , public nsWrapperCache
+{
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverEntry)
+
+ ResizeObserverEntry(nsISupports* aOwner, Element* aTarget)
+ : mOwner(aOwner)
+ , mTarget(aTarget)
+ {
+ MOZ_ASSERT(mOwner, "Need a non-null owner");
+ MOZ_ASSERT(mTarget, "Need a non-null target element");
+ }
+
+ static already_AddRefed<ResizeObserverEntry>
+ Constructor(const GlobalObject& aGlobal,
+ Element* aTarget,
+ ErrorResult& aRv);
+
+ JSObject* WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override
+ {
+ return ResizeObserverEntryBinding::Wrap(aCx, this,
+ aGivenProto);
+ }
+
+ nsISupports* GetParentObject() const
+ {
+ return mOwner;
+ }
+
+ Element* Target() const
+ {
+ return mTarget;
+ }
+
+ /*
+ * Returns the DOMRectReadOnly of target's content rect so it can be
+ * accessed from JavaScript in callback function of ResizeObserver.
+ */
+ DOMRectReadOnly* GetContentRect() const
+ {
+ return mContentRect;
+ }
+
+ /**
+ * Returns target's logical border-box size and content-box size as
+ * ResizeObserverSize.
+ */
+ ResizeObserverSize* BorderBoxSize() const {
+ return mBorderBoxSize;
+ }
+ ResizeObserverSize* ContentBoxSize() const {
+ return mContentBoxSize;
+ }
+
+ // Set borderBoxSize.
+ void SetBorderBoxSize(const nsSize& aSize);
+ // Set contentRect and contentBoxSize.
+ void SetContentRectAndSize(const nsSize& aSize);
+
+protected:
+ ~ResizeObserverEntry();
+
+ nsCOMPtr<nsISupports> mOwner;
+ nsCOMPtr<Element> mTarget;
+
+ RefPtr<DOMRectReadOnly> mContentRect;
+ RefPtr<ResizeObserverSize> mBorderBoxSize;
+ RefPtr<ResizeObserverSize> mContentBoxSize;
+};
+
+class ResizeObserverSize final : public nsISupports, public nsWrapperCache {
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverSize)
+
+ // Note: the unit of |aSize| is app unit, and we convert it into css pixel in
+ // the public JS APIs.
+ ResizeObserverSize(nsISupports* aOwner, const nsSize& aSize,
+ const WritingMode aWM)
+ : mOwner(aOwner), mSize(aWM, aSize), mWM(aWM) {
+ MOZ_ASSERT(mOwner, "Need a non-null owner");
+ }
+
+ nsISupports* GetParentObject() const { return mOwner; }
+
+ JSObject* WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override {
+ return ResizeObserverSizeBinding::Wrap(aCx, this, aGivenProto);
+ }
+
+ double InlineSize() const {
+ return NSAppUnitsToDoublePixels(mSize.ISize(mWM), AppUnitsPerCSSPixel());
+ }
+
+ double BlockSize() const {
+ return NSAppUnitsToDoublePixels(mSize.BSize(mWM), AppUnitsPerCSSPixel());
+ }
+
+protected:
+ ~ResizeObserverSize() = default;
+
+ nsCOMPtr<nsISupports> mOwner;
+ const LogicalSize mSize;
+ const WritingMode mWM;
+};
+
+/**
+ * We use ResizeObservation to store and sync the size information of one
+ * observed element so we can decide whether an observation should be fired
+ * or not.
+ */
+class ResizeObservation final
+ : public nsISupports
+ , public nsWrapperCache
+ , public LinkedListElement<ResizeObservation>
+{
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObservation)
+
+ ResizeObservation(nsISupports* aOwner,
+ Element* aTarget,
+ ResizeObserverBoxOptions aBox,
+ const WritingMode aWM)
+ : mOwner(aOwner)
+ , mTarget(aTarget)
+ , mObservedBox(aBox)
+ , mLastReportedSize(aWM)
+ , mLastReportedWM(aWM)
+ {
+ MOZ_ASSERT(mOwner, "Need a non-null owner");
+ MOZ_ASSERT(mTarget, "Need a non-null target element");
+ }
+
+ static already_AddRefed<ResizeObservation>
+ Constructor(const GlobalObject& aGlobal,
+ Element* aTarget,
+ ErrorResult& aRv);
+
+ JSObject* WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override
+ {
+ return ResizeObservationBinding::Wrap(aCx, this, aGivenProto);
+ }
+
+ nsISupports* GetParentObject() const
+ {
+ return mOwner;
+ }
+
+ Element* Target() const
+ {
+ return mTarget;
+ }
+
+ ResizeObserverBoxOptions BoxOptions() const
+ {
+ return mObservedBox;
+ }
+
+ /*
+ * Returns whether the observed target element size differs from the saved
+ * mLastReportedSize.
+ */
+ bool IsActive() const;
+
+ /*
+ * Update current mLastReportedSize with size from aSize.
+ */
+ void UpdateLastReportedSize(const nsSize& aSize);
+
+protected:
+ ~ResizeObservation();
+
+ nsCOMPtr<nsISupports> mOwner;
+ nsCOMPtr<Element> mTarget;
+
+ const ResizeObserverBoxOptions mObservedBox;
+
+ // The latest recorded size of observed target.
+ // Per the spec, observation.lastReportedSize should be entry.borderBoxSize
+ // or entry.contentBoxSize (i.e. logical size), instead of entry.contentRect
+ // (i.e. physical rect), so we store this as LogicalSize.
+ LogicalSize mLastReportedSize;
+ WritingMode mLastReportedWM;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ResizeObserver_h
+
diff --git a/dom/base/ResizeObserverController.h b/dom/base/ResizeObserverController.h
index 01169112aa..346d5ab93f 100644
--- a/dom/base/ResizeObserverController.h
+++ b/dom/base/ResizeObserverController.h
@@ -41,9 +41,9 @@ public:
void Disconnect();
- bool IsRegistered() const { return mRegistered; }
-
- void DetachFromOwner() { mOwner = nullptr; }
+ bool IsRegistered() const { return mRegistered; }
+
+ void DetachFromOwner() { mOwner = nullptr; }
protected:
virtual ~ResizeObserverNotificationHelper();