Backout revision 111c1227f51e (bug 1243846) for test_intersectionobservers.html failures on android a=backout CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Thu, 27 Oct 2016 14:16:10 -0700
changeset 319869 1e7d830ec82857d197cae4c23d9b1b4fc4cfca23
parent 319868 46acc32392759b90b5122d7678464b83ff34b5fd
child 319870 5d495bd2e961c3e4455568cbeec3feda15e1f383
push id20749
push userryanvm@gmail.com
push dateSat, 29 Oct 2016 13:21:21 +0000
treeherderfx-team@1b170b39ed6b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1243846
milestone52.0a1
backs out111c1227f51eb6e94d7213f92b2a32e55bfdf3e8
Backout revision 111c1227f51e (bug 1243846) for test_intersectionobservers.html failures on android a=backout CLOSED TREE
dom/base/DOMIntersectionObserver.cpp
dom/base/DOMIntersectionObserver.h
dom/base/Element.cpp
dom/base/Element.h
dom/base/FragmentOrElement.h
dom/base/moz.build
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsIDocument.h
dom/base/test/intersectionobserver_iframe.html
dom/base/test/intersectionobserver_window.html
dom/base/test/mochitest.ini
dom/base/test/test_intersectionobservers.html
dom/bindings/Bindings.conf
dom/bindings/Errors.msg
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/DOMRect.webidl
dom/webidl/IntersectionObserver.webidl
dom/webidl/moz.build
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSParser.h
layout/style/nsCSSPropertyID.h
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
deleted file mode 100644
--- a/dom/base/DOMIntersectionObserver.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "DOMIntersectionObserver.h"
-#include "nsCSSParser.h"
-#include "nsCSSPropertyID.h"
-#include "nsIFrame.h"
-#include "nsContentUtils.h"
-#include "nsLayoutUtils.h"
-
-namespace mozilla {
-namespace dom {
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMIntersectionObserverEntry)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMIntersectionObserverEntry)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMIntersectionObserverEntry)
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMIntersectionObserverEntry, mOwner,
-                                      mRootBounds, mBoundingClientRect,
-                                      mIntersectionRect, mTarget)
-
-double
-DOMIntersectionObserverEntry::IntersectionRatio()
-{
-  double targetArea = mBoundingClientRect->Width() * mBoundingClientRect->Height();
-  double intersectionArea = mIntersectionRect->Width() * mIntersectionRect->Height();
-  double intersectionRatio = targetArea > 0.0 ? intersectionArea / targetArea : 0.0;
-  return intersectionRatio;
-}
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMIntersectionObserver)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_INTERFACE_MAP_ENTRY(DOMIntersectionObserver)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMIntersectionObserver)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMIntersectionObserver)
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMIntersectionObserver)
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMIntersectionObserver)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueuedEntries)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mQueuedEntries)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-already_AddRefed<DOMIntersectionObserver>
-DOMIntersectionObserver::Constructor(const mozilla::dom::GlobalObject& aGlobal,
-                                     mozilla::dom::IntersectionCallback& aCb,
-                                     mozilla::ErrorResult& aRv)
-{
-  return Constructor(aGlobal, aCb, IntersectionObserverInit(), aRv);
-}
-
-already_AddRefed<DOMIntersectionObserver>
-DOMIntersectionObserver::Constructor(const mozilla::dom::GlobalObject& aGlobal,
-                                     mozilla::dom::IntersectionCallback& aCb,
-                                     const mozilla::dom::IntersectionObserverInit& aOptions,
-                                     mozilla::ErrorResult& aRv)
-{
-  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
-  if (!window) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-  RefPtr<DOMIntersectionObserver> observer =
-    new DOMIntersectionObserver(window.forget(), aCb);
-
-  observer->mRoot = aOptions.mRoot;
-
-  if (!observer->SetRootMargin(aOptions.mRootMargin)) {
-    aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
-      NS_LITERAL_CSTRING("rootMargin must be specified in pixels or percent."));
-    return nullptr;
-  }
-
-  if (aOptions.mThreshold.IsDoubleSequence()) {
-    const mozilla::dom::Sequence<double>& thresholds = aOptions.mThreshold.GetAsDoubleSequence();
-    observer->mThresholds.SetCapacity(thresholds.Length());
-    for (const auto& thresh : thresholds) {
-      if (thresh < 0.0 || thresh > 1.0) {
-        aRv.ThrowTypeError<dom::MSG_THRESHOLD_RANGE_ERROR>();
-        return nullptr;
-      }
-      observer->mThresholds.AppendElement(thresh);
-    }
-    observer->mThresholds.Sort();
-  } else {
-    double thresh = aOptions.mThreshold.GetAsDouble();
-    if (thresh < 0.0 || thresh > 1.0) {
-      aRv.ThrowTypeError<dom::MSG_THRESHOLD_RANGE_ERROR>();
-      return nullptr;
-    }
-    observer->mThresholds.AppendElement(thresh);
-  }
-
-  return observer.forget();
-}
-
-bool
-DOMIntersectionObserver::SetRootMargin(const nsAString& aString)
-{
-  // By not passing a CSS Loader object we make sure we don't parse in quirks
-  // mode so that pixel/percent and unit-less values will be differentiated.
-  nsCSSParser parser(nullptr);
-  nsCSSValue value;
-  if (!parser.ParseMarginString(aString, nullptr, 0, value, true)) {
-    return false;
-  }
-
-  mRootMargin = value.GetRectValue();
-
-  for (uint32_t i = 0; i < ArrayLength(nsCSSRect::sides); ++i) {
-    nsCSSValue value = mRootMargin.*nsCSSRect::sides[i];
-    if (!(value.IsPixelLengthUnit() || value.IsPercentLengthUnit())) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void
-DOMIntersectionObserver::GetRootMargin(mozilla::dom::DOMString& aRetVal)
-{
-  mRootMargin.AppendToString(eCSSProperty_DOM, aRetVal, nsCSSValue::eNormalized);
-}
-
-void
-DOMIntersectionObserver::GetThresholds(nsTArray<double>& aRetVal)
-{
-  aRetVal = mThresholds;
-}
-
-void
-DOMIntersectionObserver::Observe(Element& aTarget)
-{
-  if (mObservationTargets.Contains(&aTarget)) {
-    return;
-  }
-  aTarget.RegisterIntersectionObserver(this);
-  mObservationTargets.PutEntry(&aTarget);
-  Connect();
-}
-
-void
-DOMIntersectionObserver::Unobserve(Element& aTarget)
-{
-  if (!mObservationTargets.Contains(&aTarget)) {
-    return;
-  }
-  if (mObservationTargets.Count() == 1) {
-    Disconnect();
-    return;
-  }
-  aTarget.UnregisterIntersectionObserver(this);
-  mObservationTargets.RemoveEntry(&aTarget);
-}
-
-void
-DOMIntersectionObserver::Connect()
-{
-  if (mConnected) {
-    return;
-  }
-  nsIDocument* document = mOwner->GetExtantDoc();
-  document->AddIntersectionObserver(this);
-  mConnected = true;
-}
-
-void
-DOMIntersectionObserver::Disconnect()
-{
-  if (!mConnected) {
-    return;
-  }
-  for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) {
-    Element* target = iter.Get()->GetKey();
-    target->UnregisterIntersectionObserver(this);
-  }
-  mObservationTargets.Clear();
-  nsIDocument* document = mOwner->GetExtantDoc();
-  document->RemoveIntersectionObserver(this);
-  mConnected = false;
-}
-
-void
-DOMIntersectionObserver::TakeRecords(nsTArray<RefPtr<DOMIntersectionObserverEntry>>& aRetVal)
-{
-  aRetVal.SwapElements(mQueuedEntries);
-  mQueuedEntries.Clear();
-}
-
-static bool
-CheckSimilarOrigin(nsINode* aNode1, nsINode* aNode2)
-{
-  nsIPrincipal* principal1 = aNode1->NodePrincipal();
-  nsIPrincipal* principal2 = aNode2->NodePrincipal();
-  nsAutoCString baseDomain1;
-  nsAutoCString baseDomain2;
-
-  nsresult rv = principal1->GetBaseDomain(baseDomain1);
-  if (NS_FAILED(rv)) {
-    return principal1 == principal2;
-  }
-
-  rv = principal2->GetBaseDomain(baseDomain2);
-  if (NS_FAILED(rv)) {
-    return principal1 == principal2;
-  }
-
-  return baseDomain1 == baseDomain2;
-}
-
-static Maybe<nsRect>
-EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect)
-{
-  nscoord left = std::max(aRect.x, aOtherRect.x);
-  nscoord top = std::max(aRect.y, aOtherRect.y);
-  nscoord right = std::min(aRect.XMost(), aOtherRect.XMost());
-  nscoord bottom = std::min(aRect.YMost(), aOtherRect.YMost());
-  if (left > right || top > bottom) {
-    return Nothing();
-  }
-  return Some(nsRect(left, top, right - left, bottom - top));
-}
-
-void
-DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time)
-{
-  Element* root;
-  nsIFrame* rootFrame;
-  nsRect rootRect;
-
-  if (mRoot) {
-    root = mRoot;
-    rootFrame = root->GetPrimaryFrame();
-    if (rootFrame) {
-      if (rootFrame->GetType() == nsGkAtoms::scrollFrame) {
-        nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
-        rootRect = nsLayoutUtils::TransformFrameRectToAncestor(
-          rootFrame,
-          rootFrame->GetContentRectRelativeToSelf(),
-          scrollFrame->GetScrolledFrame());
-      } else {
-        rootRect = nsLayoutUtils::GetAllInFlowRectsUnion(rootFrame,
-          nsLayoutUtils::GetContainingBlockForClientRect(rootFrame),
-          nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
-      }
-    }
-  } else {
-    nsCOMPtr<nsIPresShell> presShell = aDocument->GetShell();
-    if (presShell) {
-      rootFrame = presShell->GetRootScrollFrame();
-      nsPresContext* presContext = rootFrame->PresContext();
-      while (!presContext->IsRootContentDocument()) {
-        presContext = rootFrame->PresContext()->GetParentPresContext();
-        rootFrame = presContext->PresShell()->GetRootScrollFrame();
-      }
-      root = rootFrame->GetContent()->AsElement();
-      nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
-      rootRect = scrollFrame->GetScrollPortRect();
-    }
-  }
-
-  nsMargin rootMargin;
-  NS_FOR_CSS_SIDES(side) {
-    nscoord basis = side == NS_SIDE_TOP || side == NS_SIDE_BOTTOM ?
-      rootRect.height : rootRect.width;
-    nsCSSValue value = mRootMargin.*nsCSSRect::sides[side];
-    nsStyleCoord coord;
-    if (value.IsPixelLengthUnit()) {
-      coord.SetCoordValue(value.GetPixelLength());
-    } else if (value.IsPercentLengthUnit()) {
-      coord.SetPercentValue(value.GetPercentValue());
-    } else {
-      MOZ_ASSERT_UNREACHABLE("invalid length unit");
-    }
-    rootMargin.Side(side) = nsLayoutUtils::ComputeCBDependentValue(basis, coord);
-  }
-
-  for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) {
-    Element* target = iter.Get()->GetKey();
-    nsIFrame* targetFrame = target->GetPrimaryFrame();
-    nsRect targetRect;
-    Maybe<nsRect> intersectionRect;
-
-    if (rootFrame && targetFrame) {
-      // If mRoot is set we are testing intersection with a container element
-      // instead of the implicit root.
-      if (mRoot) {
-        // Skip further processing of this target if it is not in the same
-        // Document as the intersection root, e.g. if root is an element of
-        // the main document and target an element from an embedded iframe.
-        if (target->GetComposedDoc() != root->GetComposedDoc()) {
-          continue;
-        }
-        // Skip further processing of this target if is not a descendant of the
-        // intersection root in the containing block chain. E.g. this would be
-        // the case if the target is in a position:absolute element whose
-        // containing block is an ancestor of root.
-        if (!nsLayoutUtils::IsAncestorFrameCrossDoc(rootFrame, targetFrame)) {
-          continue;
-        }
-      }
-
-      targetRect = nsLayoutUtils::GetAllInFlowRectsUnion(
-        targetFrame,
-        nsLayoutUtils::GetContainingBlockForClientRect(targetFrame),
-        nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS
-      );
-      intersectionRect = Some(targetFrame->GetVisualOverflowRect());
-
-      nsIFrame* containerFrame = nsLayoutUtils::GetCrossDocParentFrame(targetFrame);
-      while (containerFrame && containerFrame != rootFrame) {
-        if (containerFrame->GetType() == nsGkAtoms::scrollFrame) {
-          nsIScrollableFrame* scrollFrame = do_QueryFrame(containerFrame);
-          nsRect subFrameRect = scrollFrame->GetScrollPortRect();
-          nsRect intersectionRectRelativeToContainer =
-            nsLayoutUtils::TransformFrameRectToAncestor(targetFrame,
-                                                        intersectionRect.value(),
-                                                        containerFrame);
-          intersectionRect = EdgeInclusiveIntersection(intersectionRectRelativeToContainer,
-                                                       subFrameRect);
-          if (!intersectionRect) {
-            break;
-          }
-          targetFrame = containerFrame;
-        }
-
-        // TODO: Apply clip-path.
-
-        containerFrame = nsLayoutUtils::GetCrossDocParentFrame(containerFrame);
-      }
-    }
-
-    nsRect rootIntersectionRect = rootRect;
-    bool isInSimilarOriginBrowsingContext = CheckSimilarOrigin(root, target);
-
-    if (isInSimilarOriginBrowsingContext) {
-      rootIntersectionRect.Inflate(rootMargin);
-    }
-
-    if (intersectionRect.isSome()) {
-      nsRect intersectionRectRelativeToRoot =
-        nsLayoutUtils::TransformFrameRectToAncestor(
-          targetFrame,
-          intersectionRect.value(),
-          nsLayoutUtils::GetContainingBlockForClientRect(rootFrame)
-      );
-      intersectionRect = EdgeInclusiveIntersection(
-        intersectionRectRelativeToRoot,
-        rootIntersectionRect
-      );
-      if (intersectionRect.isSome()) {
-        intersectionRect = Some(nsLayoutUtils::TransformFrameRectToAncestor(
-          nsLayoutUtils::GetContainingBlockForClientRect(rootFrame),
-          intersectionRect.value(),
-          targetFrame->PresContext()->PresShell()->GetRootScrollFrame()
-        ));
-      }
-    }
-
-    double targetArea = targetRect.width * targetRect.height;
-    double intersectionArea = !intersectionRect ?
-      0 : intersectionRect->width * intersectionRect->height;
-    double intersectionRatio = targetArea > 0.0 ? intersectionArea / targetArea : 0.0;
-
-    size_t threshold = -1;
-    if (intersectionRatio > 0.0) {
-      if (intersectionRatio >= 1.0) {
-        intersectionRatio = 1.0;
-        threshold = mThresholds.Length();
-      } else {
-        for (size_t k = 0; k < mThresholds.Length(); ++k) {
-          if (mThresholds[k] <= intersectionRatio) {
-            threshold = k + 1;
-          } else {
-            break;
-          }
-        }
-      }
-    } else if (intersectionRect.isSome()) {
-      threshold = 0;
-    }
-
-    if (target->UpdateIntersectionObservation(this, threshold)) {
-      QueueIntersectionObserverEntry(
-        target, time,
-        isInSimilarOriginBrowsingContext ? Some(rootIntersectionRect) : Nothing(),
-        targetRect, intersectionRect
-      );
-    }
-  }
-}
-
-void
-DOMIntersectionObserver::QueueIntersectionObserverEntry(Element* aTarget,
-                                                        DOMHighResTimeStamp time,
-                                                        const Maybe<nsRect>& aRootRect,
-                                                        const nsRect& aTargetRect,
-                                                        const Maybe<nsRect>& aIntersectionRect)
-{
-  RefPtr<DOMRect> rootBounds;
-  if (aRootRect.isSome()) {
-    rootBounds = new DOMRect(this);
-    rootBounds->SetLayoutRect(aRootRect.value());
-  }
-  RefPtr<DOMRect> boundingClientRect = new DOMRect(this);
-  boundingClientRect->SetLayoutRect(aTargetRect);
-  RefPtr<DOMRect> intersectionRect = new DOMRect(this);
-  if (aIntersectionRect.isSome()) {
-    intersectionRect->SetLayoutRect(aIntersectionRect.value());
-  }
-  RefPtr<DOMIntersectionObserverEntry> entry = new DOMIntersectionObserverEntry(
-    this,
-    time,
-    rootBounds.forget(),
-    boundingClientRect.forget(),
-    intersectionRect.forget(),
-    aTarget);
-  mQueuedEntries.AppendElement(entry.forget());
-}
-
-void
-DOMIntersectionObserver::Notify()
-{
-  if (!mQueuedEntries.Length()) {
-    return;
-  }
-  mozilla::dom::Sequence<mozilla::OwningNonNull<DOMIntersectionObserverEntry>> entries;
-  if (entries.SetCapacity(mQueuedEntries.Length(), mozilla::fallible)) {
-    for (uint32_t i = 0; i < mQueuedEntries.Length(); ++i) {
-      RefPtr<DOMIntersectionObserverEntry> next = mQueuedEntries[i];
-      *entries.AppendElement(mozilla::fallible) = next;
-    }
-  }
-  mQueuedEntries.Clear();
-  mCallback->Call(this, entries, *this);
-}
-
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/base/DOMIntersectionObserver.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 DOMIntersectionObserver_h
-#define DOMIntersectionObserver_h
-
-#include "mozilla/dom/IntersectionObserverBinding.h"
-#include "nsCSSValue.h"
-#include "nsTArray.h"
-
-using mozilla::dom::DOMRect;
-using mozilla::dom::Element;
-
-namespace mozilla {
-namespace dom {
-
-class DOMIntersectionObserver;
-
-class DOMIntersectionObserverEntry final : public nsISupports,
-                                           public nsWrapperCache
-{
-  ~DOMIntersectionObserverEntry() {}
-
-public:
-  DOMIntersectionObserverEntry(nsISupports* aOwner,
-                               DOMHighResTimeStamp aTime,
-                               RefPtr<DOMRect> aRootBounds,
-                               RefPtr<DOMRect> aBoundingClientRect,
-                               RefPtr<DOMRect> aIntersectionRect,
-                               Element* aTarget)
-  : mOwner(aOwner),
-    mTime(aTime),
-    mRootBounds(aRootBounds),
-    mBoundingClientRect(aBoundingClientRect),
-    mIntersectionRect(aIntersectionRect),
-    mTarget(aTarget)
-  {
-  }
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMIntersectionObserverEntry)
-
-  nsISupports* GetParentObject() const
-  {
-    return mOwner;
-  }
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    return mozilla::dom::IntersectionObserverEntryBinding::Wrap(aCx, this, aGivenProto);
-  }
-
-  DOMHighResTimeStamp Time()
-  {
-    return mTime;
-  }
-
-  DOMRect* GetRootBounds()
-  {
-    return mRootBounds;
-  }
-
-  DOMRect* BoundingClientRect()
-  {
-    return mBoundingClientRect;
-  }
-
-  DOMRect* IntersectionRect()
-  {
-    return mIntersectionRect;
-  }
-
-  double IntersectionRatio();
-
-  Element* Target()
-  {
-    return mTarget;
-  }
-
-protected:
-  nsCOMPtr<nsISupports> mOwner;
-  DOMHighResTimeStamp   mTime;
-  RefPtr<DOMRect>       mRootBounds;
-  RefPtr<DOMRect>       mBoundingClientRect;
-  RefPtr<DOMRect>       mIntersectionRect;
-  RefPtr<Element>       mTarget;
-};
-
-#define NS_DOM_INTERSECTION_OBSERVER_IID \
-{ 0x8570a575, 0xe303, 0x4d18, \
-  { 0xb6, 0xb1, 0x4d, 0x2b, 0x49, 0xd8, 0xef, 0x94 } }
-
-class DOMIntersectionObserver final : public nsISupports,
-                                      public nsWrapperCache
-{
-  virtual ~DOMIntersectionObserver() { }
-
-public:
-  DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
-                          mozilla::dom::IntersectionCallback& aCb)
-  : mOwner(aOwner), mCallback(&aCb), mConnected(false)
-  {
-  }
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMIntersectionObserver)
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_INTERSECTION_OBSERVER_IID)
-
-  static already_AddRefed<DOMIntersectionObserver>
-  Constructor(const mozilla::dom::GlobalObject& aGlobal,
-              mozilla::dom::IntersectionCallback& aCb,
-              mozilla::ErrorResult& aRv);
-  static already_AddRefed<DOMIntersectionObserver>
-  Constructor(const mozilla::dom::GlobalObject& aGlobal,
-              mozilla::dom::IntersectionCallback& aCb,
-              const mozilla::dom::IntersectionObserverInit& aOptions,
-              mozilla::ErrorResult& aRv);
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    return mozilla::dom::IntersectionObserverBinding::Wrap(aCx, this, aGivenProto);
-  }
-
-  nsISupports* GetParentObject() const
-  {
-    return mOwner;
-  }
-
-  Element* GetRoot() const {
-    return mRoot;
-  }
-
-  void GetRootMargin(mozilla::dom::DOMString& aRetVal);
-  void GetThresholds(nsTArray<double>& aRetVal);
-  void Observe(Element& aTarget);
-  void Unobserve(Element& aTarget);
-
-  void Disconnect();
-  void TakeRecords(nsTArray<RefPtr<DOMIntersectionObserverEntry>>& aRetVal);
-
-  mozilla::dom::IntersectionCallback* IntersectionCallback() { return mCallback; }
-
-  bool SetRootMargin(const nsAString& aString);
-
-  void Update(nsIDocument* aDocument, DOMHighResTimeStamp time);
-  void Notify();
-
-protected:
-  void Connect();
-  void QueueIntersectionObserverEntry(Element* aTarget,
-                                      DOMHighResTimeStamp time,
-                                      const Maybe<nsRect>& aRootRect,
-                                      const nsRect& aTargetRect,
-                                      const Maybe<nsRect>& aIntersectionRect);
-
-  nsCOMPtr<nsPIDOMWindowInner>                    mOwner;
-  RefPtr<mozilla::dom::IntersectionCallback>      mCallback;
-  RefPtr<Element>                                 mRoot;
-  nsCSSRect                                       mRootMargin;
-  nsTArray<double>                                mThresholds;
-  nsTHashtable<nsPtrHashKey<Element>>             mObservationTargets;
-  nsTArray<RefPtr<DOMIntersectionObserverEntry>>  mQueuedEntries;
-  bool                                            mConnected;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(DOMIntersectionObserver, NS_DOM_INTERSECTION_OBSERVER_IID)
-
-} // namespace dom
-} // namespace mozilla
-
-#endif
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -144,17 +144,16 @@
 #include "mozilla/dom/KeyframeEffectBinding.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/dom/ElementBinding.h"
 #include "mozilla/dom/VRDisplay.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Preferences.h"
 #include "nsComputedDOMStyle.h"
 #include "nsDOMStringMap.h"
-#include "DOMIntersectionObserver.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsIAtom*
 nsIContent::DoGetID() const
 {
   MOZ_ASSERT(HasID(), "Unexpected call");
@@ -3882,49 +3881,8 @@ Element::ClearDataset()
 {
   nsDOMSlots *slots = GetExistingDOMSlots();
 
   MOZ_ASSERT(slots && slots->mDataset,
              "Slots should exist and dataset should not be null.");
   slots->mDataset = nullptr;
 }
 
-nsTArray<Element::nsDOMSlots::IntersectionObserverRegistration>*
-Element::RegisteredIntersectionObservers()
-{
-  nsDOMSlots* slots = DOMSlots();
-  return &slots->mRegisteredIntersectionObservers;
-}
-
-void
-Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  RegisteredIntersectionObservers()->AppendElement(
-    nsDOMSlots::IntersectionObserverRegistration { aObserver, -1 });
-}
-
-void
-Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
-    RegisteredIntersectionObservers();
-  for (uint32_t i = 0; i < observers->Length(); ++i) {
-    nsDOMSlots::IntersectionObserverRegistration reg = observers->ElementAt(i);
-    if (reg.observer == aObserver) {
-      observers->RemoveElementAt(i);
-      break;
-    }
-  }
-}
-
-bool
-Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
-{
-  nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
-    RegisteredIntersectionObservers();
-  for (auto& reg : *observers) {
-    if (reg.observer == aObserver && reg.previousThreshold != aThreshold) {
-      reg.previousThreshold = aThreshold;
-      return true;
-    }
-  }
-  return false;
-}
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -34,17 +34,16 @@
 #include "nsAttrValue.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/DOMTokenListSupportedTokens.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/dom/ElementBinding.h"
 #include "mozilla/dom/Nullable.h"
 #include "Units.h"
-#include "DOMIntersectionObserver.h"
 
 class nsIFrame;
 class nsIDOMMozNamedAttrMap;
 class nsIURI;
 class nsIScrollableFrame;
 class nsAttrValueOrString;
 class nsContentList;
 class nsDOMTokenList;
@@ -57,17 +56,16 @@ class nsDocument;
 class nsDOMStringMap;
 
 namespace mozilla {
 class DeclarationBlock;
 namespace dom {
   struct AnimationFilter;
   struct ScrollIntoViewOptions;
   struct ScrollToOptions;
-  class DOMIntersectionObserver;
   class ElementOrCSSPseudoElement;
   class UnrestrictedDoubleOrKeyframeAnimationOptions;
 } // namespace dom
 } // namespace mozilla
 
 
 already_AddRefed<nsContentList>
 NS_GetContentList(nsINode* aRootNode,
@@ -1146,20 +1144,16 @@ public:
    * sorts of elements expose it to JS as a .dataset property
    */
   // Getter, to be called from bindings.
   already_AddRefed<nsDOMStringMap> Dataset();
   // Callback for destructor of dataset to ensure to null out our weak pointer
   // to it.
   void ClearDataset();
 
-  void RegisterIntersectionObserver(DOMIntersectionObserver* aObserver);
-  void UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver);
-  bool UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t threshold);
-
 protected:
   /*
    * Named-bools for use with SetAttrAndNotify to make call sites easier to
    * read.
    */
   static const bool kFireMutationEvent           = true;
   static const bool kDontFireMutationEvent       = false;
   static const bool kNotifyDocumentObservers     = true;
@@ -1363,18 +1357,16 @@ protected:
    * the value of xlink:show, converted to a suitably equivalent named target
    * (e.g. _blank).
    */
   virtual void GetLinkTarget(nsAString& aTarget);
 
   nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
                                const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
 
-  nsTArray<nsDOMSlots::IntersectionObserverRegistration>* RegisteredIntersectionObservers();
-
 private:
   /**
    * Get this element's client area rect in app units.
    * @return the frame's client area
    */
   nsRect GetClientAreaRect();
 
   nsIScrollableFrame* GetScrollFrame(nsIFrame **aStyledFrame = nullptr,
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -32,17 +32,16 @@ class nsIDocument;
 class nsDOMStringMap;
 class nsIURI;
 
 namespace mozilla {
 namespace css {
 class Declaration;
 } // namespace css
 namespace dom {
-class DOMIntersectionObserver;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 /**
  * A class that implements nsIWeakReference
  */
 
@@ -340,26 +339,16 @@ public:
      * XBL binding installed on the lement.
      */
     nsCOMPtr<nsIContent> mXBLInsertionParent;
 
     /**
      * Web components custom element data.
      */
     RefPtr<CustomElementData> mCustomElementData;
-
-    /**
-     * Registered Intersection Observers on the element.
-     */
-    struct IntersectionObserverRegistration {
-      DOMIntersectionObserver* observer;
-      int32_t previousThreshold;
-    };
-
-    nsTArray<IntersectionObserverRegistration> mRegisteredIntersectionObservers;
   };
 
 protected:
   void GetMarkup(bool aIncludeSelf, nsAString& aMarkup);
   void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError);
 
   // Override from nsINode
   virtual nsINode::nsSlots* CreateSlots() override;
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -161,17 +161,16 @@ EXPORTS.mozilla.dom += [
     'DirectionalityUtils.h',
     'DocGroup.h',
     'DocumentFragment.h',
     'DocumentType.h',
     'DOMCursor.h',
     'DOMError.h',
     'DOMException.h',
     'DOMImplementation.h',
-    'DOMIntersectionObserver.h',
     'DOMMatrix.h',
     'DOMParser.h',
     'DOMPoint.h',
     'DOMQuad.h',
     'DOMRect.h',
     'DOMRequest.h',
     'DOMStringList.h',
     'DOMTokenListSupportedTokens.h',
@@ -356,18 +355,16 @@ UNIFIED_SOURCES += [
 
 if CONFIG['MOZ_WEBRTC']:
     UNIFIED_SOURCES += [
         'nsDOMDataChannel.cpp',
     ]
 
 # these files couldn't be in UNIFIED_SOURCES for now for reasons given below:
 SOURCES += [
-    # Several conflicts with other bindings.
-    'DOMIntersectionObserver.cpp',
     # Because of OS X headers.
     'nsContentUtils.cpp',
     # this file doesn't like windows.h
     'nsDOMWindowUtils.cpp',
     # Conflicts with windows.h's definition of SendMessage.
     'nsFrameMessageManager.cpp',
     # This file has a #error "Never include windows.h in this file!"
     'nsGlobalWindow.cpp',
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1452,18 +1452,16 @@ nsDocument::~nsDocument()
   mInDestructor = true;
   mInUnlinkOrDeletion = true;
 
   mozilla::DropJSObjects(this);
 
   // Clear mObservers to keep it in sync with the mutationobserver list
   mObservers.Clear();
 
-  mIntersectionObservers.Clear();
-
   if (mStyleSheetSetList) {
     mStyleSheetSetList->Disconnect();
   }
 
   if (mAnimationController) {
     mAnimationController->Disconnect();
   }
 
@@ -1723,18 +1721,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildrenCollection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnonymousContents)
 
   // Traverse all our nsCOMArrays.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnDemandBuiltInUASheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPreloadingImages)
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntersectionObservers)
-
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSubImportLinks)
 
   for (uint32_t i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameRequestCallbacks[i]");
     cb.NoteXPCOMChild(tmp->mFrameRequestCallbacks[i].mCallback);
   }
 
   // Traverse animation components
@@ -1811,18 +1807,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImportManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSubImportLinks)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet)
 
   tmp->mParentDocument = nullptr;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPreloadingImages)
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntersectionObservers)
-
   tmp->ClearAllBoxObjects();
 
   if (tmp->mListenerManager) {
     tmp->mListenerManager->Disconnect();
     tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER);
     tmp->mListenerManager = nullptr;
   }
 
@@ -12363,61 +12357,16 @@ nsDocument::ReportUseCounters()
 
           Telemetry::Accumulate(id, 1);
         }
       }
     }
   }
 }
 
-void
-nsDocument::AddIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  NS_ASSERTION(mIntersectionObservers.IndexOf(aObserver) == nsTArray<int>::NoIndex,
-               "Intersection observer already in the list");
-  mIntersectionObservers.AppendElement(aObserver);
-}
-
-void
-nsDocument::RemoveIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  mIntersectionObservers.RemoveElement(aObserver);
-}
-
-void
-nsDocument::UpdateIntersectionObservations()
-{
-  DOMHighResTimeStamp time = 0;
-  if (nsPIDOMWindowInner* window = GetInnerWindow()) {
-    Performance* perf = window->GetPerformance();
-    if (perf) {
-      time = perf->Now();
-    }
-  }
-  for (const auto& observer : mIntersectionObservers) {
-    observer->Update(this, time);
-  }
-}
-
-void
-nsDocument::ScheduleIntersectionObserverNotification()
-{
-  nsCOMPtr<nsIRunnable> notification = NewRunnableMethod(this,
-    &nsDocument::NotifyIntersectionObservers);
-  NS_DispatchToCurrentThread(notification);
-}
-
-void
-nsDocument::NotifyIntersectionObservers()
-{
-  for (const auto& observer : mIntersectionObservers) {
-    observer->Notify();
-  }
-}
-
 XPathEvaluator*
 nsIDocument::XPathEvaluator()
 {
   if (!mXPathEvaluator) {
     mXPathEvaluator = new dom::XPathEvaluator(this);
   }
   return mXPathEvaluator;
 }
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -64,17 +64,16 @@
 #include "nsDataHashtable.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Attributes.h"
 #include "nsIDOMXPathEvaluator.h"
 #include "jsfriendapi.h"
 #include "ImportManager.h"
 #include "mozilla/LinkedList.h"
 #include "CustomElementRegistry.h"
-#include "mozilla/dom/Performance.h"
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS   (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS      (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS    (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES       (1 << 3)
 
 
 class nsDOMStyleSheetSetList;
@@ -93,18 +92,16 @@ class nsPIBoxObject;
 
 namespace mozilla {
 class EventChainPreVisitor;
 namespace dom {
 class BoxObject;
 class ImageTracker;
 struct LifecycleCallbacks;
 class CallbackFunction;
-class DOMIntersectionObserver;
-class Performance;
 
 struct FullscreenRequest : public LinkedListElement<FullscreenRequest>
 {
   explicit FullscreenRequest(Element* aElement);
   FullscreenRequest(const FullscreenRequest&) = delete;
   ~FullscreenRequest();
 
   Element* GetElement() const { return mElement; }
@@ -771,25 +768,16 @@ public:
   // for radio group
   nsRadioGroupStruct* GetRadioGroup(const nsAString& aName) const;
   nsRadioGroupStruct* GetOrCreateRadioGroup(const nsAString& aName);
 
   virtual nsViewportInfo GetViewportInfo(const mozilla::ScreenIntSize& aDisplaySize) override;
 
   void ReportUseCounters();
 
-  virtual void AddIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) override;
-  virtual void RemoveIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) override;
-  virtual void UpdateIntersectionObservations() override;
-  virtual void ScheduleIntersectionObserverNotification() override;
-  virtual void NotifyIntersectionObservers() override;
-
-
 private:
   void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
   nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
   void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
 
 public:
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE
@@ -1332,19 +1320,16 @@ protected:
 
   nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheets;
   nsTArray<RefPtr<mozilla::StyleSheet>> mOnDemandBuiltInUASheets;
   nsTArray<RefPtr<mozilla::StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
 
   // Array of observers
   nsTObserverArray<nsIDocumentObserver*> mObservers;
 
-  // Array of intersection observers
-  nsTArray<RefPtr<mozilla::dom::DOMIntersectionObserver>> mIntersectionObservers;
-
   // Tracker for animations that are waiting to start.
   // nullptr until GetOrCreatePendingAnimationTracker is called.
   RefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker;
 
   // Weak reference to the scope object (aka the script global object)
   // that, unlike mScriptGlobalObject, is never unset once set. This
   // is a weak reference to avoid leaks due to circular references.
   nsWeakPtr mScopeObject;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -123,17 +123,16 @@ class BoxObject;
 class CDATASection;
 class Comment;
 struct CustomElementDefinition;
 class DocGroup;
 class DocumentFragment;
 class DocumentTimeline;
 class DocumentType;
 class DOMImplementation;
-class DOMIntersectionObserver;
 class DOMStringList;
 class Element;
 struct ElementCreationOptions;
 struct ElementRegistrationOptions;
 class Event;
 class EventTarget;
 class FontFaceSet;
 class FrameRequestCallback;
@@ -2841,25 +2840,16 @@ public:
   bool HasScriptsBlockedBySandbox();
 
   void ReportHasScrollLinkedEffect();
   bool HasScrollLinkedEffect() const
   {
     return mHasScrollLinkedEffect;
   }
 
-  virtual void AddIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
-  virtual void RemoveIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
-
-  virtual void UpdateIntersectionObservations() = 0;
-  virtual void ScheduleIntersectionObserverNotification() = 0;
-  virtual void NotifyIntersectionObservers() = 0;
-
   mozilla::dom::DocGroup* GetDocGroup();
 
 protected:
   bool GetUseCounter(mozilla::UseCounter aUseCounter)
   {
     return mUseCounters[aUseCounter];
   }
 
deleted file mode 100644
--- a/dom/base/test/intersectionobserver_iframe.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<style>
-#target5 {
-        position: absolute;
-        top: 0px;
-        left: 0px;
-        width: 20px;
-        height: 20px;
-        background: #f00;
-}
-</style>
-<body>
-<div id="target5"></div>
-<script>
-        var io = new IntersectionObserver(function (records) {
-                window.parent.postMessage(records[0].rootBounds == null, 'http://mochi.test:8888');
-        }, {});
-        io.observe(document.getElementById("target5"));
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/base/test/intersectionobserver_window.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<style>
-#target5 {
-        position: absolute;
-        top: 0px;
-        left: 0px;
-        width: 20px;
-        height: 20px;
-        background: #f00;
-}
-</style>
-<body>
-<div id="target"></div>
-<script>
-        var io = new IntersectionObserver(function(records) {
-          var viewportWidth =
-              document.documentElement.clientWidth || document.body.clientWidth;
-          var viewportHeight =
-              document.documentElement.clientHeight || document.body.clientHeight;
-          var passed = records.length === 1 &&
-                       records[0].rootBounds.top === 0 &&
-                       records[0].rootBounds.left === 0 &&
-                       records[0].rootBounds.right === viewportWidth &&
-                       records[0].rootBounds.width === viewportWidth &&
-                       records[0].rootBounds.bottom === viewportHeight &&
-                       records[0].rootBounds.height === viewportHeight;
-          window.opener.postMessage(passed, '*');
-        });
-        io.observe(document.getElementById("target"));
-</script>
-</body>
-</html>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -231,18 +231,16 @@ support-files =
   websocket_helpers.js
   websocket_tests.js
   !/dom/html/test/form_submit_server.sjs
   !/dom/security/test/cors/file_CrossSiteXHR_server.sjs
   !/image/test/mochitest/blue.png
   !/dom/xhr/tests/file_XHRSendData.sjs
   script_bug1238440.js
   file_blobURL_expiring.html
-  intersectionobserver_iframe.html
-  intersectionobserver_window.html
 
 [test_anchor_area_referrer.html]
 [test_anchor_area_referrer_changing.html]
 [test_anchor_area_referrer_invalid.html]
 [test_anchor_area_referrer_rel.html]
 [test_anonymousContent_api.html]
 [test_anonymousContent_append_after_reflow.html]
 [test_anonymousContent_canvas.html]
@@ -694,17 +692,16 @@ skip-if = e10s || os != 'linux' || build
 [test_htmlcopyencoder.xhtml]
 [test_iframe_referrer.html]
 [test_iframe_referrer_changing.html]
 [test_iframe_referrer_invalid.html]
 [test_Image_constructor.html]
 [test_img_referrer.html]
 [test_innersize_scrollport.html]
 [test_integer_attr_with_leading_zero.html]
-[test_intersectionobservers.html]
 [test_ipc_messagemanager_blob.html]
 [test_link_prefetch.html]
 skip-if = !e10s # Track Bug 1281415
 [test_link_stylesheet.html]
 [test_messagemanager_targetchain.html]
 [test_meta_viewport0.html]
 skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_meta_viewport1.html]
deleted file mode 100644
--- a/dom/base/test/test_intersectionobservers.html
+++ /dev/null
@@ -1,1214 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1243846
-
-Some tests ported from IntersectionObserver/polyfill/intersection-observer-test.html
-
-Original license header:
-
-Copyright 2016 Google Inc. All Rights Reserved.
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-    http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1243846</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body onload="next()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1243846">Mozilla Bug 1243846</a>
-<p id="display"></p>
-<pre id="test">
-<script type="application/javascript">
-
-  SpecialPowers.setIntPref("layout.visibility.min-notify-intersection-observers-interval-ms", 0);
-
-  var tests = [];
-  var curDescribeMsg = '';
-  var curItMsg = '';
-
-  function beforeEach_fn() { };
-  function afterEach_fn() { };
-
-  function before(fn) {
-    fn();
-  }
-
-  function beforeEach(fn) {
-    beforeEach_fn = fn;
-  }
-
-  function afterEach(fn) {
-    afterEach_fn = fn;
-  }
-
-  function it(msg, fn) {
-    tests.push({
-      msg: `${msg} [${curDescribeMsg}]`,
-      fn: fn
-    });
-  }
-
-  var callbacks = [];
-  function callDelayed(fn, delay) {
-    callbacks.push({
-      fn: fn,
-      time: +new Date() + delay
-    });
-  }
-
-  requestAnimationFrame(function tick() {
-    var i = callbacks.length;
-    while (i--) {
-      var cb = callbacks[i];
-      if (+new Date() >= cb.time) {
-        SimpleTest.executeSoon(cb.fn);
-        callbacks.splice(i, 1);
-      }
-    }
-    requestAnimationFrame(tick);
-  });
-
-  function expect(val) {
-    return {
-      to: {
-        throwException: function (regexp) {
-          try {
-            val();
-            ok(false, `${curItMsg} - an exception should have beeen thrown`);
-          } catch (e) {
-            ok(regexp.test(e), `${curItMsg} - supplied regexp should match thrown exception`);
-          }
-        },
-        get be() {
-          var fn = function (expected) {
-            is(val, expected, curItMsg);
-          };
-          fn.ok = function () {
-            ok(val, curItMsg);
-          };
-          fn.greaterThan = function (other) {
-            ok(val > other, `${curItMsg} - ${val} should be greater than ${other}`);
-          };
-          fn.lessThan = function (other) {
-            ok(val < other, `${curItMsg} - ${val} should be less than ${other}`);
-          };
-          return fn;
-        },
-        eql: function (expected) {
-          if (Array.isArray(expected)) {
-            if (!Array.isArray(val)) {
-              ok(false, curItMsg, `${curItMsg} - should be an array,`);
-              return;
-            }
-            is(val.length, expected.length, curItMsg, `${curItMsg} - arrays should be the same length`);
-            if (expected.length != val.length) {
-              return;
-            }
-            for (var i = 0; i < expected.length; i++) {
-              is(val[i], expected[i], `${curItMsg} - array elements at position ${i} should be equal`);
-              if (expected[i] != val[i]) {
-                return;
-              }
-            }
-            ok(true);
-          }
-        },
-      }
-    }
-  }
-
-  function describe(msg, fn) {
-    curDescribeMsg = msg;
-    fn();
-    curDescribeMsg = '';
-  }
-
-  function next() {
-    var test = tests.shift();
-    if (test) {
-      console.log(test.msg);
-      curItMsg = test.msg;
-      var fn = test.fn;
-      beforeEach_fn();
-      if (fn.length) {
-        fn(function () {
-          afterEach_fn();
-          next();
-        });
-      } else {
-        fn();
-        afterEach_fn();
-        next();
-      }
-    } else {
-      SimpleTest.finish();
-    }
-  }
-
-  var sinon = {
-    spy: function () {
-      var callbacks = [];
-      var fn = function () {
-        fn.callCount++;
-        fn.lastCall = { args: arguments };
-        if (callbacks.length) {
-          callbacks.shift()();
-        }
-      };
-      fn.callCount = 0;
-      fn.lastCall = { args: [] };
-      fn.waitForNotification = (fn) => {
-        callbacks.push(fn);
-      };
-      return fn;
-    }
-  };
-
-  var ASYNC_TIMEOUT = 300;
-
-
-  var io;
-  var noop = function() {};
-
-
-  // References to DOM elements, which are accessible to any test
-  // and reset prior to each test so state isn't shared.
-  var rootEl;
-  var grandParentEl;
-  var parentEl;
-  var targetEl1;
-  var targetEl2;
-  var targetEl3;
-  var targetEl4;
-  var targetEl5;
-
-
-  describe('IntersectionObserver', function() {
-
-    before(function() {
-
-    });
-
-
-    beforeEach(function() {
-      addStyles();
-      addFixtures();
-    });
-
-
-    afterEach(function() {
-      if (io && 'disconnect' in io) io.disconnect();
-      io = null;
-
-      window.onmessage = null;
-
-      removeStyles();
-      removeFixtures();
-    });
-
-
-    describe('constructor', function() {
-
-      it('throws when callback is not a function', function() {
-        expect(function() {
-          io = new IntersectionObserver(null);
-        }).to.throwException(/.*/i);
-      });
-
-
-      it('instantiates root correctly', function() {
-        io = new IntersectionObserver(noop);
-        expect(io.root).to.be(null);
-
-        io = new IntersectionObserver(noop, {root: rootEl});
-        expect(io.root).to.be(rootEl);
-      });
-
-
-      it('throws when root is not an Element', function() {
-        expect(function() {
-          io = new IntersectionObserver(noop, {root: 'foo'});
-        }).to.throwException(/.*/i);
-      });
-
-
-      it('instantiates rootMargin correctly', function() {
-        io = new IntersectionObserver(noop, {rootMargin: '10px'});
-        expect(io.rootMargin).to.be('10px 10px 10px 10px');
-
-        io = new IntersectionObserver(noop, {rootMargin: '10px -5%'});
-        expect(io.rootMargin).to.be('10px -5% 10px -5%');
-
-        io = new IntersectionObserver(noop, {rootMargin: '10px 20% 0px'});
-        expect(io.rootMargin).to.be('10px 20% 0px 20%');
-
-        io = new IntersectionObserver(noop, {rootMargin: '0px 0px -5% 5px'});
-        expect(io.rootMargin).to.be('0px 0px -5% 5px');
-      });
-
-
-      it('throws when rootMargin is not in pixels or percent', function() {
-        expect(function() {
-          io = new IntersectionObserver(noop, {rootMargin: 'auto'});
-        }).to.throwException(/pixels.*percent/i);
-      });
-
-
-      it('instantiates thresholds correctly', function() {
-        io = new IntersectionObserver(noop);
-        expect(io.thresholds).to.eql([0]);
-
-        io = new IntersectionObserver(noop, {threshold: 0.5});
-        expect(io.thresholds).to.eql([0.5]);
-
-        io = new IntersectionObserver(noop, {threshold: [0.25, 0.5, 0.75]});
-        expect(io.thresholds).to.eql([0.25, 0.5, 0.75]);
-
-        io = new IntersectionObserver(noop, {threshold: [1, .5, 0]});
-        expect(io.thresholds).to.eql([0, .5, 1]);
-      });
-
-      it('throws when a threshold value is not between 0 and 1', function() {
-        expect(function() {
-          io = new IntersectionObserver(noop, {threshold: [0, -1]});
-        }).to.throwException(/threshold/i);
-      });
-
-      it('throws when a threshold value is not a number', function() {
-        expect(function() {
-          io = new IntersectionObserver(noop, {threshold: "foo"});
-        }).to.throwException(/.*/i);
-      });
-
-    });
-
-
-    describe('observe', function() {
-
-      it('throws when target is not an Element', function() {
-        expect(function() {
-          io = new IntersectionObserver(noop);
-          io.observe(null);
-        }).to.throwException(/.*/i);
-      });
-
-
-      it('triggers if target intersects when observing begins', function(done) {
-        io = new IntersectionObserver(function(records) {
-          expect(records.length).to.be(1);
-          expect(records[0].intersectionRatio).to.be(1);
-          done();
-        }, {root: rootEl});
-        io.observe(targetEl1);
-      });
-
-
-      it('triggers with the correct arguments', function(done) {
-        io = new IntersectionObserver(function(records, observer) {
-          expect(records.length).to.be(1);
-          expect(records[0] instanceof IntersectionObserverEntry).to.be.ok();
-          expect(observer).to.be(io);
-          expect(this).to.be(io);
-          done();
-        }, {root: rootEl});
-        io.observe(targetEl1);
-      });
-
-
-      it('does not trigger if target does not intersect when observing begins',
-          function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        targetEl2.style.top = '-40px';
-        io.observe(targetEl2);
-        callDelayed(function() {
-          expect(spy.callCount).to.be(0);
-          done();
-        }, ASYNC_TIMEOUT);
-      });
-
-
-      it('does not trigger if target is not a descendant of the intersection root in the containing block chain',
-          function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: parentEl});
-
-        parentEl.style.position = 'static';
-        io.observe(targetEl2);
-        callDelayed(function() {
-          expect(spy.callCount).to.be(0);
-          done();
-        }, ASYNC_TIMEOUT);
-      });
-
-      it('triggers if target or root becomes invisible',
-          function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        runSequence([
-          function(done) {
-            io.observe(targetEl1);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.display = 'none';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(2);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.display = 'block';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(3);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            rootEl.style.display = 'none';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(4);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            rootEl.style.display = 'block';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(5);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-        ], done);
-      });
-
-
-      it('handles container elements with non-visible overflow',
-          function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        runSequence([
-          function(done) {
-            io.observe(targetEl1);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.left = '-40px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(2);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            parentEl.style.overflow = 'visible';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(3);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          }
-        ], done);
-      });
-
-
-      it('observes one target at a single threshold correctly', function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl, threshold: 0.5});
-
-        runSequence([
-          function(done) {
-            targetEl1.style.left = '-5px';
-            io.observe(targetEl1);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be.greaterThan(0.5);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.left = '-15px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(2);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be.lessThan(0.5);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.left = '-25px';
-            callDelayed(function() {
-              expect(spy.callCount).to.be(2);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.left = '-10px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(3);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0.5);
-              done();
-            }, ASYNC_TIMEOUT);
-          }
-        ], done);
-
-      });
-
-
-      it('observes multiple targets at multiple thresholds correctly',
-          function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {
-          root: rootEl,
-          threshold: [1, 0.5, 0]
-        });
-
-        runSequence([
-          function(done) {
-            targetEl1.style.top = '0px';
-            targetEl1.style.left = '-15px';
-            targetEl2.style.top = '-5px';
-            targetEl2.style.left = '0px';
-            targetEl3.style.top = '0px';
-            targetEl3.style.left = '205px';
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            io.observe(targetEl3);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(2);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(0.25);
-              expect(records[1].target).to.be(targetEl2);
-              expect(records[1].intersectionRatio).to.be(0.75);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.top = '0px';
-            targetEl1.style.left = '-5px';
-            targetEl2.style.top = '-15px';
-            targetEl2.style.left = '0px';
-            targetEl3.style.top = '0px';
-            targetEl3.style.left = '195px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(2);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(3);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(0.75);
-              expect(records[1].target).to.be(targetEl2);
-              expect(records[1].intersectionRatio).to.be(0.25);
-              expect(records[2].target).to.be(targetEl3);
-              expect(records[2].intersectionRatio).to.be(0.25);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.top = '0px';
-            targetEl1.style.left = '5px';
-            targetEl2.style.top = '-25px';
-            targetEl2.style.left = '0px';
-            targetEl3.style.top = '0px';
-            targetEl3.style.left = '185px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(3);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(3);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(1);
-              expect(records[1].target).to.be(targetEl2);
-              expect(records[1].intersectionRatio).to.be(0);
-              expect(records[2].target).to.be(targetEl3);
-              expect(records[2].intersectionRatio).to.be(0.75);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.top = '0px';
-            targetEl1.style.left = '15px';
-            targetEl2.style.top = '-35px';
-            targetEl2.style.left = '0px';
-            targetEl3.style.top = '0px';
-            targetEl3.style.left = '175px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(4);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].target).to.be(targetEl3);
-              expect(records[0].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          }
-        ], done);
-      });
-
-
-      it('handles rootMargin properly', function(done) {
-
-        parentEl.style.overflow = 'visible';
-        targetEl1.style.top = '0px';
-        targetEl1.style.left = '-20px';
-        targetEl2.style.top = '-20px';
-        targetEl2.style.left = '0px';
-        targetEl3.style.top = '0px';
-        targetEl3.style.left = '200px';
-        targetEl4.style.top = '180px';
-        targetEl4.style.left = '180px';
-
-        runSequence([
-          function(done) {
-            io = new IntersectionObserver(function(records) {
-              records = sortRecords(records);
-              expect(records.length).to.be(4);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(1);
-              expect(records[1].target).to.be(targetEl2);
-              expect(records[1].intersectionRatio).to.be(.5);
-              expect(records[2].target).to.be(targetEl3);
-              expect(records[2].intersectionRatio).to.be(.5);
-              expect(records[3].target).to.be(targetEl4);
-              expect(records[3].intersectionRatio).to.be(1);
-              io.disconnect();
-              done();
-            }, {root: rootEl, rootMargin: '10px'});
-
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            io.observe(targetEl3);
-            io.observe(targetEl4);
-          },
-          function(done) {
-            io = new IntersectionObserver(function(records) {
-              records = sortRecords(records);
-              expect(records.length).to.be(3);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(0.5);
-              expect(records[1].target).to.be(targetEl3);
-              expect(records[1].intersectionRatio).to.be(0.5);
-              expect(records[2].target).to.be(targetEl4);
-              expect(records[2].intersectionRatio).to.be(0.5);
-              io.disconnect();
-              done();
-            }, {root: rootEl, rootMargin: '-10px 10%'});
-
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            io.observe(targetEl3);
-            io.observe(targetEl4);
-          },
-          function(done) {
-            io = new IntersectionObserver(function(records) {
-              records = sortRecords(records);
-              expect(records.length).to.be(2);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(0.5);
-              expect(records[1].target).to.be(targetEl4);
-              expect(records[1].intersectionRatio).to.be(0.5);
-              io.disconnect();
-              done();
-            }, {root: rootEl, rootMargin: '-5% -2.5% 0px'});
-
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            io.observe(targetEl3);
-            io.observe(targetEl4);
-          },
-          function(done) {
-            io = new IntersectionObserver(function(records) {
-              records = sortRecords(records);
-              expect(records.length).to.be(3);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(0.5);
-              expect(records[1].target).to.be(targetEl2);
-              expect(records[1].intersectionRatio).to.be(0.5);
-              expect(records[2].target).to.be(targetEl4);
-              expect(records[2].intersectionRatio).to.be(0.25);
-              io.disconnect();
-              done();
-            }, {root: rootEl, rootMargin: '5% -2.5% -10px -190px'});
-
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            io.observe(targetEl3);
-            io.observe(targetEl4);
-          }
-        ], done);
-      });
-
-
-      it('handles targets on the boundary of root', function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        runSequence([
-          function(done) {
-            targetEl1.style.top = '0px';
-            targetEl1.style.left = '-21px';
-            targetEl2.style.top = '-20px';
-            targetEl2.style.left = '0px';
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0);
-              expect(records[0].target).to.be(targetEl2);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.top = '0px';
-            targetEl1.style.left = '-20px';
-            targetEl2.style.top = '-21px';
-            targetEl2.style.left = '0px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(2);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(2);
-              expect(records[0].intersectionRatio).to.be(0);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[1].intersectionRatio).to.be(0);
-              expect(records[1].target).to.be(targetEl2);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl1.style.top = '-20px';
-            targetEl1.style.left = '200px';
-            targetEl2.style.top = '200px';
-            targetEl2.style.left = '200px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(3);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0);
-              expect(records[0].target).to.be(targetEl2);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            targetEl3.style.top = '20px';
-            targetEl3.style.left = '-20px';
-            targetEl4.style.top = '-20px';
-            targetEl4.style.left = '20px';
-            io.observe(targetEl3);
-            io.observe(targetEl4);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(4);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(2);
-              expect(records[0].intersectionRatio).to.be(0);
-              expect(records[0].target).to.be(targetEl3);
-              expect(records[1].intersectionRatio).to.be(0);
-              expect(records[1].target).to.be(targetEl4);
-              done();
-            }, ASYNC_TIMEOUT);
-          }
-        ], done);
-
-      });
-
-
-      it('handles zero-size targets within the root coordinate space',
-          function(done) {
-
-        io = new IntersectionObserver(function(records) {
-          expect(records.length).to.be(1);
-          expect(records[0].intersectionRatio).to.be(0);
-          done();
-        }, {root: rootEl});
-
-        targetEl1.style.top = '0px';
-        targetEl1.style.left = '0px';
-        targetEl1.style.width = '0px';
-        targetEl1.style.height = '0px';
-        io.observe(targetEl1);
-      });
-
-
-      it('handles root/target elements not yet in the DOM', function(done) {
-
-        rootEl.parentNode.removeChild(rootEl);
-        targetEl1.parentNode.removeChild(targetEl1);
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        runSequence([
-          function(done) {
-            io.observe(targetEl1);
-            callDelayed(done, 0);
-          },
-          function(done) {
-            document.getElementById('fixtures').appendChild(rootEl);
-            callDelayed(function() {
-              expect(spy.callCount).to.be(0);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            parentEl.insertBefore(targetEl1, targetEl2);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(1);
-              expect(records[0].target).to.be(targetEl1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            grandParentEl.parentNode.removeChild(grandParentEl);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(2);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0);
-              expect(records[0].target).to.be(targetEl1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            rootEl.appendChild(targetEl1);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(3);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(1);
-              expect(records[0].target).to.be(targetEl1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            rootEl.parentNode.removeChild(rootEl);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(4);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].intersectionRatio).to.be(0);
-              expect(records[0].target).to.be(targetEl1);
-              done();
-            }, ASYNC_TIMEOUT);
-          }
-        ], done);
-      });
-
-
-      it('handles sub-root element scrolling', function(done) {
-        io = new IntersectionObserver(function(records) {
-          expect(records.length).to.be(1);
-          expect(records[0].intersectionRatio).to.be(1);
-          done();
-        }, {root: rootEl});
-
-        io.observe(targetEl3);
-        callDelayed(function() {
-          parentEl.scrollLeft = 40;
-        }, 0);
-      });
-
-
-      it('supports CSS transitions and transforms', function(done) {
-
-        targetEl1.style.top = '220px';
-        targetEl1.style.left = '220px';
-
-        io = new IntersectionObserver(function(records) {
-          expect(records.length).to.be(1);
-          expect(records[0].intersectionRatio).to.be(1);
-          done();
-        }, {root: rootEl, threshold: [1]});
-
-        io.observe(targetEl1);
-        callDelayed(function() {
-          targetEl1.style.transform = 'translateX(-40px) translateY(-40px)';
-        }, 0);
-      });
-
-
-      it('uses the viewport when no root is specified', function(done) {
-        window.onmessage = function (e) {
-          expect(e.data).to.be.ok();
-          win.close();
-          done();
-        };
-
-        var win = window.open("intersectionobserver_window.html");
-      });
-
-    });
-
-    describe('observe subframe', function () {
-      
-      it('should not trigger if target and root are not in the same document',
-          function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        targetEl4.onload = function () {
-          targetEl5 = targetEl4.contentDocument.getElementById('target5');
-          io.observe(targetEl5);
-          callDelayed(function() {
-            expect(spy.callCount).to.be(0);
-            done();
-          }, ASYNC_TIMEOUT);
-        }
-
-        targetEl4.src = "intersectionobserver_iframe.html";
-      
-      });
-
-      it('boundingClientRect matches target.getBoundingClientRect() for an element inside an iframe',
-          function(done) {
-
-        io = new IntersectionObserver(function(records) {
-          expect(records.length).to.be(1);
-          expect(records[0].boundingClientRect.top, targetEl5.getBoundingClientRect().top);
-          expect(records[0].boundingClientRect.left, targetEl5.getBoundingClientRect().left);
-          expect(records[0].boundingClientRect.width, targetEl5.getBoundingClientRect().width);
-          expect(records[0].boundingClientRect.height, targetEl5.getBoundingClientRect().height);
-          done();
-        }, {threshold: [1]});
-
-        targetEl4.onload = function () {
-          targetEl5 = targetEl4.contentDocument.getElementById('target5');
-          io.observe(targetEl5);
-        }
-
-        targetEl4.src = "intersectionobserver_iframe.html";
-      });
-
-      it('rootBounds should is set to null for cross-origin observations', function(done) {
-
-        window.onmessage = function (e) {
-          expect(e.data).to.be.ok();
-          done();
-        };
-
-        targetEl4.src = "http://example.org/tests/dom/base/test/intersectionobserver_iframe.html";
-
-      });
-    
-    });
-
-    describe('takeRecords', function() {
-
-      it('supports getting records before the callback is invoked',
-          function(done) {
-
-        var lastestRecords = [];
-        io = new IntersectionObserver(function(records) {
-          lastestRecords = lastestRecords.concat(records);
-        }, {root: rootEl});
-        io.observe(targetEl1);
-
-        window.requestAnimationFrame && requestAnimationFrame(function() {
-          lastestRecords = lastestRecords.concat(io.takeRecords());
-        });
-
-        callDelayed(function() {
-          expect(lastestRecords.length).to.be(1);
-          expect(lastestRecords[0].intersectionRatio).to.be(1);
-          done();
-        }, ASYNC_TIMEOUT);
-      });
-
-    });
-
-
-    describe('unobserve', function() {
-
-      it('removes targets from the internal store', function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        runSequence([
-          function(done) {
-            targetEl1.style.top = targetEl2.style.top = '0px';
-            targetEl1.style.left = targetEl2.style.left = '0px';
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(2);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(1);
-              expect(records[1].target).to.be(targetEl2);
-              expect(records[1].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            io.unobserve(targetEl1);
-            targetEl1.style.top = targetEl2.style.top = '0px';
-            targetEl1.style.left = targetEl2.style.left = '-40px';
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(2);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(1);
-              expect(records[0].target).to.be(targetEl2);
-              expect(records[0].intersectionRatio).to.be(0);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            io.unobserve(targetEl2);
-            targetEl1.style.top = targetEl2.style.top = '0px';
-            targetEl1.style.left = targetEl2.style.left = '0px';
-            callDelayed(function() {
-              expect(spy.callCount).to.be(2);
-              done();
-            }, ASYNC_TIMEOUT);
-          }
-        ], done);
-
-      });
-
-    });
-
-    describe('disconnect', function() {
-
-      it('removes all targets and stops listening for changes', function(done) {
-
-        var spy = sinon.spy();
-        io = new IntersectionObserver(spy, {root: rootEl});
-
-        runSequence([
-          function(done) {
-            targetEl1.style.top = targetEl2.style.top = '0px';
-            targetEl1.style.left = targetEl2.style.left = '0px';
-            io.observe(targetEl1);
-            io.observe(targetEl2);
-            spy.waitForNotification(function() {
-              expect(spy.callCount).to.be(1);
-              var records = sortRecords(spy.lastCall.args[0]);
-              expect(records.length).to.be(2);
-              expect(records[0].target).to.be(targetEl1);
-              expect(records[0].intersectionRatio).to.be(1);
-              expect(records[1].target).to.be(targetEl2);
-              expect(records[1].intersectionRatio).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          },
-          function(done) {
-            io.disconnect();
-            targetEl1.style.top = targetEl2.style.top = '0px';
-            targetEl1.style.left = targetEl2.style.left = '-40px';
-            callDelayed(function() {
-              expect(spy.callCount).to.be(1);
-              done();
-            }, ASYNC_TIMEOUT);
-          }
-        ], done);
-
-      });
-
-    });
-
-  });
-
-
-  /**
-   * Runs a sequence of function and when finished invokes the done callback.
-   * Each function in the sequence is invoked with its own done function and
-   * it should call that function once it's complete.
-   * @param {Array<Function>} functions An array of async functions.
-   * @param {Function} done A final callback to be invoked once all function
-   *     have run.
-   */
-  function runSequence(functions, done) {
-    var next = functions.shift();
-    if (next) {
-      next(function() {
-        runSequence(functions, done);
-      });
-    } else {
-      done && done();
-    }
-  }
-
-
-  /**
-   * Sorts an array of records alphebetically by ascending ID. Since the current
-   * native implementation doesn't sort change entries by `observe` order, we do
-   * that ourselves for the non-polyfill case. Since all tests call observe
-   * on targets in sequential order, this should always match.
-   * https://crbug.com/613679
-   * @param {Array<IntersectionObserverEntry>} entries The entries to sort.
-   * @return {Array<IntersectionObserverEntry>} The sorted array.
-   */
-  function sortRecords(entries) {
-    entries = entries.sort(function(a, b) {
-      return a.target.id < b.target.id ? -1 : 1;
-    });
-    return entries;
-  }
-
-
-  /**
-   * Adds the common styles used by all tests to the page.
-   */
-  function addStyles() {
-    var styles = document.createElement('style');
-    styles.id = 'styles';
-    document.documentElement.appendChild(styles);
-
-    var cssText =
-        '#root {' +
-        '  position: relative;' +
-        '  width: 400px;' +
-        '  height: 200px;' +
-        '  background: #eee' +
-        '}' +
-        '#grand-parent {' +
-        '  position: relative;' +
-        '  width: 200px;' +
-        '  height: 200px;' +
-        '}' +
-        '#parent {' +
-        '  position: absolute;' +
-        '  top: 0px;' +
-        '  left: 200px;' +
-        '  overflow: hidden;' +
-        '  width: 200px;' +
-        '  height: 200px;' +
-        '  background: #ddd;' +
-        '}' +
-        '#target1, #target2, #target3, #target4 {' +
-        '  position: absolute;' +
-        '  top: 0px;' +
-        '  left: 0px;' +
-        '  width: 20px;' +
-        '  height: 20px;' +
-        '  transform: translateX(0px) translateY(0px);' +
-        '  transition: transform .5s;' +
-        '  background: #f00;' +
-        '  border: none;' +
-        '}';
-
-    styles.innerHTML = cssText;
-  }
-
-
-  /**
-   * Adds the DOM fixtures used by all tests to the page and assigns them to
-   * global variables so they can be referenced within the tests.
-   */
-  function addFixtures() {
-    var fixtures = document.createElement('div');
-    fixtures.id = 'fixtures';
-
-    fixtures.innerHTML =
-        '<div id="root">' +
-        '  <div id="grand-parent">' +
-        '    <div id="parent">' +
-        '      <div id="target1"></div>' +
-        '      <div id="target2"></div>' +
-        '      <div id="target3"></div>' +
-        '      <iframe id="target4"></iframe>' +
-        '    </div>' +
-        '  </div>' +
-        '</div>';
-
-    document.body.appendChild(fixtures);
-
-    rootEl = document.getElementById('root');
-    grandParentEl = document.getElementById('grand-parent');
-    parentEl = document.getElementById('parent');
-    targetEl1 = document.getElementById('target1');
-    targetEl2 = document.getElementById('target2');
-    targetEl3 = document.getElementById('target3');
-    targetEl4 = document.getElementById('target4');
-  }
-
-
-  /**
-   * Removes the common styles from the page.
-   */
-  function removeStyles() {
-    var styles = document.getElementById('styles');
-    styles.parentNode.removeChild(styles);
-  }
-
-
-  /**
-   * Removes the DOM fixtures from the page and resets the global references.
-   */
-  function removeFixtures() {
-    var fixtures = document.getElementById('fixtures');
-    fixtures.parentNode.removeChild(fixtures);
-
-    rootEl = null;
-    grandParentEl = null;
-    parentEl = null;
-    targetEl1 = null;
-    targetEl2 = null;
-    targetEl3 = null;
-    targetEl4 = null;
-  }
-
-  SimpleTest.waitForExplicitFinish();
-</script>
-</pre>
-<div id="log">
-</div>
-</body>
-</html>
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -576,25 +576,16 @@ DOMInterfaces = {
     'wrapperCache': False,
 },
 
 'InputStream': {
     'nativeType': 'nsIInputStream',
     'notflattened': True
 },
 
-'IntersectionObserver': {
-    'nativeType': 'mozilla::dom::DOMIntersectionObserver',
-},
-
-'IntersectionObserverEntry': {
-    'nativeType': 'mozilla::dom::DOMIntersectionObserverEntry',
-    'headerFile': 'DOMIntersectionObserver.h',
-},
-
 'KeyEvent': {
     'concrete': False
 },
 
 'KeyframeEffect': {
     'implicitJSContext': { 'setterOnly': [ 'spacing' ] }
 },
 
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -98,9 +98,8 @@ MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 
 MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
 MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
 MSG_DEF(MSG_INVALID_SPACING_MODE_ERROR, 1, JSEXN_TYPEERR, "Invalid spacing '{0}'.")
 MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)")
 MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
 MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")
 MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the supported range for time values.")
 MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
-MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -606,20 +606,16 @@ var interfaceNamesInGlobalScope =
     {name: "ImageCaptureErrorEvent", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ImageData",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "InputEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "InstallTrigger",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IntersectionObserver",
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    "IntersectionObserverEntry",
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "KeyEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "KeyboardEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "KeyframeEffectReadOnly", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "KeyframeEffect", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/DOMRect.webidl
+++ b/dom/webidl/DOMRect.webidl
@@ -24,16 +24,9 @@ interface DOMRectReadOnly {
     readonly attribute unrestricted double x;
     readonly attribute unrestricted double y;
     readonly attribute unrestricted double width;
     readonly attribute unrestricted double height;
     readonly attribute unrestricted double top;
     readonly attribute unrestricted double right;
     readonly attribute unrestricted double bottom;
     readonly attribute unrestricted double left;
-};
-
-dictionary DOMRectInit {
-    unrestricted double x = 0;
-    unrestricted double y = 0;
-    unrestricted double width = 0;
-    unrestricted double height = 0;
-};
+};
\ No newline at end of file
deleted file mode 100644
--- a/dom/webidl/IntersectionObserver.webidl
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; 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/.
- *
- * The origin of this IDL file is
- * https://wicg.github.io/IntersectionObserver/
- */
-
-[ProbablyShortLivingObject]
-interface IntersectionObserverEntry {
-  [Constant]
-  readonly attribute DOMHighResTimeStamp time;
-  [Constant]
-  readonly attribute DOMRectReadOnly? rootBounds;
-  [Constant]
-  readonly attribute DOMRectReadOnly boundingClientRect;
-  [Constant]
-  readonly attribute DOMRectReadOnly intersectionRect;
-  [Constant]
-  readonly attribute double intersectionRatio;
-  [Constant]
-  readonly attribute Element target;
-};
-
-[Constructor(IntersectionCallback intersectionCallback,
-             optional IntersectionObserverInit options)]
-interface IntersectionObserver {
-  [Constant]
-  readonly attribute Element? root;
-  [Constant]
-  readonly attribute DOMString rootMargin;
-  [Constant,Cached]
-  readonly attribute sequence<double> thresholds;
-  void observe(Element target);
-  void unobserve(Element target);
-  void disconnect();
-  sequence<IntersectionObserverEntry> takeRecords();
-
-  [ChromeOnly]
-  readonly attribute IntersectionCallback intersectionCallback;
-};
-
-callback IntersectionCallback =
-  void (sequence<IntersectionObserverEntry> entries, IntersectionObserver observer);
-
-dictionary IntersectionObserverEntryInit {
-  required DOMHighResTimeStamp time;
-  required DOMRectInit rootBounds;
-  required DOMRectInit boundingClientRect;
-  required DOMRectInit intersectionRect;
-  required Element target;
-};
-
-dictionary IntersectionObserverInit {
-  Element?  root = null;
-  DOMString rootMargin = "0px";
-  (double or sequence<double>) threshold = 0;
-};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -275,17 +275,16 @@ WEBIDL_FILES = [
     'ImageCapture.webidl',
     'ImageData.webidl',
     'ImageDocument.webidl',
     'InputEvent.webidl',
     'InputMethod.webidl',
     'InputPort.webidl',
     'InputPortManager.webidl',
     'InspectorUtils.webidl',
-    'IntersectionObserver.webidl',
     'IterableIterator.webidl',
     'KeyAlgorithm.webidl',
     'KeyboardEvent.webidl',
     'KeyEvent.webidl',
     'KeyframeAnimationOptions.webidl',
     'KeyframeEffect.webidl',
     'KeyIdsInitData.webidl',
     'LegacyQueryInterface.webidl',
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -75,17 +75,16 @@ using namespace mozilla::widget;
 using namespace mozilla::ipc;
 using namespace mozilla::layout;
 
 static mozilla::LazyLogModule sRefreshDriverLog("nsRefreshDriver");
 #define LOG(...) MOZ_LOG(sRefreshDriverLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
 
 #define DEFAULT_THROTTLED_FRAME_RATE 1
 #define DEFAULT_RECOMPUTE_VISIBILITY_INTERVAL_MS 1000
-#define DEFAULT_NOTIFY_INTERSECTION_OBSERVERS_INTERVAL_MS 100
 // after 10 minutes, stop firing off inactive timers
 #define DEFAULT_INACTIVE_TIMER_DISABLE_SECONDS 600
 
 // The number of seconds spent skipping frames because we are waiting for the compositor
 // before logging.
 #if defined(MOZ_ASAN)
 # define REFRESH_WAIT_WARNING 5
 #elif defined(DEBUG) && !defined(MOZ_VALGRIND)
@@ -972,27 +971,16 @@ nsRefreshDriver::GetMinRecomputeVisibili
   int32_t interval =
     Preferences::GetInt("layout.visibility.min-recompute-interval-ms", -1);
   if (interval <= 0) {
     interval = DEFAULT_RECOMPUTE_VISIBILITY_INTERVAL_MS;
   }
   return TimeDuration::FromMilliseconds(interval);
 }
 
-/* static */ mozilla::TimeDuration
-nsRefreshDriver::GetMinNotifyIntersectionObserversInterval()
-{
-  int32_t interval =
-    Preferences::GetInt("layout.visibility.min-notify-intersection-observers-interval-ms", -1);
-  if (interval <= 0) {
-    interval = DEFAULT_NOTIFY_INTERSECTION_OBSERVERS_INTERVAL_MS;
-  }
-  return TimeDuration::FromMilliseconds(interval);
-}
-
 double
 nsRefreshDriver::GetRefreshTimerInterval() const
 {
   return mThrottled ? GetThrottledTimerInterval() : GetRegularTimerInterval();
 }
 
 RefreshDriverTimer*
 nsRefreshDriver::ChooseTimer() const
@@ -1025,18 +1013,16 @@ nsRefreshDriver::nsRefreshDriver(nsPresC
     mPresContext(aPresContext),
     mRootRefresh(nullptr),
     mPendingTransaction(0),
     mCompletedTransaction(0),
     mFreezeCount(0),
     mThrottledFrameRequestInterval(TimeDuration::FromMilliseconds(
                                      GetThrottledTimerInterval())),
     mMinRecomputeVisibilityInterval(GetMinRecomputeVisibilityInterval()),
-    mMinNotifyIntersectionObserversInterval(
-      GetMinNotifyIntersectionObserversInterval()),
     mThrottled(false),
     mNeedToRecomputeVisibility(false),
     mTestControllingRefreshes(false),
     mViewManagerFlushIsPending(false),
     mRequestedHighPrecision(false),
     mInRefresh(false),
     mWaitingForTransaction(false),
     mSkippedPaints(false),
@@ -1047,17 +1033,16 @@ nsRefreshDriver::nsRefreshDriver(nsPresC
   MOZ_ASSERT(mPresContext,
              "Need a pres context to tell us to call Disconnect() later "
              "and decrement sRefreshDriverCount.");
   mMostRecentRefreshEpochTime = JS_Now();
   mMostRecentRefresh = TimeStamp::Now();
   mMostRecentTick = mMostRecentRefresh;
   mNextThrottledFrameRequestTick = mMostRecentTick;
   mNextRecomputeVisibilityTick = mMostRecentTick;
-  mNextNotifyIntersectionObserversTick = mMostRecentTick;
 
   ++sRefreshDriverCount;
 }
 
 nsRefreshDriver::~nsRefreshDriver()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(ObserverCount() == 0,
@@ -1838,32 +1823,16 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
       aNowTime >= mNextRecomputeVisibilityTick &&
       !presShell->IsPaintingSuppressed()) {
     mNextRecomputeVisibilityTick = aNowTime + mMinRecomputeVisibilityInterval;
     mNeedToRecomputeVisibility = false;
 
     presShell->ScheduleApproximateFrameVisibilityUpdateNow();
   }
 
-  bool notifyIntersectionObservers = false;
-  if (aNowTime >= mNextNotifyIntersectionObserversTick) {
-    mNextNotifyIntersectionObserversTick =
-      aNowTime + mMinNotifyIntersectionObserversInterval;
-    notifyIntersectionObservers = true;
-  }
-  nsCOMArray<nsIDocument> documents;
-  CollectDocuments(mPresContext->Document(), &documents);
-  for (int32_t i = 0; i < documents.Count(); ++i) {
-    nsIDocument* doc = documents[i];
-    doc->UpdateIntersectionObservations();
-    if (notifyIntersectionObservers) {
-      doc->ScheduleIntersectionObserverNotification();
-    }
-  }
-
   /*
    * Perform notification to imgIRequests subscribed to listen
    * for refresh events.
    */
 
   for (auto iter = mStartTable.Iter(); !iter.Done(); iter.Next()) {
     const uint32_t& delay = iter.Key();
     ImageStartData* data = iter.UserData();
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -363,17 +363,16 @@ private:
   // Trigger a refresh immediately, if haven't been disconnected or frozen.
   void DoRefresh();
 
   double GetRefreshTimerInterval() const;
   double GetRegularTimerInterval(bool *outIsDefault = nullptr) const;
   static double GetThrottledTimerInterval();
 
   static mozilla::TimeDuration GetMinRecomputeVisibilityInterval();
-  static mozilla::TimeDuration GetMinNotifyIntersectionObserversInterval();
 
   bool HaveFrameRequestCallbacks() const {
     return mFrameRequestCallbackDocs.Length() != 0;
   }
 
   void FinishedWaitingForTransaction();
 
   mozilla::RefreshDriverTimer* ChooseTimer() const;
@@ -399,18 +398,16 @@ private:
   const mozilla::TimeDuration mThrottledFrameRequestInterval;
 
   // How long we wait, at a minimum, before recomputing approximate frame
   // visibility information. This is a minimum because, regardless of this
   // interval, we only recompute visibility when we've seen a layout or style
   // flush since the last time we did it.
   const mozilla::TimeDuration mMinRecomputeVisibilityInterval;
 
-  const mozilla::TimeDuration mMinNotifyIntersectionObserversInterval;
-
   bool mThrottled;
   bool mNeedToRecomputeVisibility;
   bool mTestControllingRefreshes;
   bool mViewManagerFlushIsPending;
   bool mRequestedHighPrecision;
   bool mInRefresh;
 
   // True if the refresh driver is suspended waiting for transaction
@@ -431,17 +428,16 @@ private:
   // transaction to be completed before we append a note to the gfx critical log.
   // The number is doubled every time the threshold is hit.
   uint64_t mWarningThreshold;
   mozilla::TimeStamp mMostRecentRefresh;
   mozilla::TimeStamp mMostRecentTick;
   mozilla::TimeStamp mTickStart;
   mozilla::TimeStamp mNextThrottledFrameRequestTick;
   mozilla::TimeStamp mNextRecomputeVisibilityTick;
-  mozilla::TimeStamp mNextNotifyIntersectionObserversTick;
 
   // separate arrays for each flush type we support
   ObserverArray mObservers[3];
   RequestTable mRequests;
   ImageStartTable mStartTable;
 
   struct PendingEvent {
     nsCOMPtr<nsINode> mTarget;
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -227,22 +227,16 @@ public:
                                  nsCSSValue& aValue);
 
   bool ParseColorString(const nsSubstring& aBuffer,
                         nsIURI* aURL, // for error reporting
                         uint32_t aLineNumber, // for error reporting
                         nsCSSValue& aValue,
                         bool aSuppressErrors /* false */);
 
-  bool ParseMarginString(const nsSubstring& aBuffer,
-                         nsIURI* aURL, // for error reporting
-                         uint32_t aLineNumber, // for error reporting
-                         nsCSSValue& aValue,
-                         bool aSuppressErrors /* false */);
-
   nsresult ParseSelectorString(const nsSubstring& aSelectorString,
                                nsIURI* aURL, // for error reporting
                                uint32_t aLineNumber, // for error reporting
                                nsCSSSelectorList **aSelectorList);
 
   already_AddRefed<nsCSSKeyframeRule>
   ParseKeyframeRule(const nsSubstring& aBuffer,
                     nsIURI*            aURL,
@@ -1159,18 +1153,17 @@ protected:
    * Calls AppendImpliedEOFCharacters on mScanner.
    */
   void AppendImpliedEOFCharacters(nsAString& aResult);
 
   // Reused utility parsing routines
   void AppendValue(nsCSSPropertyID aPropID, const nsCSSValue& aValue);
   bool ParseBoxProperties(const nsCSSPropertyID aPropIDs[]);
   bool ParseGroupedBoxProperty(int32_t aVariantMask,
-                               nsCSSValue& aValue,
-                               uint32_t aRestrictions);
+                               nsCSSValue& aValue);
   bool ParseBoxCornerRadius(const nsCSSPropertyID aPropID);
   bool ParseBoxCornerRadiiInternals(nsCSSValue array[]);
   bool ParseBoxCornerRadii(const nsCSSPropertyID aPropIDs[]);
 
   int32_t ParseChoice(nsCSSValue aValues[],
                       const nsCSSPropertyID aPropIDs[], int32_t aNumIDs);
 
   CSSParseResult ParseColor(nsCSSValue& aValue);
@@ -2275,42 +2268,16 @@ CSSParserImpl::ParseColorString(const ns
     OUTPUT_ERROR();
   }
 
   ReleaseScanner();
   return colorParsed;
 }
 
 bool
-CSSParserImpl::ParseMarginString(const nsSubstring& aBuffer,
-                                 nsIURI* aURI, // for error reporting
-                                 uint32_t aLineNumber, // for error reporting
-                                 nsCSSValue& aValue,
-                                 bool aSuppressErrors /* false */)
-{
-  nsCSSScanner scanner(aBuffer, aLineNumber);
-  css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aURI);
-  InitScanner(scanner, reporter, aURI, aURI, nullptr);
-
-  nsAutoSuppressErrors suppressErrors(this, aSuppressErrors);
-
-  // Parse a margin, and check that there's nothing else after it.
-  bool marginParsed = ParseGroupedBoxProperty(VARIANT_LP, aValue, 0) && !GetToken(true);
-
-  if (aSuppressErrors) {
-    CLEAR_ERROR();
-  } else {
-    OUTPUT_ERROR();
-  }
-
-  ReleaseScanner();
-  return marginParsed;
-}
-
-bool
 CSSParserImpl::ParseFontFamilyListString(const nsSubstring& aBuffer,
                                          nsIURI* aURI, // for error reporting
                                          uint32_t aLineNumber, // for error reporting
                                          nsCSSValue& aValue)
 {
   nsCSSScanner scanner(aBuffer, aLineNumber);
   css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aURI);
   InitScanner(scanner, reporter, aURI, aURI, nullptr);
@@ -11212,30 +11179,29 @@ CSSParserImpl::ParseBoxProperties(const 
 
   NS_FOR_CSS_SIDES (index) {
     AppendValue(aPropIDs[index], result.*(nsCSSRect::sides[index]));
   }
   return true;
 }
 
 // Similar to ParseBoxProperties, except there is only one property
-// with the result as its value, not four.
+// with the result as its value, not four. Requires values be nonnegative.
 bool
 CSSParserImpl::ParseGroupedBoxProperty(int32_t aVariantMask,
-                                       /** outparam */ nsCSSValue& aValue,
-                                       uint32_t aRestrictions)
+                                       /** outparam */ nsCSSValue& aValue)
 {
   nsCSSRect& result = aValue.SetRectValue();
 
   int32_t count = 0;
   NS_FOR_CSS_SIDES (index) {
     CSSParseResult parseResult =
       ParseVariantWithRestrictions(result.*(nsCSSRect::sides[index]),
                                    aVariantMask, nullptr,
-                                   aRestrictions);
+                                   CSS_PROPERTY_VALUE_NONNEGATIVE);
     if (parseResult == CSSParseResult::NotFound) {
       break;
     }
     if (parseResult == CSSParseResult::Error) {
       return false;
     }
     count++;
   }
@@ -13239,18 +13205,17 @@ CSSParserImpl::ParseBorderImageSlice(boo
 
   // Try parsing "fill" value.
   nsCSSValue imageSliceFillValue;
   bool hasFill = ParseEnum(imageSliceFillValue,
                            nsCSSProps::kBorderImageSliceKTable);
 
   // Parse the box dimensions.
   nsCSSValue imageSliceBoxValue;
-  if (!ParseGroupedBoxProperty(VARIANT_PN, imageSliceBoxValue,
-                               CSS_PROPERTY_VALUE_NONNEGATIVE)) {
+  if (!ParseGroupedBoxProperty(VARIANT_PN, imageSliceBoxValue)) {
     if (!hasFill && aConsumedTokens) {
       *aConsumedTokens = false;
     }
 
     return false;
   }
 
   // Try parsing "fill" keyword again if the first time failed because keyword
@@ -13284,17 +13249,17 @@ CSSParserImpl::ParseBorderImageWidth(boo
       ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     // Keywords "inherit", "initial" and "unset" can not be mixed, so we
     // are done.
     AppendValue(eCSSProperty_border_image_width, value);
     return true;
   }
 
   // Parse the box dimensions.
-  if (!ParseGroupedBoxProperty(VARIANT_ALPN, value, CSS_PROPERTY_VALUE_NONNEGATIVE)) {
+  if (!ParseGroupedBoxProperty(VARIANT_ALPN, value)) {
     return false;
   }
 
   AppendValue(eCSSProperty_border_image_width, value);
   return true;
 }
 
 bool
@@ -13307,17 +13272,17 @@ CSSParserImpl::ParseBorderImageOutset(bo
       ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     // Keywords "inherit", "initial" and "unset" can not be mixed, so we
     // are done.
     AppendValue(eCSSProperty_border_image_outset, value);
     return true;
   }
 
   // Parse the box dimensions.
-  if (!ParseGroupedBoxProperty(VARIANT_LN, value, CSS_PROPERTY_VALUE_NONNEGATIVE)) {
+  if (!ParseGroupedBoxProperty(VARIANT_LN, value)) {
     return false;
   }
 
   AppendValue(eCSSProperty_border_image_outset, value);
   return true;
 }
 
 bool
@@ -18024,27 +17989,16 @@ nsCSSParser::ParseColorString(const nsSu
                               uint32_t           aLineNumber,
                               nsCSSValue&        aValue,
                               bool               aSuppressErrors /* false */)
 {
   return static_cast<CSSParserImpl*>(mImpl)->
     ParseColorString(aBuffer, aURI, aLineNumber, aValue, aSuppressErrors);
 }
 
-bool
-nsCSSParser::ParseMarginString(const nsSubstring& aBuffer,
-                               nsIURI*            aURI,
-                               uint32_t           aLineNumber,
-                               nsCSSValue&        aValue,
-                               bool               aSuppressErrors /* false */)
-{
-  return static_cast<CSSParserImpl*>(mImpl)->
-    ParseMarginString(aBuffer, aURI, aLineNumber, aValue, aSuppressErrors);
-}
-
 nsresult
 nsCSSParser::ParseSelectorString(const nsSubstring&  aSelectorString,
                                  nsIURI*             aURI,
                                  uint32_t            aLineNumber,
                                  nsCSSSelectorList** aSelectorList)
 {
   return static_cast<CSSParserImpl*>(mImpl)->
     ParseSelectorString(aSelectorString, aURI, aLineNumber, aSelectorList);
--- a/layout/style/nsCSSParser.h
+++ b/layout/style/nsCSSParser.h
@@ -201,28 +201,16 @@ public:
    */
   bool ParseColorString(const nsSubstring& aBuffer,
                         nsIURI*            aURL,
                         uint32_t           aLineNumber,
                         nsCSSValue&        aValue,
                         bool               aSuppressErrors = false);
 
   /**
-   * Parse aBuffer into a nsCSSValue |aValue|. Will return false
-   * if aBuffer is not a valid CSS margin specification.
-   * One can use nsRuleNode::GetRectValue to compute an nsCSSRect from
-   * the returned nsCSSValue.
-   */
-  bool ParseMarginString(const nsSubstring& aBuffer,
-                         nsIURI*            aURL,
-                         uint32_t           aLineNumber,
-                         nsCSSValue&        aValue,
-                         bool               aSuppressErrors = false);
-
-  /**
    * Parse aBuffer into a selector list.  On success, caller must
    * delete *aSelectorList when done with it.
    */
   nsresult ParseSelectorString(const nsSubstring&  aSelectorString,
                                nsIURI*             aURL,
                                uint32_t            aLineNumber,
                                nsCSSSelectorList** aSelectorList);
 
--- a/layout/style/nsCSSPropertyID.h
+++ b/layout/style/nsCSSPropertyID.h
@@ -58,20 +58,17 @@ enum nsCSSPropertyID {
   eCSSPropertyExtra_no_properties,
   eCSSPropertyExtra_all_properties,
 
   // Extra dummy values for nsCSSParser internal use.
   eCSSPropertyExtra_x_none_value,
   eCSSPropertyExtra_x_auto_value,
 
   // Extra value to represent custom properties (--*).
-  eCSSPropertyExtra_variable,
-
-  // Extra value for use in the DOM API's
-  eCSSProperty_DOM
+  eCSSPropertyExtra_variable
 };
 
 namespace mozilla {
 
 template<>
 inline PLDHashNumber
 Hash<nsCSSPropertyID>(const nsCSSPropertyID& aValue)
 {
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1213,18 +1213,17 @@ nsCSSValue::AppendAlignJustifyValueToStr
 
 void
 nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
                            Serialization aSerialization) const
 {
   // eCSSProperty_UNKNOWN gets used for some recursive calls below.
   MOZ_ASSERT((0 <= aProperty &&
               aProperty <= eCSSProperty_COUNT_no_shorthands) ||
-             aProperty == eCSSProperty_UNKNOWN ||
-             aProperty == eCSSProperty_DOM,
+             aProperty == eCSSProperty_UNKNOWN,
              "property ID out of range");
 
   nsCSSUnit unit = GetUnit();
   if (unit == eCSSUnit_Null) {
     return;
   }
 
   if (eCSSUnit_String <= unit && unit <= eCSSUnit_Attr) {
@@ -2425,18 +2424,17 @@ nsCSSRect::AppendToString(nsCSSPropertyI
   MOZ_ASSERT(mTop.GetUnit() != eCSSUnit_Null &&
              mTop.GetUnit() != eCSSUnit_Inherit &&
              mTop.GetUnit() != eCSSUnit_Initial &&
              mTop.GetUnit() != eCSSUnit_Unset,
              "parser should have used a bare value");
 
   if (eCSSProperty_border_image_slice == aProperty ||
       eCSSProperty_border_image_width == aProperty ||
-      eCSSProperty_border_image_outset == aProperty ||
-      eCSSProperty_DOM == aProperty) {
+      eCSSProperty_border_image_outset == aProperty) {
     NS_NAMED_LITERAL_STRING(space, " ");
 
     mTop.AppendToString(aProperty, aResult, aSerialization);
     aResult.Append(space);
     mRight.AppendToString(aProperty, aResult, aSerialization);
     aResult.Append(space);
     mBottom.AppendToString(aProperty, aResult, aSerialization);
     aResult.Append(space);
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -660,20 +660,16 @@ public:
     { return eCSSUnit_EM <= mUnit && mUnit <= eCSSUnit_RootEM; }
   /**
    * A "pixel" length unit is a some multiple of CSS pixels.
    */
   static bool IsPixelLengthUnit(nsCSSUnit aUnit)
     { return eCSSUnit_Point <= aUnit && aUnit <= eCSSUnit_Pixel; }
   bool      IsPixelLengthUnit() const
     { return IsPixelLengthUnit(mUnit); }
-  static bool IsPercentLengthUnit(nsCSSUnit aUnit)
-    { return aUnit == eCSSUnit_Percent; }
-  bool      IsPercentLengthUnit()
-    { return IsPercentLengthUnit(mUnit); }
   static bool IsFloatUnit(nsCSSUnit aUnit)
     { return eCSSUnit_Number <= aUnit; }
   bool      IsAngularUnit() const  
     { return eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Turn; }
   bool      IsFrequencyUnit() const  
     { return eCSSUnit_Hertz <= mUnit && mUnit <= eCSSUnit_Kilohertz; }
   bool      IsTimeUnit() const  
     { return eCSSUnit_Seconds <= mUnit && mUnit <= eCSSUnit_Milliseconds; }