From 2703c4fc63244617ec49cf869460e93fd9967864 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 21 Jun 2021 00:40:58 +0000 Subject: [PATCH] [whitespace] Fix CRLF line endings. When originally implementing ResizeObserver, line endings ended up being CRLF instead of LF. This commit fixes those line endings (no code changes) --- dom/base/ResizeObserver.cpp | 752 ++++++++++++++-------------- dom/base/ResizeObserver.h | 624 +++++++++++------------ dom/base/ResizeObserverController.h | 6 +- 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::Constructor(const GlobalObject& aGlobal, - ResizeObserverCallback& aCb, - ErrorResult& aRv) -{ - nsCOMPtr window = - do_QueryInterface(aGlobal.GetAsSupports()); - - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr document = window->GetExtantDoc(); - - if (!document) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr 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 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 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> entries; - - for (auto observation : mActiveTargets) { - Element* target = observation->Target(); - RefPtr 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::Constructor(const GlobalObject& aGlobal, - Element* aTarget, - ErrorResult& aRv) -{ - RefPtr 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 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::Constructor(const GlobalObject& aGlobal, + ResizeObserverCallback& aCb, + ErrorResult& aRv) +{ + nsCOMPtr window = + do_QueryInterface(aGlobal.GetAsSupports()); + + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsCOMPtr document = window->GetExtantDoc(); + + if (!document) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr 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 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 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> entries; + + for (auto observation : mActiveTargets) { + Element* target = observation->Target(); + RefPtr 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::Constructor(const GlobalObject& aGlobal, + Element* aTarget, + ErrorResult& aRv) +{ + RefPtr 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 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&& aOwner, - ResizeObserverCallback& aCb) - : mOwner(aOwner) - , mCallback(&aCb) - { - MOZ_ASSERT(mOwner, "Need a non-null owner window"); - } - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - ResizeObserverCallback& aCb, - ErrorResult& aRv); - - JSObject* WrapObject(JSContext* aCx, - JS::Handle 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::max() if - * there are not any active observations. - */ - uint32_t BroadcastActiveObservations(); - -protected: - ~ResizeObserver() - { - mObservationList.clear(); - } - - nsCOMPtr mOwner; - RefPtr mCallback; - nsTArray> 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, ResizeObservation> mObservationMap; - LinkedList 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 - Constructor(const GlobalObject& aGlobal, - Element* aTarget, - ErrorResult& aRv); - - JSObject* WrapObject(JSContext* aCx, - JS::Handle 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 mOwner; - nsCOMPtr mTarget; - - RefPtr mContentRect; - RefPtr mBorderBoxSize; - RefPtr 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 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 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 -{ -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 - Constructor(const GlobalObject& aGlobal, - Element* aTarget, - ErrorResult& aRv); - - JSObject* WrapObject(JSContext* aCx, - JS::Handle 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 mOwner; - nsCOMPtr 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&& aOwner, + ResizeObserverCallback& aCb) + : mOwner(aOwner) + , mCallback(&aCb) + { + MOZ_ASSERT(mOwner, "Need a non-null owner window"); + } + + static already_AddRefed + Constructor(const GlobalObject& aGlobal, + ResizeObserverCallback& aCb, + ErrorResult& aRv); + + JSObject* WrapObject(JSContext* aCx, + JS::Handle 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::max() if + * there are not any active observations. + */ + uint32_t BroadcastActiveObservations(); + +protected: + ~ResizeObserver() + { + mObservationList.clear(); + } + + nsCOMPtr mOwner; + RefPtr mCallback; + nsTArray> 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, ResizeObservation> mObservationMap; + LinkedList 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 + Constructor(const GlobalObject& aGlobal, + Element* aTarget, + ErrorResult& aRv); + + JSObject* WrapObject(JSContext* aCx, + JS::Handle 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 mOwner; + nsCOMPtr mTarget; + + RefPtr mContentRect; + RefPtr mBorderBoxSize; + RefPtr 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 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 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 +{ +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 + Constructor(const GlobalObject& aGlobal, + Element* aTarget, + ErrorResult& aRv); + + JSObject* WrapObject(JSContext* aCx, + JS::Handle 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 mOwner; + nsCOMPtr 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();