Bug 1333580 - Properly unregister last unobserved target. r?mrbkap draft
authorTobias Schneider <schneider@jancona.com>
Tue, 24 Jan 2017 14:11:34 -0800
changeset 465806 527b2753d1ccef5bfc9b72ac98ca53dcd2c9817d
parent 464800 bd0cd9af94d9334b862d9891013fed56fb9b3b7c
child 543264 32ffb7d11c8e1a6e78f59cba8825c4b5d64285a9
push id42727
push userbmo:tschneider@mozilla.com
push dateTue, 24 Jan 2017 22:23:12 +0000
reviewersmrbkap
bugs1333580
milestone53.0a1
Bug 1333580 - Properly unregister last unobserved target. r?mrbkap MozReview-Commit-ID: FfPJFSXeT98
dom/base/DOMIntersectionObserver.cpp
dom/base/DOMIntersectionObserver.h
dom/base/crashtests/1332939.html
dom/base/crashtests/crashtests.list
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -154,34 +154,36 @@ DOMIntersectionObserver::Observe(Element
   aTarget.RegisterIntersectionObserver(this);
   mObservationTargets.PutEntry(&aTarget);
   Connect();
 }
 
 void
 DOMIntersectionObserver::Unobserve(Element& aTarget)
 {
-  if (UnlinkTarget(aTarget)) {
-    aTarget.UnregisterIntersectionObserver(this);
+  if (mObservationTargets.Count() == 1) {
+    Disconnect();
+    return;
   }
+
+  mObservationTargets.RemoveEntry(&aTarget);
+  aTarget.UnregisterIntersectionObserver(this);
 }
 
-bool
+void
 DOMIntersectionObserver::UnlinkTarget(Element& aTarget)
 {
     if (!mObservationTargets.Contains(&aTarget)) {
-        return false;
+        return;
     }
 
     mObservationTargets.RemoveEntry(&aTarget);
     if (mObservationTargets.Count() == 0) {
         Disconnect();
-        return false;
     }
-    return true;
 }
 
 void
 DOMIntersectionObserver::Connect()
 {
   if (mConnected) {
     return;
   }
--- a/dom/base/DOMIntersectionObserver.h
+++ b/dom/base/DOMIntersectionObserver.h
@@ -96,17 +96,19 @@ protected:
 
 #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() { }
+  virtual ~DOMIntersectionObserver() {
+    Disconnect();
+  }
 
 public:
   DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
                           mozilla::dom::IntersectionCallback& aCb)
   : mOwner(aOwner), mCallback(&aCb), mConnected(false)
   {
   }
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -137,17 +139,17 @@ public:
     return mRoot;
   }
 
   void GetRootMargin(mozilla::dom::DOMString& aRetVal);
   void GetThresholds(nsTArray<double>& aRetVal);
   void Observe(Element& aTarget);
   void Unobserve(Element& aTarget);
 
-  bool UnlinkTarget(Element& aTarget);
+  void UnlinkTarget(Element& aTarget);
   void Disconnect();
 
   void TakeRecords(nsTArray<RefPtr<DOMIntersectionObserverEntry>>& aRetVal);
 
   mozilla::dom::IntersectionCallback* IntersectionCallback() { return mCallback; }
 
   bool SetRootMargin(const nsAString& aString);
 
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1332939.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script type="application/javascript">
+
+var target = document.createElement("div");
+target.foo = 'bar';
+var observer = new IntersectionObserver(function () { });
+observer.observe(target);
+observer.unobserve(target);
+observer = null;
+target = null;
+
+</script>
+</head>
+</html>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -206,8 +206,9 @@ HTTP(..) load xhr_abortinprogress.html
 load xhr_empty_datauri.html
 load xhr_html_nullresponse.html
 load 1230422.html
 load 1251361.html
 load 1304437.html
 pref(dom.IntersectionObserver.enabled,true) load 1324209.html
 pref(dom.IntersectionObserver.enabled,true) load 1326194-1.html
 pref(dom.IntersectionObserver.enabled,true) load 1326194-2.html
+pref(dom.IntersectionObserver.enabled,true) load 1332939.html