Backed out changeset 3a89e23a25f0 (bug 839838) for rooting analysis bustage on a CLOSED TREE.
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 11 Oct 2014 19:47:58 +0200
changeset 209976 16a8a5c8b96a2fe14420f3a689b099e4410ddf32
parent 209975 03de764d461a9d023d65a20279fdb6dc26ce56c4
child 209977 44168a7af20de3db73f0a7ed63abd923ad3a3732
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
bugs839838
milestone35.0a1
backs out3a89e23a25f07bf29ad5da35dcb04edc772d481b
Backed out changeset 3a89e23a25f0 (bug 839838) for rooting analysis bustage on a CLOSED TREE.
dom/base/DOMCursor.h
dom/base/DOMRequest.cpp
dom/base/DOMRequest.h
dom/base/test/test_domcursor.html
dom/base/test/test_domrequest.html
dom/bindings/Bindings.conf
dom/bindings/ToJSValue.h
dom/telephony/test/marionette/head.js
dom/webidl/DOMCursor.webidl
dom/webidl/DOMRequest.webidl
js/public/RootingAPI.h
--- a/dom/base/DOMCursor.h
+++ b/dom/base/DOMCursor.h
@@ -38,21 +38,16 @@ public:
   void Reset();
   void FireDone();
 
 protected:
   ~DOMCursor() {}
 
 private:
   DOMCursor() MOZ_DELETE;
-  // Calling Then() on DOMCursor is a mistake, since the DOMCursor object
-  // should not have a .then() method from JS' point of view.
-  already_AddRefed<mozilla::dom::Promise>
-  Then(JSContext* aCx, AnyCallback* aResolveCallback,
-       AnyCallback* aRejectCallback, ErrorResult& aRv) MOZ_DELETE;
 
   nsCOMPtr<nsICursorContinueCallback> mCallback;
   bool mFinished;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -5,54 +5,41 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DOMRequest.h"
 
 #include "DOMError.h"
 #include "nsThreadUtils.h"
 #include "DOMCursor.h"
 #include "nsIDOMEvent.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/ScriptSettings.h"
 
-using mozilla::dom::AnyCallback;
 using mozilla::dom::DOMError;
 using mozilla::dom::DOMRequest;
 using mozilla::dom::DOMRequestService;
 using mozilla::dom::DOMCursor;
-using mozilla::dom::Promise;
 using mozilla::AutoSafeJSContext;
 
 DOMRequest::DOMRequest(nsPIDOMWindow* aWindow)
   : DOMEventTargetHelper(aWindow->IsInnerWindow() ?
                            aWindow : aWindow->GetCurrentInnerWindow())
   , mResult(JSVAL_VOID)
   , mDone(false)
 {
 }
 
-DOMRequest::~DOMRequest()
-{
-  mResult.setUndefined();
-  mozilla::DropJSObjects(this);
-}
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest,
                                                   DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest,
                                                 DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
   tmp->mResult = JSVAL_VOID;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DOMRequest,
                                                DOMEventTargetHelper)
   // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
   // DOMEventTargetHelper does it for us.
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mResult)
@@ -115,72 +102,56 @@ DOMRequest::FireSuccess(JS::Handle<JS::V
 
   mDone = true;
   if (aResult.isGCThing()) {
     RootResultVal();
   }
   mResult = aResult;
 
   FireEvent(NS_LITERAL_STRING("success"), false, false);
-
-  if (mPromise) {
-    mPromise->MaybeResolve(mResult);
-  }
 }
 
 void
 DOMRequest::FireError(const nsAString& aError)
 {
   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
   NS_ASSERTION(!mError, "mError shouldn't have been set!");
   NS_ASSERTION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
   mDone = true;
   mError = new DOMError(GetOwner(), aError);
 
   FireEvent(NS_LITERAL_STRING("error"), true, true);
-
-  if (mPromise) {
-    mPromise->MaybeRejectBrokenly(mError);
-  }
 }
 
 void
 DOMRequest::FireError(nsresult aError)
 {
   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
   NS_ASSERTION(!mError, "mError shouldn't have been set!");
   NS_ASSERTION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
   mDone = true;
   mError = new DOMError(GetOwner(), aError);
 
   FireEvent(NS_LITERAL_STRING("error"), true, true);
-
-  if (mPromise) {
-    mPromise->MaybeRejectBrokenly(mError);
-  }
 }
 
 void
 DOMRequest::FireDetailedError(DOMError* aError)
 {
   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
   NS_ASSERTION(!mError, "mError shouldn't have been set!");
   NS_ASSERTION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
   NS_ASSERTION(aError, "No detailed error provided");
 
   mDone = true;
   mError = aError;
 
   FireEvent(NS_LITERAL_STRING("error"), true, true);
-
-  if (mPromise) {
-    mPromise->MaybeRejectBrokenly(mError);
-  }
 }
 
 void
 DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable)
 {
   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     return;
   }
@@ -199,41 +170,16 @@ DOMRequest::FireEvent(const nsAString& a
 }
 
 void
 DOMRequest::RootResultVal()
 {
   mozilla::HoldJSObjects(this);
 }
 
-already_AddRefed<Promise>
-DOMRequest::Then(JSContext* aCx, AnyCallback* aResolveCallback,
-                 AnyCallback* aRejectCallback, mozilla::ErrorResult& aRv)
-{
-  if (!mPromise) {
-    mPromise = Promise::Create(DOMEventTargetHelper::GetParentObject(), aRv);
-    if (aRv.Failed()) {
-      return nullptr;
-    }
-    if (mDone) {
-      // Since we create mPromise lazily, it's possible that the DOMRequest object
-      // has already fired its success/error event.  In that case we should
-      // manually resolve/reject mPromise here.  mPromise will take care of
-      // calling the callbacks on |promise| as needed.
-      if (mError) {
-        mPromise->MaybeRejectBrokenly(mError);
-      } else {
-        mPromise->MaybeResolve(mResult);
-      }
-    }
-  }
-
-  return mPromise->Then(aCx, aResolveCallback, aRejectCallback, aRv);
-}
-
 NS_IMPL_ISUPPORTS(DOMRequestService, nsIDOMRequestService)
 
 NS_IMETHODIMP
 DOMRequestService::CreateRequest(nsIDOMWindow* aWindow,
                                  nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aWindow));
   NS_ENSURE_STATE(win);
@@ -302,17 +248,17 @@ public:
   // Due to the fact that initialization can fail during shutdown (since we
   // can't fetch a js context), set up an initiatization function to make sure
   // we can return the failure appropriately
   static nsresult
   Dispatch(DOMRequest* aRequest,
            const JS::Value& aResult)
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-    mozilla::ThreadsafeAutoSafeJSContext cx;
+    AutoSafeJSContext cx;
     nsRefPtr<FireSuccessAsyncTask> asyncTask = new FireSuccessAsyncTask(cx, aRequest, aResult);
     if (NS_FAILED(NS_DispatchToMainThread(asyncTask))) {
       NS_WARNING("Failed to dispatch to main thread!");
       return NS_ERROR_FAILURE;
     }
     return NS_OK;
   }
 
--- a/dom/base/DOMRequest.h
+++ b/dom/base/DOMRequest.h
@@ -11,31 +11,24 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/DOMRequestBinding.h"
 
 #include "nsCOMPtr.h"
 
 namespace mozilla {
-
-class ErrorResult;
-
 namespace dom {
 
-class AnyCallback;
-class Promise;
-
 class DOMRequest : public DOMEventTargetHelper,
                    public nsIDOMDOMRequest
 {
 protected:
   JS::Heap<JS::Value> mResult;
   nsRefPtr<DOMError> mError;
-  nsRefPtr<Promise> mPromise;
   bool mDone;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDOMREQUEST
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DOMRequest,
@@ -69,29 +62,30 @@ public:
     NS_ASSERTION(mDone || !mError,
                  "Error should be null when pending");
     return mError;
   }
 
   IMPL_EVENT_HANDLER(success)
   IMPL_EVENT_HANDLER(error)
 
-  already_AddRefed<mozilla::dom::Promise>
-  Then(JSContext* aCx, AnyCallback* aResolveCallback,
-       AnyCallback* aRejectCallback, mozilla::ErrorResult& aRv);
 
   void FireSuccess(JS::Handle<JS::Value> aResult);
   void FireError(const nsAString& aError);
   void FireError(nsresult aError);
   void FireDetailedError(DOMError* aError);
 
   explicit DOMRequest(nsPIDOMWindow* aWindow);
 
 protected:
-  virtual ~DOMRequest();
+  virtual ~DOMRequest()
+  {
+    mResult = JSVAL_VOID;
+    mozilla::DropJSObjects(this);
+  }
 
   void FireEvent(const nsAString& aType, bool aBubble, bool aCancelable);
 
   void RootResultVal();
 };
 
 class DOMRequestService MOZ_FINAL : public nsIDOMRequestService
 {
--- a/dom/base/test/test_domcursor.html
+++ b/dom/base/test/test_domcursor.html
@@ -46,17 +46,16 @@ var tests = [
     });
     ok("result" in req, "cursor has result");
     ok("error" in req, "cursor has error");
     ok("onsuccess" in req, "cursor has onsuccess");
     ok("onerror" in req, "cursor has onerror");
     ok("readyState" in req, "cursor has readyState");
     ok("done" in req, "cursor has finished");
     ok("continue" in req, "cursor has continue");
-    ok(!("then" in req), "cursor should not have a then method");
 
     is(req.readyState, "pending", "readyState is pending");
     is(req.result, undefined, "result is undefined");
     is(req.onsuccess, null, "onsuccess is null");
     is(req.onerror, null, "onerror is null");
     next();
   },
   function() {
--- a/dom/base/test/test_domrequest.html
+++ b/dom/base/test/test_domrequest.html
@@ -12,218 +12,65 @@
 </div>
 <pre id="test">
 <script class="testbody" type="application/javascript;version=1.7">
 "use strict";
 
 var reqserv = SpecialPowers.getDOMRequestService();
 ok("createRequest" in reqserv, "appears to be a service");
 
-function testBasics() {
-  // create a request
-  var req = reqserv.createRequest(window);
-  ok("result" in req, "request has result");
-  ok("error" in req, "request has error");
-  ok("onsuccess" in req, "request has onsuccess");
-  ok("onerror" in req, "request has onerror");
-  ok("readyState" in req, "request has readyState");
-  ok("then" in req, "request has then");
-
-  is(req.readyState, "pending", "readyState is pending");
-  is(req.result, undefined, "result is undefined");
-  is(req.onsuccess, null, "onsuccess is null");
-  is(req.onerror, null, "onerror is null");
-
-  runTest();
-}
+// create a request
+var req = reqserv.createRequest(window);
+ok("result" in req, "request has result");
+ok("error" in req, "request has error");
+ok("onsuccess" in req, "request has onsuccess");
+ok("onerror" in req, "request has onerror");
+ok("readyState" in req, "request has readyState");
 
-function testSuccess() {
-  // fire success
-  var req = reqserv.createRequest(window);
-  var ev = null;
-  req.onsuccess = function(e) {
-    ev = e;
-  }
-  var result = null;
-  var promise = req.then(function(r) {
-    is(r, "my result", "correct result when resolving the promise");
-    result = r;
-    runTest();
-  }, function(e) {
-    ok(false, "promise should not be rejected");
-    runTest();
-  });
-  ok(promise instanceof Promise, "then() should return a Promise");
-  reqserv.fireSuccess(req, "my result");
-  ok(ev, "got success event");
-  is(ev.type, "success", "correct type during success");
-  is(ev.target, req, "correct target during success");
-  is(req.readyState, "done", "correct readyState after success");
-  is(req.error, null, "correct error after success");
-  is(req.result, "my result", "correct result after success");
-  is(result, null, "Promise should not be resolved synchronously");
-}
+is(req.readyState, "pending", "readyState is pending");
+is(req.result, undefined, "result is undefined");
+is(req.onsuccess, null, "onsuccess is null");
+is(req.onerror, null, "onerror is null");
 
-function testError() {
-  // fire error
-  var req = reqserv.createRequest(window);
-  var ev = null;
-  req.onerror = function(e) {
-    ev = e;
-  }
-  var error = null;
-  var promise = req.then(function(r) {
-    ok(false, "promise should not be resolved");
-    runTest();
-  }, function(e) {
-    ok(e instanceof DOMError, "got error rejection");
-    ok(e === req.error, "got correct error when rejecting the promise");
-    error = e;
-    runTest();
-  });
-  ok(promise instanceof Promise, "then() should return a Promise");
-  reqserv.fireError(req, "OhMyError");
-  ok(ev, "got error event");
-  is(ev.type, "error", "correct type during error");
-  is(ev.target, req, "correct target during error");
-  is(req.readyState, "done", "correct readyState after error");
-  is(req.error.name, "OhMyError", "correct error after error");
-  is(req.result, undefined, "correct result after error");
-  is(error, null, "Promise should not be rejected synchronously");
+// fire success
+var ev = null;
+req.onsuccess = function(e) {
+  ev = e;
 }
-
-function testDetailedError() {
-  // fire detailed error
-  var req = reqserv.createRequest(window);
-  var ev = null;
-  req.onerror = function(e) {
-    ev = e;
-  };
-  var error = null;
-  var promise = req.then(function(r) {
-    ok(false, "promise should not be resolved");
-    runTest();
-  }, function(e) {
-    ok(e instanceof DOMError, "got error rejection");
-    ok(e === req.error, "got correct error when rejecting the promise");
-    error = e;
-    runTest();
-  });
-  ok(promise instanceof Promise, "then() should return a Promise");
-  reqserv.fireDetailedError(req, new DOMError("detailedError"));
-  ok(ev, "got error event");
-  is(ev.type, "error", "correct type during error");
-  is(ev.target, req, "correct target during error");
-  is(req.readyState, "done", "correct readyState after error");
-  is(req.error.name, "detailedError", "correct error after error");
-  is(req.result, undefined, "correct result after error");
-  is(error, null, "Promise should not be rejected synchronously");
-}
+reqserv.fireSuccess(req, "my result");
+ok(ev, "got success event");
+is(ev.type, "success", "correct type during success");
+is(ev.target, req, "correct target during success");
+is(req.readyState, "done", "correct readyState after success");
+is(req.error, null, "correct error after success");
+is(req.result, "my result", "correct result after success");
 
-function testThenAfterSuccess() {
-  // fire success
-  var req = reqserv.createRequest(window);
-  var ev = null;
-  req.onsuccess = function(e) {
-    ev = e;
-  }
-  reqserv.fireSuccess(req, "my result");
-  ok(ev, "got success event");
-  is(ev.type, "success", "correct type during success");
-  is(ev.target, req, "correct target during success");
-  is(req.readyState, "done", "correct readyState after success");
-  is(req.error, null, "correct error after success");
-  is(req.result, "my result", "correct result after success");
-  var result = null;
-  var promise = req.then(function(r) {
-    is(r, "my result", "correct result when resolving the promise");
-    result = r;
-    runTest();
-  }, function(e) {
-    ok(false, "promise should not be rejected");
-    runTest();
-  });
-  ok(promise instanceof Promise, "then() should return a Promise");
-  is(result, null, "Promise should not be resolved synchronously");
+// fire error
+req = reqserv.createRequest(window);
+ev = null;
+req.onerror = function(e) {
+  ev = e;
 }
+reqserv.fireError(req, "OhMyError");
+ok(ev, "got error event");
+is(ev.type, "error", "correct type during error");
+is(ev.target, req, "correct target during error");
+is(req.readyState, "done", "correct readyState after error");
+is(req.error.name, "OhMyError", "correct error after error");
+is(req.result, undefined, "correct result after error");
 
-function testThenAfterError() {
-  // fire error
-  var req = reqserv.createRequest(window);
-  var ev = null;
-  req.onerror = function(e) {
-    ev = e;
-  }
-  reqserv.fireError(req, "OhMyError");
-  ok(ev, "got error event");
-  is(ev.type, "error", "correct type during error");
-  is(ev.target, req, "correct target during error");
-  is(req.readyState, "done", "correct readyState after error");
-  is(req.error.name, "OhMyError", "correct error after error");
-  is(req.result, undefined, "correct result after error");
-  var error = null;
-  var promise = req.then(function(r) {
-    ok(false, "promise should not be resolved");
-    runTest();
-  }, function(e) {
-    ok(e instanceof DOMError, "got error rejection");
-    ok(e === req.error, "got correct error when rejecting the promise");
-    error = e;
-    runTest();
-  });
-  ok(promise instanceof Promise, "then() should return a Promise");
-  is(error, null, "Promise should not be rejected synchronously");
-}
-
-function testDetailedError() {
-  // fire detailed error
-  var req = reqserv.createRequest(window);
-  var ev = null;
-  req.onerror = function(e) {
-    ev = e;
-  };
-  var error = null;
-  var promise = req.then(function(r) {
-    ok(false, "promise should not be resolved");
-    runTest();
-  }, function(e) {
-    ok(e instanceof DOMError, "got error rejection");
-    ok(e === req.error, "got correct error when rejecting the promise");
-    error = e;
-    runTest();
-  });
-  ok(promise instanceof Promise, "then() should return a Promise");
-  reqserv.fireDetailedError(req, new DOMError("detailedError"));
-  ok(ev, "got error event");
-  is(ev.type, "error", "correct type during error");
-  is(ev.target, req, "correct target during error");
-  is(req.readyState, "done", "correct readyState after error");
-  is(req.error.name, "detailedError", "correct error after error");
-  is(req.result, undefined, "correct result after error");
-  is(error, null, "Promise should not be rejected synchronously");
-}
-
-var tests = [
-  testBasics,
-  testSuccess,
-  testError,
-  testDetailedError,
-  testThenAfterSuccess,
-  testThenAfterError,
-];
-
-function runTest() {
-  if (!tests.length) {
-    SimpleTest.finish();
-    return;
-  }
-
-  var test = tests.shift();
-  test();
-}
-
-SimpleTest.waitForExplicitFinish();
-runTest();
-
+// fire detailed error
+req = reqserv.createRequest(window);
+ev = null;
+req.onerror = function(e) {
+  ev = e;
+};
+reqserv.fireDetailedError(req, new DOMError("detailedError"));
+ok(ev, "got error event");
+is(ev.type, "error", "correct type during error");
+is(ev.target, req, "correct target during error");
+is(req.readyState, "done", "correct readyState after error");
+is(req.error.name, "detailedError", "correct error after error");
+is(req.result, undefined, "correct result after error");
 </script>
 </pre>
 </body>
 </html>
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -347,20 +347,16 @@ DOMInterfaces = {
 'DOMRectList': {
     'headerFile': 'mozilla/dom/DOMRect.h',
 },
 
 'DOMRectReadOnly': {
     'headerFile': 'mozilla/dom/DOMRect.h',
 },
 
-'DOMRequest': {
-    'implicitJSContext': [ 'then' ],
-},
-
 'DOMSettableTokenList': {
     'nativeType': 'nsDOMSettableTokenList',
 },
 
 'DOMStringMap': {
     'nativeType': 'nsDOMStringMap'
 },
 
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -231,34 +231,16 @@ ToJSValue(JSContext* aCx,
 inline bool
 ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   aValue.set(aArgument);
   return MaybeWrapValue(aCx, aValue);
 }
 
-// Accept existing JS values on the Heap (which may not be same-compartment with us
-inline bool
-ToJSValue(JSContext* aCx, JS::Heap<JS::Value> aArgument,
-          JS::MutableHandle<JS::Value> aValue)
-{
-  aValue.set(aArgument);
-  return MaybeWrapValue(aCx, aValue);
-}
-
-// Accept existing rooted JS values (which may not be same-compartment with us
-inline bool
-ToJSValue(JSContext* aCx, JS::Rooted<JS::Value> aArgument,
-          JS::MutableHandle<JS::Value> aValue)
-{
-  aValue.set(aArgument);
-  return MaybeWrapValue(aCx, aValue);
-}
-
 // Accept nsresult, for use in rejections, and create an XPCOM
 // exception object representing that nsresult.
 bool
 ToJSValue(JSContext* aCx,
           nsresult aArgument,
           JS::MutableHandle<JS::Value> aValue);
 
 // Accept pointers to other things we accept
--- a/dom/telephony/test/marionette/head.js
+++ b/dom/telephony/test/marionette/head.js
@@ -1311,16 +1311,25 @@ function startDSDSTest(test) {
     finish();
   }
 }
 
 function sendMMI(aMmi) {
   let deferred = Promise.defer();
 
   telephony.dial(aMmi)
-    .then(result => {
-      deferred.resolve(result);
+    .then(request => {
+      ok(request instanceof DOMRequest,
+         "request is instanceof " + request.constructor);
+
+      request.addEventListener("success", function(event) {
+        deferred.resolve(request.result);
+      });
+
+      request.addEventListener("error", function(event) {
+        deferred.reject(request.error);
+      });
     }, cause => {
       deferred.reject(cause);
     });
 
   return deferred.promise;
 }
--- a/dom/webidl/DOMCursor.webidl
+++ b/dom/webidl/DOMCursor.webidl
@@ -1,12 +1,10 @@
 /* -*- 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/. */
 
-interface DOMCursor : EventTarget {
+interface DOMCursor : DOMRequest {
   readonly attribute boolean done;
   [Throws]
   void continue();
 };
-
-DOMCursor implements DOMRequestShared;
--- a/dom/webidl/DOMRequest.webidl
+++ b/dom/webidl/DOMRequest.webidl
@@ -1,27 +1,16 @@
 /* -*- 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/. */
 
 enum DOMRequestReadyState { "pending", "done" };
 
-[NoInterfaceObject]
-interface DOMRequestShared {
+interface DOMRequest : EventTarget {
   readonly attribute DOMRequestReadyState readyState;
 
   readonly attribute any result;
   readonly attribute DOMError? error;
 
   attribute EventHandler onsuccess;
   attribute EventHandler onerror;
 };
-
-interface DOMRequest : EventTarget {
-  // The [TreatNonCallableAsNull] annotation is required since then() should do
-  // nothing instead of throwing errors when non-callable arguments are passed.
-  [NewObject, Throws]
-  Promise<any> then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
-                    [TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
-};
-
-DOMRequest implements DOMRequestShared;
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -215,17 +215,17 @@ class Heap : public js::HeapBase<T>
     explicit Heap(T p) { init(p); }
 
     /*
      * For Heap, move semantics are equivalent to copy semantics. In C++, a
      * copy constructor taking const-ref is the way to get a single function
      * that will be used for both lvalue and rvalue copies, so we can simply
      * omit the rvalue variant.
      */
-    Heap(const Heap<T> &p) { init(p.ptr); }
+    explicit Heap(const Heap<T> &p) { init(p.ptr); }
 
     ~Heap() {
         if (js::GCMethods<T>::needsPostBarrier(ptr))
             relocate();
     }
 
     bool operator==(const Heap<T> &other) { return ptr == other.ptr; }
     bool operator!=(const Heap<T> &other) { return ptr != other.ptr; }