LCOV - code coverage report
Current view: top level - dom/base - DOMIntersectionObserver.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 276 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 30 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "DOMIntersectionObserver.h"
       8             : #include "nsCSSParser.h"
       9             : #include "nsCSSPropertyID.h"
      10             : #include "nsIFrame.h"
      11             : #include "nsContentUtils.h"
      12             : #include "nsLayoutUtils.h"
      13             : 
      14             : namespace mozilla {
      15             : namespace dom {
      16             : 
      17           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMIntersectionObserverEntry)
      18           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      19           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      20           0 : NS_INTERFACE_MAP_END
      21             : 
      22           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMIntersectionObserverEntry)
      23           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMIntersectionObserverEntry)
      24             : 
      25           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMIntersectionObserverEntry, mOwner,
      26             :                                       mRootBounds, mBoundingClientRect,
      27             :                                       mIntersectionRect, mTarget)
      28             : 
      29           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMIntersectionObserver)
      30           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      31           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      32           0 :   NS_INTERFACE_MAP_ENTRY(DOMIntersectionObserver)
      33           0 : NS_INTERFACE_MAP_END
      34             : 
      35           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMIntersectionObserver)
      36           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMIntersectionObserver)
      37             : 
      38             : NS_IMPL_CYCLE_COLLECTION_CLASS(DOMIntersectionObserver)
      39             : 
      40           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMIntersectionObserver)
      41           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
      42           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      43             : 
      44           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver)
      45           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
      46           0 :   tmp->Disconnect();
      47           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
      48           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
      49           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
      50           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
      51           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueuedEntries)
      52           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      53             : 
      54           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver)
      55           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
      56           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
      57           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
      58           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
      59           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mQueuedEntries)
      60           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      61             : 
      62             : already_AddRefed<DOMIntersectionObserver>
      63           0 : DOMIntersectionObserver::Constructor(const mozilla::dom::GlobalObject& aGlobal,
      64             :                                      mozilla::dom::IntersectionCallback& aCb,
      65             :                                      mozilla::ErrorResult& aRv)
      66             : {
      67           0 :   return Constructor(aGlobal, aCb, IntersectionObserverInit(), aRv);
      68             : }
      69             : 
      70             : already_AddRefed<DOMIntersectionObserver>
      71           0 : DOMIntersectionObserver::Constructor(const mozilla::dom::GlobalObject& aGlobal,
      72             :                                      mozilla::dom::IntersectionCallback& aCb,
      73             :                                      const mozilla::dom::IntersectionObserverInit& aOptions,
      74             :                                      mozilla::ErrorResult& aRv)
      75             : {
      76           0 :   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
      77           0 :   if (!window) {
      78           0 :     aRv.Throw(NS_ERROR_FAILURE);
      79           0 :     return nullptr;
      80             :   }
      81             :   RefPtr<DOMIntersectionObserver> observer =
      82           0 :     new DOMIntersectionObserver(window.forget(), aCb);
      83             : 
      84           0 :   observer->mRoot = aOptions.mRoot;
      85             : 
      86           0 :   if (!observer->SetRootMargin(aOptions.mRootMargin)) {
      87           0 :     aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
      88           0 :       NS_LITERAL_CSTRING("rootMargin must be specified in pixels or percent."));
      89           0 :     return nullptr;
      90             :   }
      91             : 
      92           0 :   if (aOptions.mThreshold.IsDoubleSequence()) {
      93           0 :     const mozilla::dom::Sequence<double>& thresholds = aOptions.mThreshold.GetAsDoubleSequence();
      94           0 :     observer->mThresholds.SetCapacity(thresholds.Length());
      95           0 :     for (const auto& thresh : thresholds) {
      96           0 :       if (thresh < 0.0 || thresh > 1.0) {
      97           0 :         aRv.ThrowTypeError<dom::MSG_THRESHOLD_RANGE_ERROR>();
      98           0 :         return nullptr;
      99             :       }
     100           0 :       observer->mThresholds.AppendElement(thresh);
     101             :     }
     102           0 :     observer->mThresholds.Sort();
     103             :   } else {
     104           0 :     double thresh = aOptions.mThreshold.GetAsDouble();
     105           0 :     if (thresh < 0.0 || thresh > 1.0) {
     106           0 :       aRv.ThrowTypeError<dom::MSG_THRESHOLD_RANGE_ERROR>();
     107           0 :       return nullptr;
     108             :     }
     109           0 :     observer->mThresholds.AppendElement(thresh);
     110             :   }
     111             : 
     112           0 :   return observer.forget();
     113             : }
     114             : 
     115             : bool
     116           0 : DOMIntersectionObserver::SetRootMargin(const nsAString& aString)
     117             : {
     118             :   // By not passing a CSS Loader object we make sure we don't parse in quirks
     119             :   // mode so that pixel/percent and unit-less values will be differentiated.
     120           0 :   nsCSSParser parser(nullptr);
     121           0 :   nsCSSValue value;
     122           0 :   if (!parser.ParseMarginString(aString, nullptr, 0, value, true)) {
     123           0 :     return false;
     124             :   }
     125             : 
     126           0 :   mRootMargin = value.GetRectValue();
     127             : 
     128           0 :   for (auto side : nsCSSRect::sides) {
     129           0 :     nsCSSValue& value = mRootMargin.*side;
     130           0 :     if (!(value.IsPixelLengthUnit() || value.IsPercentLengthUnit())) {
     131           0 :       return false;
     132             :     }
     133             :   }
     134             : 
     135           0 :   return true;
     136             : }
     137             : 
     138             : void
     139           0 : DOMIntersectionObserver::GetRootMargin(mozilla::dom::DOMString& aRetVal)
     140             : {
     141           0 :   mRootMargin.AppendToString(eCSSProperty_DOM, aRetVal, nsCSSValue::eNormalized);
     142           0 : }
     143             : 
     144             : void
     145           0 : DOMIntersectionObserver::GetThresholds(nsTArray<double>& aRetVal)
     146             : {
     147           0 :   aRetVal = mThresholds;
     148           0 : }
     149             : 
     150             : void
     151           0 : DOMIntersectionObserver::Observe(Element& aTarget)
     152             : {
     153           0 :   if (mObservationTargets.Contains(&aTarget)) {
     154           0 :     return;
     155             :   }
     156           0 :   aTarget.RegisterIntersectionObserver(this);
     157           0 :   mObservationTargets.AppendElement(&aTarget);
     158           0 :   Connect();
     159             : }
     160             : 
     161             : void
     162           0 : DOMIntersectionObserver::Unobserve(Element& aTarget)
     163             : {
     164           0 :   if (mObservationTargets.Length() == 1) {
     165           0 :     Disconnect();
     166           0 :     return;
     167             :   }
     168             : 
     169           0 :   mObservationTargets.RemoveElement(&aTarget);
     170           0 :   aTarget.UnregisterIntersectionObserver(this);
     171             : }
     172             : 
     173             : void
     174           0 : DOMIntersectionObserver::UnlinkTarget(Element& aTarget)
     175             : {
     176           0 :   mObservationTargets.RemoveElement(&aTarget);
     177           0 :   if (mObservationTargets.Length() == 0) {
     178           0 :     Disconnect();
     179             :   }
     180           0 : }
     181             : 
     182             : void
     183           0 : DOMIntersectionObserver::Connect()
     184             : {
     185           0 :   if (mConnected) {
     186           0 :     return;
     187             :   }
     188             : 
     189           0 :   mConnected = true;
     190           0 :   if (mDocument) {
     191           0 :     mDocument->AddIntersectionObserver(this);
     192             :   }
     193             : }
     194             : 
     195             : void
     196           0 : DOMIntersectionObserver::Disconnect()
     197             : {
     198           0 :   if (!mConnected) {
     199           0 :     return;
     200             :   }
     201             : 
     202           0 :   mConnected = false;
     203           0 :   for (size_t i = 0; i < mObservationTargets.Length(); ++i) {
     204           0 :     Element* target = mObservationTargets.ElementAt(i);
     205           0 :     target->UnregisterIntersectionObserver(this);
     206             :   }
     207           0 :   mObservationTargets.Clear();
     208           0 :   if (mDocument) {
     209           0 :     mDocument->RemoveIntersectionObserver(this);
     210             :   }
     211             : }
     212             : 
     213             : void
     214           0 : DOMIntersectionObserver::TakeRecords(nsTArray<RefPtr<DOMIntersectionObserverEntry>>& aRetVal)
     215             : {
     216           0 :   aRetVal.SwapElements(mQueuedEntries);
     217           0 :   mQueuedEntries.Clear();
     218           0 : }
     219             : 
     220             : static bool
     221           0 : CheckSimilarOrigin(nsINode* aNode1, nsINode* aNode2)
     222             : {
     223           0 :   nsIPrincipal* principal1 = aNode1->NodePrincipal();
     224           0 :   nsIPrincipal* principal2 = aNode2->NodePrincipal();
     225           0 :   nsAutoCString baseDomain1;
     226           0 :   nsAutoCString baseDomain2;
     227             : 
     228           0 :   nsresult rv = principal1->GetBaseDomain(baseDomain1);
     229           0 :   if (NS_FAILED(rv)) {
     230           0 :     return principal1 == principal2;
     231             :   }
     232             : 
     233           0 :   rv = principal2->GetBaseDomain(baseDomain2);
     234           0 :   if (NS_FAILED(rv)) {
     235           0 :     return principal1 == principal2;
     236             :   }
     237             : 
     238           0 :   return baseDomain1 == baseDomain2;
     239             : }
     240             : 
     241             : static Maybe<nsRect>
     242           0 : EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect)
     243             : {
     244           0 :   nscoord left = std::max(aRect.x, aOtherRect.x);
     245           0 :   nscoord top = std::max(aRect.y, aOtherRect.y);
     246           0 :   nscoord right = std::min(aRect.XMost(), aOtherRect.XMost());
     247           0 :   nscoord bottom = std::min(aRect.YMost(), aOtherRect.YMost());
     248           0 :   if (left > right || top > bottom) {
     249           0 :     return Nothing();
     250             :   }
     251           0 :   return Some(nsRect(left, top, right - left, bottom - top));
     252             : }
     253             : 
     254             : enum class BrowsingContextInfo {
     255             :   SimilarOriginBrowsingContext,
     256             :   DifferentOriginBrowsingContext,
     257             :   UnknownBrowsingContext
     258             : };
     259             : 
     260             : void
     261           0 : DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time)
     262             : {
     263           0 :   Element* root = nullptr;
     264           0 :   nsIFrame* rootFrame = nullptr;
     265           0 :   nsRect rootRect;
     266             : 
     267           0 :   if (mRoot) {
     268           0 :     root = mRoot;
     269           0 :     rootFrame = root->GetPrimaryFrame();
     270           0 :     if (rootFrame) {
     271           0 :       nsRect rootRectRelativeToRootFrame;
     272           0 :       if (rootFrame->IsScrollFrame()) {
     273             :         // rootRectRelativeToRootFrame should be the content rect of rootFrame, not including the scrollbars.
     274           0 :         nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
     275           0 :         rootRectRelativeToRootFrame = scrollFrame->GetScrollPortRect();
     276             :       } else {
     277             :         // rootRectRelativeToRootFrame should be the border rect of rootFrame.
     278           0 :         rootRectRelativeToRootFrame = rootFrame->GetRectRelativeToSelf();
     279             :       }
     280             :       nsIFrame* containingBlock =
     281           0 :         nsLayoutUtils::GetContainingBlockForClientRect(rootFrame);
     282           0 :       rootRect =
     283           0 :         nsLayoutUtils::TransformFrameRectToAncestor(rootFrame,
     284             :                                                     rootRectRelativeToRootFrame,
     285             :                                                     containingBlock);
     286             :     }
     287             :   } else {
     288           0 :     nsCOMPtr<nsIPresShell> presShell = aDocument->GetShell();
     289           0 :     if (presShell) {
     290           0 :       rootFrame = presShell->GetRootScrollFrame();
     291           0 :       if (rootFrame) {
     292           0 :         nsPresContext* presContext = rootFrame->PresContext();
     293           0 :         while (!presContext->IsRootContentDocument()) {
     294           0 :           presContext = presContext->GetParentPresContext();
     295           0 :           if (!presContext) {
     296           0 :             break;
     297             :           }
     298           0 :           nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
     299           0 :           if (rootScrollFrame) {
     300           0 :             rootFrame = rootScrollFrame;
     301             :           } else {
     302           0 :             break;
     303             :           }
     304             :         }
     305           0 :         root = rootFrame->GetContent()->AsElement();
     306           0 :         nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
     307           0 :         rootRect = scrollFrame->GetScrollPortRect();
     308             :       }
     309             :     }
     310             :   }
     311             : 
     312           0 :   nsMargin rootMargin;
     313           0 :   NS_FOR_CSS_SIDES(side) {
     314           0 :     nscoord basis = side == eSideTop || side == eSideBottom ?
     315           0 :       rootRect.height : rootRect.width;
     316           0 :     nsCSSValue value = mRootMargin.*nsCSSRect::sides[side];
     317           0 :     nsStyleCoord coord;
     318           0 :     if (value.IsPixelLengthUnit()) {
     319           0 :       coord.SetCoordValue(value.GetPixelLength());
     320           0 :     } else if (value.IsPercentLengthUnit()) {
     321           0 :       coord.SetPercentValue(value.GetPercentValue());
     322             :     } else {
     323           0 :       MOZ_ASSERT_UNREACHABLE("invalid length unit");
     324             :     }
     325           0 :     rootMargin.Side(side) = nsLayoutUtils::ComputeCBDependentValue(basis, coord);
     326             :   }
     327             : 
     328           0 :   for (size_t i = 0; i < mObservationTargets.Length(); ++i) {
     329           0 :     Element* target = mObservationTargets.ElementAt(i);
     330           0 :     nsIFrame* targetFrame = target->GetPrimaryFrame();
     331           0 :     nsRect targetRect;
     332           0 :     Maybe<nsRect> intersectionRect;
     333           0 :     bool isSameDoc = root && root->GetComposedDoc() == target->GetComposedDoc();
     334             : 
     335           0 :     if (rootFrame && targetFrame) {
     336             :       // If mRoot is set we are testing intersection with a container element
     337             :       // instead of the implicit root.
     338           0 :       if (mRoot) {
     339             :         // Skip further processing of this target if it is not in the same
     340             :         // Document as the intersection root, e.g. if root is an element of
     341             :         // the main document and target an element from an embedded iframe.
     342           0 :         if (!isSameDoc) {
     343           0 :           continue;
     344             :         }
     345             :         // Skip further processing of this target if is not a descendant of the
     346             :         // intersection root in the containing block chain. E.g. this would be
     347             :         // the case if the target is in a position:absolute element whose
     348             :         // containing block is an ancestor of root.
     349           0 :         if (!nsLayoutUtils::IsAncestorFrameCrossDoc(rootFrame, targetFrame)) {
     350           0 :           continue;
     351             :         }
     352             :       }
     353             : 
     354           0 :       targetRect = nsLayoutUtils::GetAllInFlowRectsUnion(
     355             :         targetFrame,
     356             :         nsLayoutUtils::GetContainingBlockForClientRect(targetFrame),
     357             :         nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS
     358             :       );
     359           0 :       intersectionRect = Some(targetFrame->GetRectRelativeToSelf());
     360             : 
     361           0 :       nsIFrame* containerFrame = nsLayoutUtils::GetCrossDocParentFrame(targetFrame);
     362           0 :       while (containerFrame && containerFrame != rootFrame) {
     363           0 :         if (containerFrame->IsScrollFrame()) {
     364           0 :           nsIScrollableFrame* scrollFrame = do_QueryFrame(containerFrame);
     365           0 :           nsRect subFrameRect = scrollFrame->GetScrollPortRect();
     366             :           nsRect intersectionRectRelativeToContainer =
     367             :             nsLayoutUtils::TransformFrameRectToAncestor(targetFrame,
     368           0 :                                                         intersectionRect.value(),
     369           0 :                                                         containerFrame);
     370           0 :           intersectionRect = EdgeInclusiveIntersection(intersectionRectRelativeToContainer,
     371           0 :                                                        subFrameRect);
     372           0 :           if (!intersectionRect) {
     373           0 :             break;
     374             :           }
     375           0 :           targetFrame = containerFrame;
     376             :         }
     377             : 
     378             :         // TODO: Apply clip-path.
     379             : 
     380           0 :         containerFrame = nsLayoutUtils::GetCrossDocParentFrame(containerFrame);
     381             :       }
     382             :     }
     383             : 
     384           0 :     nsRect rootIntersectionRect;
     385             :     BrowsingContextInfo isInSimilarOriginBrowsingContext =
     386           0 :       BrowsingContextInfo::UnknownBrowsingContext;
     387             : 
     388           0 :     if (rootFrame && targetFrame) {
     389           0 :       rootIntersectionRect = rootRect;
     390             :     }
     391             : 
     392           0 :     if (root && target) {
     393           0 :       isInSimilarOriginBrowsingContext = CheckSimilarOrigin(root, target) ?
     394             :         BrowsingContextInfo::SimilarOriginBrowsingContext :
     395             :         BrowsingContextInfo::DifferentOriginBrowsingContext;
     396             :     }
     397             : 
     398           0 :     if (isInSimilarOriginBrowsingContext ==
     399             :         BrowsingContextInfo::SimilarOriginBrowsingContext) {
     400           0 :       rootIntersectionRect.Inflate(rootMargin);
     401             :     }
     402             : 
     403           0 :     if (intersectionRect.isSome()) {
     404             :       nsRect intersectionRectRelativeToRoot =
     405             :         nsLayoutUtils::TransformFrameRectToAncestor(
     406             :           targetFrame,
     407           0 :           intersectionRect.value(),
     408           0 :           nsLayoutUtils::GetContainingBlockForClientRect(rootFrame)
     409           0 :       );
     410           0 :       intersectionRect = EdgeInclusiveIntersection(
     411             :         intersectionRectRelativeToRoot,
     412             :         rootIntersectionRect
     413           0 :       );
     414           0 :       if (intersectionRect.isSome() && !isSameDoc) {
     415           0 :         nsRect rect = intersectionRect.value();
     416           0 :         nsPresContext* presContext = targetFrame->PresContext();
     417           0 :         nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
     418           0 :         if (rootScrollFrame) {
     419           0 :           nsLayoutUtils::TransformRect(rootFrame, rootScrollFrame, rect);
     420             :         }
     421           0 :         intersectionRect = Some(rect);
     422             :       }
     423             :     }
     424             : 
     425           0 :     double targetArea = targetRect.width * targetRect.height;
     426           0 :     double intersectionArea = !intersectionRect ?
     427           0 :       0 : intersectionRect->width * intersectionRect->height;
     428             : 
     429             :     double intersectionRatio;
     430           0 :     if (targetArea > 0.0) {
     431           0 :       intersectionRatio = intersectionArea / targetArea;
     432             :     } else {
     433           0 :       intersectionRatio = intersectionRect.isSome() ? 1.0 : 0.0;
     434             :     }
     435             : 
     436           0 :     size_t threshold = -1;
     437           0 :     if (intersectionRatio > 0.0) {
     438           0 :       if (intersectionRatio >= 1.0) {
     439           0 :         intersectionRatio = 1.0;
     440           0 :         threshold = mThresholds.Length();
     441             :       } else {
     442           0 :         for (size_t k = 0; k < mThresholds.Length(); ++k) {
     443           0 :           if (mThresholds[k] <= intersectionRatio) {
     444           0 :             threshold = k + 1;
     445             :           } else {
     446           0 :             break;
     447             :           }
     448             :         }
     449             :       }
     450           0 :     } else if (intersectionRect.isSome()) {
     451           0 :       threshold = 0;
     452             :     }
     453             : 
     454           0 :     if (target->UpdateIntersectionObservation(this, threshold)) {
     455             :       QueueIntersectionObserverEntry(
     456             :         target, time,
     457             :         isInSimilarOriginBrowsingContext ==
     458           0 :           BrowsingContextInfo::DifferentOriginBrowsingContext ?
     459           0 :           Nothing() : Some(rootIntersectionRect),
     460             :         targetRect, intersectionRect, intersectionRatio
     461           0 :       );
     462             :     }
     463             :   }
     464           0 : }
     465             : 
     466             : void
     467           0 : DOMIntersectionObserver::QueueIntersectionObserverEntry(Element* aTarget,
     468             :                                                         DOMHighResTimeStamp time,
     469             :                                                         const Maybe<nsRect>& aRootRect,
     470             :                                                         const nsRect& aTargetRect,
     471             :                                                         const Maybe<nsRect>& aIntersectionRect,
     472             :                                                         double aIntersectionRatio)
     473             : {
     474           0 :   RefPtr<DOMRect> rootBounds;
     475           0 :   if (aRootRect.isSome()) {
     476           0 :     rootBounds = new DOMRect(this);
     477           0 :     rootBounds->SetLayoutRect(aRootRect.value());
     478             :   }
     479           0 :   RefPtr<DOMRect> boundingClientRect = new DOMRect(this);
     480           0 :   boundingClientRect->SetLayoutRect(aTargetRect);
     481           0 :   RefPtr<DOMRect> intersectionRect = new DOMRect(this);
     482           0 :   if (aIntersectionRect.isSome()) {
     483           0 :     intersectionRect->SetLayoutRect(aIntersectionRect.value());
     484             :   }
     485             :   RefPtr<DOMIntersectionObserverEntry> entry = new DOMIntersectionObserverEntry(
     486             :     this,
     487             :     time,
     488           0 :     rootBounds.forget(),
     489           0 :     boundingClientRect.forget(),
     490           0 :     intersectionRect.forget(),
     491           0 :     aIntersectionRect.isSome(),
     492           0 :     aTarget, aIntersectionRatio);
     493           0 :   mQueuedEntries.AppendElement(entry.forget());
     494           0 : }
     495             : 
     496             : void
     497           0 : DOMIntersectionObserver::Notify()
     498             : {
     499           0 :   if (!mQueuedEntries.Length()) {
     500           0 :     return;
     501             :   }
     502           0 :   mozilla::dom::Sequence<mozilla::OwningNonNull<DOMIntersectionObserverEntry>> entries;
     503           0 :   if (entries.SetCapacity(mQueuedEntries.Length(), mozilla::fallible)) {
     504           0 :     for (size_t i = 0; i < mQueuedEntries.Length(); ++i) {
     505           0 :       RefPtr<DOMIntersectionObserverEntry> next = mQueuedEntries[i];
     506           0 :       *entries.AppendElement(mozilla::fallible) = next;
     507             :     }
     508             :   }
     509           0 :   mQueuedEntries.Clear();
     510           0 :   mCallback->Call(this, entries, *this);
     511             : }
     512             : 
     513             : 
     514             : } // namespace dom
     515             : } // namespace mozilla

Generated by: LCOV version 1.13