Bug 1040263. Eagerly create and preserve Promise reflectors so we always have them available during unlink. r=nsm,bholley.
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 18 Jul 2014 21:31:11 -0400
changeset 195115 7784c83c72a20a527652ddc2e4e6b8b47cad6085
parent 195114 1db5409ea062d50c47374f1713af1f232e57d0ef
child 195116 a2f5fa870c8aaabf3ca79e925988baece89391e1
push id27169
push userryanvm@gmail.com
push dateMon, 21 Jul 2014 01:13:29 +0000
treeherdermozilla-central@4bafe35cfb65 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnsm, bholley
bugs1040263
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1040263. Eagerly create and preserve Promise reflectors so we always have them available during unlink. r=nsm,bholley.
content/html/content/src/HTMLMediaElement.cpp
content/media/eme/MediaKeySession.cpp
content/media/eme/MediaKeySession.h
content/media/eme/MediaKeys.cpp
content/media/eme/MediaKeys.h
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/SubtleCrypto.cpp
dom/base/SubtleCrypto.h
dom/bluetooth2/BluetoothAdapter.cpp
dom/bluetooth2/BluetoothDevice.cpp
dom/datastore/DataStoreService.cpp
dom/devicestorage/DeviceStorage.h
dom/devicestorage/nsDeviceStorage.cpp
dom/filesystem/CreateDirectoryTask.cpp
dom/filesystem/CreateDirectoryTask.h
dom/filesystem/CreateFileTask.cpp
dom/filesystem/CreateFileTask.h
dom/filesystem/Directory.cpp
dom/filesystem/Directory.h
dom/filesystem/GetFileOrDirectoryTask.cpp
dom/filesystem/GetFileOrDirectoryTask.h
dom/filesystem/RemoveTask.cpp
dom/filesystem/RemoveTask.h
dom/promise/Promise.cpp
dom/promise/Promise.h
dom/promise/PromiseWorkerProxy.h
dom/src/notification/Notification.cpp
dom/telephony/Telephony.cpp
dom/telephony/Telephony.h
dom/webidl/DeviceStorage.webidl
dom/webidl/Directory.webidl
dom/webidl/MediaKeySession.webidl
dom/webidl/MediaKeys.webidl
dom/webidl/Navigator.webidl
dom/webidl/Promise.webidl
dom/webidl/ServiceWorkerContainer.webidl
dom/webidl/SubtleCrypto.webidl
dom/webidl/Telephony.webidl
dom/workers/DataStore.cpp
dom/workers/DataStoreCursor.cpp
dom/workers/Navigator.cpp
dom/workers/ServiceWorkerContainer.cpp
dom/workers/ServiceWorkerContainer.h
dom/workers/ServiceWorkerManager.cpp
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -3962,17 +3962,20 @@ HTMLMediaElement::SetMediaKeys(mozilla::
 {
   nsCOMPtr<nsIGlobalObject> global =
     do_QueryInterface(OwnerDoc()->GetInnerWindow());
   if (!global) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
   // TODO: Need to shutdown existing MediaKeys instance? bug 1016709.
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   if (mMediaKeys != aMediaKeys) {
     mMediaKeys = aMediaKeys;
   }
   promise->MaybeResolve(JS::UndefinedHandleValue);
   return promise.forget();
 }
 
 MediaWaitingFor
--- a/content/media/eme/MediaKeySession.cpp
+++ b/content/media/eme/MediaKeySession.cpp
@@ -26,25 +26,26 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(MediaKeySession, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(MediaKeySession, DOMEventTargetHelper)
 
 MediaKeySession::MediaKeySession(nsPIDOMWindow* aParent,
                                  MediaKeys* aKeys,
                                  const nsAString& aKeySystem,
-                                 SessionType aSessionType)
+                                 SessionType aSessionType,
+                                 ErrorResult& aRv)
   : DOMEventTargetHelper(aParent)
   , mKeys(aKeys)
   , mKeySystem(aKeySystem)
   , mSessionType(aSessionType)
   , mIsClosed(false)
 {
   MOZ_ASSERT(aParent);
-  mClosed = mKeys->MakePromise();
+  mClosed = mKeys->MakePromise(aRv);
 }
 
 void MediaKeySession::Init(const nsAString& aSessionId)
 {
   mSessionId = aSessionId;
 }
 
 MediaKeySession::~MediaKeySession()
@@ -83,36 +84,42 @@ MediaKeySession::Expiration() const
 
 Promise*
 MediaKeySession::Closed() const
 {
   return mClosed;
 }
 
 already_AddRefed<Promise>
-MediaKeySession::Update(const Uint8Array& aResponse)
+MediaKeySession::Update(const Uint8Array& aResponse, ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise(mKeys->MakePromise());
+  nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   aResponse.ComputeLengthAndData();
   if (IsClosed() ||
       !mKeys->GetCDMProxy() ||
       !aResponse.Length()) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return promise.forget();
   }
   mKeys->GetCDMProxy()->UpdateSession(mSessionId,
                                       mKeys->StorePromise(promise),
                                       aResponse);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
-MediaKeySession::Close()
+MediaKeySession::Close(ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise(mKeys->MakePromise());
+  nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   if (IsClosed() || !mKeys->GetCDMProxy()) {
     promise->MaybeResolve(JS::UndefinedHandleValue);
     return promise.forget();
   }
   mKeys->GetCDMProxy()->CloseSession(mSessionId, mKeys->StorePromise(promise));
 
   return promise.forget();
 }
@@ -132,19 +139,22 @@ MediaKeySession::OnClosed()
 
 bool
 MediaKeySession::IsClosed() const
 {
   return mIsClosed;
 }
 
 already_AddRefed<Promise>
-MediaKeySession::Remove()
+MediaKeySession::Remove(ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise(mKeys->MakePromise());
+  nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   if (mSessionType != SessionType::Persistent) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     // "The operation is not supported on session type sessions."
     return promise.forget();
   }
   if (IsClosed() || !mKeys->GetCDMProxy()) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     // "The session is closed."
--- a/content/media/eme/MediaKeySession.h
+++ b/content/media/eme/MediaKeySession.h
@@ -34,17 +34,18 @@ class MediaKeySession MOZ_FINAL : public
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaKeySession,
                                            DOMEventTargetHelper)
 public:
   MediaKeySession(nsPIDOMWindow* aParent,
                   MediaKeys* aKeys,
                   const nsAString& aKeySystem,
-                  SessionType aSessionType);
+                  SessionType aSessionType,
+                  ErrorResult& aRv);
 
   void Init(const nsAString& aSessionId);
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // Mark this as resultNotAddRefed to return raw pointers
   MediaKeyError* GetError() const;
 
@@ -54,21 +55,22 @@ public:
 
   // Number of ms since epoch at which expiration occurs, or NaN if unknown.
   // TODO: The type of this attribute is still under contention.
   // https://www.w3.org/Bugs/Public/show_bug.cgi?id=25902
   double Expiration() const;
 
   Promise* Closed() const;
 
-  already_AddRefed<Promise> Update(const Uint8Array& response);
+  already_AddRefed<Promise> Update(const Uint8Array& response,
+                                   ErrorResult& aRv);
 
-  already_AddRefed<Promise> Close();
+  already_AddRefed<Promise> Close(ErrorResult& aRv);
 
-  already_AddRefed<Promise> Remove();
+  already_AddRefed<Promise> Remove(ErrorResult& aRv);
 
   void DispatchKeyMessage(const nsTArray<uint8_t>& aMessage,
                           const nsString& aURL);
 
   void DispatchKeyError(uint32_t system_code);
 
   void OnClosed();
 
--- a/content/media/eme/MediaKeys.cpp
+++ b/content/media/eme/MediaKeys.cpp
@@ -60,20 +60,23 @@ MediaKeys::WrapObject(JSContext* aCx)
 
 void
 MediaKeys::GetKeySystem(nsString& retval) const
 {
   retval = mKeySystem;
 }
 
 already_AddRefed<Promise>
-MediaKeys::SetServerCertificate(const Uint8Array& aCert)
+MediaKeys::SetServerCertificate(const Uint8Array& aCert, ErrorResult& aRv)
 {
   aCert.ComputeLengthAndData();
-  nsRefPtr<Promise> promise(MakePromise());
+  nsRefPtr<Promise> promise(MakePromise(aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   mProxy->SetServerCertificate(StorePromise(promise), aCert);
   return promise.forget();
 }
 
 /* static */
 IsTypeSupportedResult
 MediaKeys::IsTypeSupported(const GlobalObject& aGlobal,
                            const nsAString& aKeySystem,
@@ -83,25 +86,25 @@ MediaKeys::IsTypeSupported(const GlobalO
 {
   // TODO: Query list of known CDMs and their supported content types.
   // TODO: Should really get spec changed to this is async, so we can wait
   //       for user to consent to running plugin.
   return IsTypeSupportedResult::Maybe;
 }
 
 already_AddRefed<Promise>
-MediaKeys::MakePromise()
+MediaKeys::MakePromise(ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
   if (!global) {
     NS_WARNING("Passed non-global to MediaKeys ctor!");
+    aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
-  nsRefPtr<Promise> promise = new Promise(global);
-  return promise.forget();
+  return Promise::Create(global, aRv);
 }
 
 PromiseId
 MediaKeys::StorePromise(Promise* aPromise)
 {
   static uint32_t sEMEPromiseCount = 1;
   MOZ_ASSERT(aPromise);
   uint32_t id = sEMEPromiseCount++;
@@ -161,19 +164,18 @@ MediaKeys::Create(const GlobalObject& aG
   // returns the MediaKeys object to JS.
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
   if (!window) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsRefPtr<MediaKeys> keys = new MediaKeys(window, aKeySystem);
-  nsRefPtr<Promise> promise(keys->MakePromise());
-  if (!promise) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
+  nsRefPtr<Promise> promise(keys->MakePromise(aRv));
+  if (aRv.Failed()) {
     return nullptr;
   }
 
   if (!aKeySystem.EqualsASCII("org.w3.clearkey")) {
     aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return nullptr;
   }
 
@@ -191,54 +193,68 @@ MediaKeys::OnCDMCreated(PromiseId aId)
     NS_WARNING("MediaKeys tried to resolve a non-existent promise");
     return;
   }
   nsRefPtr<MediaKeys> keys(this);
   promise->MaybeResolve(keys);
 }
 
 already_AddRefed<Promise>
-MediaKeys::LoadSession(const nsAString& aSessionId)
+MediaKeys::LoadSession(const nsAString& aSessionId, ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise(MakePromise());
+  nsRefPtr<Promise> promise(MakePromise(aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   if (aSessionId.IsEmpty()) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     // "The sessionId parameter is empty."
     return promise.forget();
   }
 
   // TODO: The spec doesn't specify what to do in this case...
   if (mKeySessions.Contains(aSessionId)) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return promise.forget();
   }
 
   // Create session.
   nsRefPtr<MediaKeySession> session(
-    new MediaKeySession(GetParentObject(), this, mKeySystem, SessionType::Persistent));
+    new MediaKeySession(GetParentObject(), this, mKeySystem, SessionType::Persistent, aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   // Proxy owns session object until resolving promise.
   mProxy->LoadSession(StorePromise(promise),
                       aSessionId);
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 MediaKeys::CreateSession(const nsAString& initDataType,
                          const Uint8Array& aInitData,
-                         SessionType aSessionType)
+                         SessionType aSessionType,
+                         ErrorResult& aRv)
 {
   aInitData.ComputeLengthAndData();
-  nsRefPtr<Promise> promise(MakePromise());
+  nsRefPtr<Promise> promise(MakePromise(aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   nsRefPtr<MediaKeySession> session = new MediaKeySession(GetParentObject(),
                                                           this,
                                                           mKeySystem,
-                                                          aSessionType);
+                                                          aSessionType, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
   auto pid = StorePromise(promise);
   // Hang onto session until the CDM has finished setting it up.
   mPendingSessions.Put(pid, session);
   mProxy->CreateSession(aSessionType,
                         pid,
                         initDataType,
                         aInitData);
 
--- a/content/media/eme/MediaKeys.h
+++ b/content/media/eme/MediaKeys.h
@@ -49,23 +49,26 @@ public:
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // Javascript: readonly attribute DOMString keySystem;
   void GetKeySystem(nsString& retval) const;
 
   // JavaScript: MediaKeys.createSession()
   already_AddRefed<Promise> CreateSession(const nsAString& aInitDataType,
                                           const Uint8Array& aInitData,
-                                          SessionType aSessionType);
+                                          SessionType aSessionType,
+                                          ErrorResult& aRv);
 
   // JavaScript: MediaKeys.loadSession()
-  already_AddRefed<Promise> LoadSession(const nsAString& aSessionId);
+  already_AddRefed<Promise> LoadSession(const nsAString& aSessionId,
+                                        ErrorResult& aRv);
 
   // JavaScript: MediaKeys.SetServerCertificate()
-  already_AddRefed<Promise> SetServerCertificate(const Uint8Array& aServerCertificate);
+  already_AddRefed<Promise> SetServerCertificate(const Uint8Array& aServerCertificate,
+                                                 ErrorResult& aRv);
 
   // JavaScript: MediaKeys.create()
   static
   already_AddRefed<Promise> Create(const GlobalObject& aGlobal,
                                    const nsAString& aKeySystem,
                                    ErrorResult& aRv);
 
   // JavaScript: MediaKeys.IsTypeSupported()
@@ -82,17 +85,17 @@ public:
   // Called once a CreateSession or LoadSession succeeds.
   void OnSessionActivated(PromiseId aId, const nsAString& aSessionId);
   // Called once a session has closed.
   void OnSessionClosed(MediaKeySession* aSession);
 
   CDMProxy* GetCDMProxy() { return mProxy; }
 
   // Makes a new promise, or nullptr on failure.
-  already_AddRefed<Promise> MakePromise();
+  already_AddRefed<Promise> MakePromise(ErrorResult& aRv);
   // Stores promise in mPromises, returning an ID that can be used to retrieve
   // it later. The ID is passed to the CDM, so that it can signal specific
   // promises to be resolved.
   PromiseId StorePromise(Promise* aPromise);
 
   // Reject promise with DOMException corresponding to aExceptionCode.
   void RejectPromise(PromiseId aId, nsresult aExceptionCode);
   // Resolves promise with "undefined".
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1488,20 +1488,23 @@ Navigator::GetDataStores(nsPIDOMWindow* 
 
 already_AddRefed<Promise>
 Navigator::GetDataStores(const nsAString& aName, ErrorResult& aRv)
 {
   return GetDataStores(mWindow, aName, aRv);
 }
 
 already_AddRefed<Promise>
-Navigator::GetFeature(const nsAString& aName)
+Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
-  nsRefPtr<Promise> p = new Promise(go);
+  nsRefPtr<Promise> p = Promise::Create(go, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
 #if defined(XP_LINUX)
   if (aName.EqualsLiteral("hardware.memory")) {
     // with seccomp enabled, fopen() should be in a non-sandboxed process
     if (XRE_GetProcessType() == GeckoProcessType_Default) {
       uint32_t memLevel = mozilla::hal::GetTotalSystemMemoryLevel();
       if (memLevel == 0) {
         p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -162,17 +162,18 @@ public:
   static already_AddRefed<Promise> GetDataStores(nsPIDOMWindow* aWindow,
                                                  const nsAString& aName,
                                                  ErrorResult& aRv);
 
   already_AddRefed<Promise> GetDataStores(const nsAString &aName,
                                           ErrorResult& aRv);
 
   // Feature Detection API
-  already_AddRefed<Promise> GetFeature(const nsAString &aName);
+  already_AddRefed<Promise> GetFeature(const nsAString &aName,
+                                       ErrorResult& aRv);
 
   bool Vibrate(uint32_t aDuration);
   bool Vibrate(const nsTArray<uint32_t>& aDuration);
   uint32_t MaxTouchPoints();
   void GetAppCodeName(nsString& aAppCodeName, ErrorResult& aRv)
   {
     aRv = GetAppCodeName(aAppCodeName);
   }
--- a/dom/base/SubtleCrypto.cpp
+++ b/dom/base/SubtleCrypto.cpp
@@ -30,110 +30,123 @@ SubtleCrypto::SubtleCrypto(nsPIDOMWindow
 }
 
 JSObject*
 SubtleCrypto::WrapObject(JSContext* aCx)
 {
   return SubtleCryptoBinding::Wrap(aCx, this);
 }
 
-#define SUBTLECRYPTO_METHOD_BODY(Operation, ...) \
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow); \
-  MOZ_ASSERT(global); \
-  nsRefPtr<Promise> p = new Promise(global); \
+#define SUBTLECRYPTO_METHOD_BODY(Operation, aRv, ...)                   \
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);        \
+  MOZ_ASSERT(global);                                                   \
+  nsRefPtr<Promise> p = Promise::Create(global, aRv);                   \
+  if (aRv.Failed()) {                                                   \
+    return nullptr;                                                     \
+  }                                                                     \
   nsRefPtr<WebCryptoTask> task = WebCryptoTask::Operation ## Task(__VA_ARGS__); \
   task->DispatchWithPromise(p); \
   return p.forget();
 
 already_AddRefed<Promise>
 SubtleCrypto::Encrypt(JSContext* cx,
                       const ObjectOrString& algorithm,
                       CryptoKey& key,
-                      const CryptoOperationData& data)
+                      const CryptoOperationData& data,
+                      ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(Encrypt, cx, algorithm, key, data)
+  SUBTLECRYPTO_METHOD_BODY(Encrypt, aRv, cx, algorithm, key, data)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::Decrypt(JSContext* cx,
                       const ObjectOrString& algorithm,
                       CryptoKey& key,
-                      const CryptoOperationData& data)
+                      const CryptoOperationData& data,
+                      ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(Decrypt, cx, algorithm, key, data)
+  SUBTLECRYPTO_METHOD_BODY(Decrypt, aRv, cx, algorithm, key, data)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::Sign(JSContext* cx,
                    const ObjectOrString& algorithm,
                    CryptoKey& key,
-                   const CryptoOperationData& data)
+                   const CryptoOperationData& data,
+                   ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(Sign, cx, algorithm, key, data)
+  SUBTLECRYPTO_METHOD_BODY(Sign, aRv, cx, algorithm, key, data)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::Verify(JSContext* cx,
                      const ObjectOrString& algorithm,
                      CryptoKey& key,
                      const CryptoOperationData& signature,
-                     const CryptoOperationData& data)
+                     const CryptoOperationData& data,
+                     ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(Verify, cx, algorithm, key, signature, data)
+  SUBTLECRYPTO_METHOD_BODY(Verify, aRv, cx, algorithm, key, signature, data)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::Digest(JSContext* cx,
                      const ObjectOrString& algorithm,
-                     const CryptoOperationData& data)
+                     const CryptoOperationData& data,
+                     ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(Digest, cx, algorithm, data)
+  SUBTLECRYPTO_METHOD_BODY(Digest, aRv, cx, algorithm, data)
 }
 
 
 already_AddRefed<Promise>
 SubtleCrypto::ImportKey(JSContext* cx,
                         const nsAString& format,
                         const KeyData& keyData,
                         const ObjectOrString& algorithm,
                         bool extractable,
-                        const Sequence<nsString>& keyUsages)
+                        const Sequence<nsString>& keyUsages,
+                        ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(ImportKey, cx, format, keyData, algorithm,
-                                      extractable, keyUsages)
+  SUBTLECRYPTO_METHOD_BODY(ImportKey, aRv, cx, format, keyData, algorithm,
+                           extractable, keyUsages)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::ExportKey(const nsAString& format,
-                        CryptoKey& key)
+                        CryptoKey& key,
+                        ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(ExportKey, format, key)
+  SUBTLECRYPTO_METHOD_BODY(ExportKey, aRv, format, key)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::GenerateKey(JSContext* cx, const ObjectOrString& algorithm,
-                          bool extractable, const Sequence<nsString>& keyUsages)
+                          bool extractable, const Sequence<nsString>& keyUsages,
+                          ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(GenerateKey, cx, algorithm, extractable, keyUsages)
+  SUBTLECRYPTO_METHOD_BODY(GenerateKey, aRv, cx, algorithm, extractable, keyUsages)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::DeriveKey(JSContext* cx,
                         const ObjectOrString& algorithm,
                         CryptoKey& baseKey,
                         const ObjectOrString& derivedKeyType,
-                        bool extractable, const Sequence<nsString>& keyUsages)
+                        bool extractable, const Sequence<nsString>& keyUsages,
+                        ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(DeriveKey, cx, algorithm, baseKey, derivedKeyType,
-                                      extractable, keyUsages)
+  SUBTLECRYPTO_METHOD_BODY(DeriveKey, aRv, cx, algorithm, baseKey,
+                           derivedKeyType, extractable, keyUsages)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::DeriveBits(JSContext* cx,
                          const ObjectOrString& algorithm,
                          CryptoKey& baseKey,
-                         uint32_t length)
+                         uint32_t length,
+                         ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(DeriveBits, cx, algorithm, baseKey, length)
+  SUBTLECRYPTO_METHOD_BODY(DeriveBits, aRv, cx, algorithm, baseKey, length)
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/SubtleCrypto.h
+++ b/dom/base/SubtleCrypto.h
@@ -39,63 +39,73 @@ public:
     return mWindow;
   }
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   already_AddRefed<Promise> Encrypt(JSContext* cx,
                                     const ObjectOrString& algorithm,
                                     CryptoKey& key,
-                                    const CryptoOperationData& data);
+                                    const CryptoOperationData& data,
+                                    ErrorResult& aRv);
 
   already_AddRefed<Promise> Decrypt(JSContext* cx,
                                     const ObjectOrString& algorithm,
                                     CryptoKey& key,
-                                    const CryptoOperationData& data);
+                                    const CryptoOperationData& data,
+                                    ErrorResult& aRv);
 
   already_AddRefed<Promise> Sign(JSContext* cx,
                                  const ObjectOrString& algorithm,
                                  CryptoKey& key,
-                                 const CryptoOperationData& data);
+                                 const CryptoOperationData& data,
+                                 ErrorResult& aRv);
 
   already_AddRefed<Promise> Verify(JSContext* cx,
                                    const ObjectOrString& algorithm,
                                    CryptoKey& key,
                                    const CryptoOperationData& signature,
-                                   const CryptoOperationData& data);
+                                   const CryptoOperationData& data,
+                                   ErrorResult& aRv);
 
   already_AddRefed<Promise> Digest(JSContext* cx,
                                    const ObjectOrString& aAlgorithm,
-                                   const CryptoOperationData& aData);
+                                   const CryptoOperationData& aData,
+                                   ErrorResult& aRv);
 
   already_AddRefed<Promise> ImportKey(JSContext* cx,
                                       const nsAString& format,
                                       const KeyData& keyData,
                                       const ObjectOrString& algorithm,
                                       bool extractable,
-                                      const Sequence<nsString>& keyUsages);
+                                      const Sequence<nsString>& keyUsages,
+                                      ErrorResult& aRv);
 
-  already_AddRefed<Promise> ExportKey(const nsAString& format, CryptoKey& key);
+  already_AddRefed<Promise> ExportKey(const nsAString& format, CryptoKey& key,
+                                      ErrorResult& aRv);
 
   already_AddRefed<Promise> GenerateKey(JSContext* cx,
                                         const ObjectOrString& algorithm,
                                         bool extractable,
-                                        const Sequence<nsString>& keyUsages);
+                                        const Sequence<nsString>& keyUsages,
+                                        ErrorResult& aRv);
 
   already_AddRefed<Promise> DeriveKey(JSContext* cx,
                                       const ObjectOrString& algorithm,
                                       CryptoKey& baseKey,
                                       const ObjectOrString& derivedKeyType,
                                       bool extractable,
-                                      const Sequence<nsString>& keyUsages);
+                                      const Sequence<nsString>& keyUsages,
+                                      ErrorResult& aRv);
 
   already_AddRefed<Promise> DeriveBits(JSContext* cx,
                                        const ObjectOrString& algorithm,
                                        CryptoKey& baseKey,
-                                       uint32_t length);
+                                       uint32_t length,
+                                       ErrorResult& aRv);
 
 private:
   nsCOMPtr<nsPIDOMWindow> mWindow;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/bluetooth2/BluetoothAdapter.cpp
+++ b/dom/bluetooth2/BluetoothAdapter.cpp
@@ -415,17 +415,20 @@ BluetoothAdapter::SetDiscoveryHandleInUs
 already_AddRefed<Promise>
 BluetoothAdapter::StartDiscovery(ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   if (!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   /**
    * Ensure
    * - adapter is not discovering (note we reject here to ensure
        each resolved promise returns a new BluetoothDiscoveryHandle),
    * - adapter is already enabled, and
    * - BluetoothService is available
    */
@@ -513,17 +516,20 @@ BluetoothAdapter::GetUuids(JSContext* aC
 already_AddRefed<Promise>
 BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   if(!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   /**
    * Ensure
    * - adapter's name does not equal to aName,
    * - adapter is already enabled, and
    * - BluetoothService is available
    */
   BT_ENSURE_TRUE_RESOLVE(!mName.Equals(aName), JS::UndefinedHandleValue);
@@ -551,17 +557,20 @@ BluetoothAdapter::SetName(const nsAStrin
 already_AddRefed<Promise>
 BluetoothAdapter::SetDiscoverable(bool aDiscoverable, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   if(!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   /**
    * Ensure
    * - mDiscoverable does not equal to aDiscoverable,
    * - adapter is already enabled, and
    * - BluetoothService is available
    */
   BT_ENSURE_TRUE_RESOLVE(mDiscoverable != aDiscoverable,
@@ -779,17 +788,20 @@ BluetoothAdapter::SetPairingConfirmation
 already_AddRefed<Promise>
 BluetoothAdapter::EnableDisable(bool aEnable, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   if(!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   // Ensure BluetoothService is available before modifying adapter state
   BluetoothService* bs = BluetoothService::Get();
   BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
 
   // Modify adapter state to Enabling/Disabling if adapter is in a valid state
   nsAutoString methodName;
   if (aEnable) {
--- a/dom/bluetooth2/BluetoothDevice.cpp
+++ b/dom/bluetooth2/BluetoothDevice.cpp
@@ -138,17 +138,20 @@ already_AddRefed<Promise>
 BluetoothDevice::FetchUuids(ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   if (!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   BluetoothService* bs = BluetoothService::Get();
   BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
 
   nsRefPtr<BluetoothReplyRunnable> result =
     new FetchUuidsTask(promise,
                        NS_LITERAL_STRING("FetchUuids"),
                        this);
--- a/dom/datastore/DataStoreService.cpp
+++ b/dom/datastore/DataStoreService.cpp
@@ -879,17 +879,21 @@ DataStoreService::GetDataStores(nsIDOMWi
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
   if (!window) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window);
-  nsRefPtr<Promise> promise = new Promise(global);
+  ErrorResult rv;
+  nsRefPtr<Promise> promise = Promise::Create(global, rv);
+  if (rv.Failed()) {
+    return rv.ErrorCode();
+  }
 
   nsCOMPtr<nsIDocument> document = window->GetDoc();
   MOZ_ASSERT(document);
 
   nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
   MOZ_ASSERT(principal);
 
   nsTArray<DataStoreInfo> stores;
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -279,17 +279,17 @@ public:
   bool CanBeMounted();
   bool CanBeFormatted();
   bool CanBeShared();
   bool Default();
 
   // Uses XPCOM GetStorageName
 
   already_AddRefed<Promise>
-  GetRoot();
+  GetRoot(ErrorResult& aRv);
 
   static void
   CreateDeviceStorageFor(nsPIDOMWindow* aWin,
                          const nsAString& aType,
                          nsDOMDeviceStorage** aStore);
 
   static void
   CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -4116,23 +4116,23 @@ nsDOMDeviceStorage::CanBeMounted()
 
 bool
 nsDOMDeviceStorage::CanBeShared()
 {
   return mIsShareable;
 }
 
 already_AddRefed<Promise>
-nsDOMDeviceStorage::GetRoot()
+nsDOMDeviceStorage::GetRoot(ErrorResult& aRv)
 {
   if (!mFileSystem) {
     mFileSystem = new DeviceStorageFileSystem(mStorageType, mStorageName);
     mFileSystem->Init(this);
   }
-  return mozilla::dom::Directory::GetRoot(mFileSystem);
+  return mozilla::dom::Directory::GetRoot(mFileSystem, aRv);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::GetDefault(bool* aDefault)
 {
   *aDefault = Default();
   return NS_OK;
 }
--- a/dom/filesystem/CreateDirectoryTask.cpp
+++ b/dom/filesystem/CreateDirectoryTask.cpp
@@ -13,28 +13,29 @@
 #include "mozilla/dom/Promise.h"
 #include "nsIFile.h"
 #include "nsStringGlue.h"
 
 namespace mozilla {
 namespace dom {
 
 CreateDirectoryTask::CreateDirectoryTask(FileSystemBase* aFileSystem,
-                                         const nsAString& aPath)
+                                         const nsAString& aPath,
+                                         ErrorResult& aRv)
   : FileSystemTaskBase(aFileSystem)
   , mTargetRealPath(aPath)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   MOZ_ASSERT(aFileSystem);
   nsCOMPtr<nsIGlobalObject> globalObject =
     do_QueryInterface(aFileSystem->GetWindow());
   if (!globalObject) {
     return;
   }
-  mPromise = new Promise(globalObject);
+  mPromise = Promise::Create(globalObject, aRv);
 }
 
 CreateDirectoryTask::CreateDirectoryTask(
   FileSystemBase* aFileSystem,
   const FileSystemCreateDirectoryParams& aParam,
   FileSystemRequestParent* aParent)
   : FileSystemTaskBase(aFileSystem, aParam, aParent)
 {
--- a/dom/filesystem/CreateDirectoryTask.h
+++ b/dom/filesystem/CreateDirectoryTask.h
@@ -4,28 +4,30 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_CreateDirectoryTask_h
 #define mozilla_dom_CreateDirectoryTask_h
 
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "nsAutoPtr.h"
+#include "mozilla/ErrorResult.h"
 
 namespace mozilla {
 namespace dom {
 
 class Promise;
 
 class CreateDirectoryTask MOZ_FINAL
   : public FileSystemTaskBase
 {
 public:
   CreateDirectoryTask(FileSystemBase* aFileSystem,
-                      const nsAString& aPath);
+                      const nsAString& aPath,
+                      ErrorResult& aRv);
   CreateDirectoryTask(FileSystemBase* aFileSystem,
                       const FileSystemCreateDirectoryParams& aParam,
                       FileSystemRequestParent* aParent);
 
   virtual
   ~CreateDirectoryTask();
 
   already_AddRefed<Promise>
--- a/dom/filesystem/CreateFileTask.cpp
+++ b/dom/filesystem/CreateFileTask.cpp
@@ -22,17 +22,18 @@ namespace mozilla {
 namespace dom {
 
 uint32_t CreateFileTask::sOutputBufferSize = 0;
 
 CreateFileTask::CreateFileTask(FileSystemBase* aFileSystem,
                                const nsAString& aPath,
                                nsIDOMBlob* aBlobData,
                                InfallibleTArray<uint8_t>& aArrayData,
-                               bool replace)
+                               bool replace,
+                               ErrorResult& aRv)
   : FileSystemTaskBase(aFileSystem)
   , mTargetRealPath(aPath)
   , mBlobData(aBlobData)
   , mReplace(replace)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   MOZ_ASSERT(aFileSystem);
   GetOutputBufferSize();
@@ -41,17 +42,17 @@ CreateFileTask::CreateFileTask(FileSyste
     NS_WARN_IF(NS_FAILED(rv));
   }
   mArrayData.SwapElements(aArrayData);
   nsCOMPtr<nsIGlobalObject> globalObject =
     do_QueryInterface(aFileSystem->GetWindow());
   if (!globalObject) {
     return;
   }
-  mPromise = new Promise(globalObject);
+  mPromise = Promise::Create(globalObject, aRv);
 }
 
 CreateFileTask::CreateFileTask(FileSystemBase* aFileSystem,
                        const FileSystemCreateFileParams& aParam,
                        FileSystemRequestParent* aParent)
   : FileSystemTaskBase(aFileSystem, aParam, aParent)
   , mReplace(false)
 {
--- a/dom/filesystem/CreateFileTask.h
+++ b/dom/filesystem/CreateFileTask.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_CreateFileTask_h
 #define mozilla_dom_CreateFileTask_h
 
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "nsAutoPtr.h"
+#include "mozilla/ErrorResult.h"
 
 class nsIDOMBlob;
 class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 
 class DOMFileImpl;
@@ -22,17 +23,18 @@ class Promise;
 class CreateFileTask MOZ_FINAL
   : public FileSystemTaskBase
 {
 public:
   CreateFileTask(FileSystemBase* aFileSystem,
                  const nsAString& aPath,
                  nsIDOMBlob* aBlobData,
                  InfallibleTArray<uint8_t>& aArrayData,
-                 bool replace);
+                 bool replace,
+                 ErrorResult& aRv);
   CreateFileTask(FileSystemBase* aFileSystem,
                  const FileSystemCreateFileParams& aParam,
                  FileSystemRequestParent* aParent);
 
   virtual
   ~CreateFileTask();
 
   already_AddRefed<Promise>
--- a/dom/filesystem/Directory.cpp
+++ b/dom/filesystem/Directory.cpp
@@ -39,20 +39,23 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(Director
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Directory)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Directory)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 // static
 already_AddRefed<Promise>
-Directory::GetRoot(FileSystemBase* aFileSystem)
+Directory::GetRoot(FileSystemBase* aFileSystem, ErrorResult& aRv)
 {
   nsRefPtr<GetFileOrDirectoryTask> task = new GetFileOrDirectoryTask(
-    aFileSystem, EmptyString(), true);
+    aFileSystem, EmptyString(), true, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   FileSystemPermissionRequest::RequestForTask(task);
   return task->GetPromise();
 }
 
 Directory::Directory(FileSystemBase* aFileSystem,
                      const nsAString& aPath)
   : mFileSystem(aFileSystem)
   , mPath(aPath)
@@ -90,17 +93,18 @@ Directory::GetName(nsString& aRetval) co
     return;
   }
 
   aRetval = Substring(mPath,
                       mPath.RFindChar(FileSystemUtils::kSeparatorChar) + 1);
 }
 
 already_AddRefed<Promise>
-Directory::CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions)
+Directory::CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions,
+                      ErrorResult& aRv)
 {
   nsresult error = NS_OK;
   nsString realPath;
   nsRefPtr<nsIDOMBlob> blobData;
   InfallibleTArray<uint8_t> arrayData;
   bool replace = (aOptions.mIfExists == CreateIfExistsMode::Replace);
 
   // Get the file content.
@@ -123,66 +127,76 @@ Directory::CreateFile(const nsAString& a
     }
   }
 
   if (!DOMPathToRealPath(aPath, realPath)) {
     error = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
   }
 
   nsRefPtr<CreateFileTask> task = new CreateFileTask(mFileSystem, realPath,
-    blobData, arrayData, replace);
+    blobData, arrayData, replace, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   task->SetError(error);
   FileSystemPermissionRequest::RequestForTask(task);
   return task->GetPromise();
 }
 
 already_AddRefed<Promise>
-Directory::CreateDirectory(const nsAString& aPath)
+Directory::CreateDirectory(const nsAString& aPath, ErrorResult& aRv)
 {
   nsresult error = NS_OK;
   nsString realPath;
   if (!DOMPathToRealPath(aPath, realPath)) {
     error = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
   }
   nsRefPtr<CreateDirectoryTask> task = new CreateDirectoryTask(
-    mFileSystem, realPath);
+    mFileSystem, realPath, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   task->SetError(error);
   FileSystemPermissionRequest::RequestForTask(task);
   return task->GetPromise();
 }
 
 already_AddRefed<Promise>
-Directory::Get(const nsAString& aPath)
+Directory::Get(const nsAString& aPath, ErrorResult& aRv)
 {
   nsresult error = NS_OK;
   nsString realPath;
   if (!DOMPathToRealPath(aPath, realPath)) {
     error = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
   }
   nsRefPtr<GetFileOrDirectoryTask> task = new GetFileOrDirectoryTask(
-    mFileSystem, realPath, false);
+    mFileSystem, realPath, false, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   task->SetError(error);
   FileSystemPermissionRequest::RequestForTask(task);
   return task->GetPromise();
 }
 
 already_AddRefed<Promise>
-Directory::Remove(const StringOrFileOrDirectory& aPath)
+Directory::Remove(const StringOrFileOrDirectory& aPath, ErrorResult& aRv)
 {
-  return RemoveInternal(aPath, false);
+  return RemoveInternal(aPath, false, aRv);
 }
 
 already_AddRefed<Promise>
-Directory::RemoveDeep(const StringOrFileOrDirectory& aPath)
+Directory::RemoveDeep(const StringOrFileOrDirectory& aPath, ErrorResult& aRv)
 {
-  return RemoveInternal(aPath, true);
+  return RemoveInternal(aPath, true, aRv);
 }
 
 already_AddRefed<Promise>
-Directory::RemoveInternal(const StringOrFileOrDirectory& aPath, bool aRecursive)
+Directory::RemoveInternal(const StringOrFileOrDirectory& aPath, bool aRecursive,
+                          ErrorResult& aRv)
 {
   nsresult error = NS_OK;
   nsString realPath;
   nsCOMPtr<nsIDOMFile> file;
 
   // Check and get the target path.
 
   if (aPath.IsFile()) {
@@ -206,17 +220,20 @@ Directory::RemoveInternal(const StringOr
   // The target must be a descendant of this directory.
   if (!FileSystemUtils::IsDescendantPath(mPath, realPath)) {
     error = NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
   }
 
 parameters_check_done:
 
   nsRefPtr<RemoveTask> task = new RemoveTask(mFileSystem, mPath, file, realPath,
-    aRecursive);
+    aRecursive, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   task->SetError(error);
   FileSystemPermissionRequest::RequestForTask(task);
   return task->GetPromise();
 }
 
 FileSystemBase*
 Directory::GetFileSystem() const
 {
--- a/dom/filesystem/Directory.h
+++ b/dom/filesystem/Directory.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Directory_h
 #define mozilla_dom_Directory_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMFile.h"
 #include "nsPIDOMWindow.h"
 #include "nsWrapperCache.h"
 
 // Resolve the name collision of Microsoft's API name with macros defined in
@@ -40,45 +41,46 @@ class Directory MOZ_FINAL
   , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Directory)
 
 public:
   static already_AddRefed<Promise>
-  GetRoot(FileSystemBase* aFileSystem);
+  GetRoot(FileSystemBase* aFileSystem, ErrorResult& aRv);
 
   Directory(FileSystemBase* aFileSystem, const nsAString& aPath);
 
   // ========= Begin WebIDL bindings. ===========
 
   nsPIDOMWindow*
   GetParentObject() const;
 
   virtual JSObject*
   WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   void
   GetName(nsString& aRetval) const;
 
   already_AddRefed<Promise>
-  CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions);
+  CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions,
+             ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  CreateDirectory(const nsAString& aPath);
+  CreateDirectory(const nsAString& aPath, ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  Get(const nsAString& aPath);
+  Get(const nsAString& aPath, ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  Remove(const StringOrFileOrDirectory& aPath);
+  Remove(const StringOrFileOrDirectory& aPath, ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  RemoveDeep(const StringOrFileOrDirectory& aPath);
+  RemoveDeep(const StringOrFileOrDirectory& aPath, ErrorResult& aRv);
 
   // =========== End WebIDL bindings.============
 
   FileSystemBase*
   GetFileSystem() const;
 private:
   ~Directory();
 
@@ -88,17 +90,18 @@ private:
   /*
    * Convert relative DOM path to the absolute real path.
    * @return true if succeed. false if the DOM path is invalid.
    */
   bool
   DOMPathToRealPath(const nsAString& aPath, nsAString& aRealPath) const;
 
   already_AddRefed<Promise>
-  RemoveInternal(const StringOrFileOrDirectory& aPath, bool aRecursive);
+  RemoveInternal(const StringOrFileOrDirectory& aPath, bool aRecursive,
+                 ErrorResult& aRv);
 
   nsRefPtr<FileSystemBase> mFileSystem;
   nsString mPath;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/filesystem/GetFileOrDirectoryTask.cpp
+++ b/dom/filesystem/GetFileOrDirectoryTask.cpp
@@ -16,29 +16,30 @@
 #include "nsStringGlue.h"
 
 namespace mozilla {
 namespace dom {
 
 GetFileOrDirectoryTask::GetFileOrDirectoryTask(
   FileSystemBase* aFileSystem,
   const nsAString& aTargetPath,
-  bool aDirectoryOnly)
+  bool aDirectoryOnly,
+  ErrorResult& aRv)
   : FileSystemTaskBase(aFileSystem)
   , mTargetRealPath(aTargetPath)
   , mIsDirectory(aDirectoryOnly)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   MOZ_ASSERT(aFileSystem);
   nsCOMPtr<nsIGlobalObject> globalObject =
     do_QueryInterface(aFileSystem->GetWindow());
   if (!globalObject) {
     return;
   }
-  mPromise = new Promise(globalObject);
+  mPromise = Promise::Create(globalObject, aRv);
 }
 
 GetFileOrDirectoryTask::GetFileOrDirectoryTask(
   FileSystemBase* aFileSystem,
   const FileSystemGetFileOrDirectoryParams& aParam,
   FileSystemRequestParent* aParent)
   : FileSystemTaskBase(aFileSystem, aParam, aParent)
   , mIsDirectory(false)
--- a/dom/filesystem/GetFileOrDirectoryTask.h
+++ b/dom/filesystem/GetFileOrDirectoryTask.h
@@ -4,30 +4,32 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_GetFileOrDirectory_h
 #define mozilla_dom_GetFileOrDirectory_h
 
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "nsAutoPtr.h"
+#include "mozilla/ErrorResult.h"
 
 namespace mozilla {
 namespace dom {
 
 class DOMFileImpl;
 
 class GetFileOrDirectoryTask MOZ_FINAL
   : public FileSystemTaskBase
 {
 public:
   // If aDirectoryOnly is set, we should ensure that the target is a directory.
   GetFileOrDirectoryTask(FileSystemBase* aFileSystem,
                          const nsAString& aTargetPath,
-                         bool aDirectoryOnly);
+                         bool aDirectoryOnly,
+                         ErrorResult& aRv);
   GetFileOrDirectoryTask(FileSystemBase* aFileSystem,
                          const FileSystemGetFileOrDirectoryParams& aParam,
                          FileSystemRequestParent* aParent);
 
   virtual
   ~GetFileOrDirectoryTask();
 
   already_AddRefed<Promise>
--- a/dom/filesystem/RemoveTask.cpp
+++ b/dom/filesystem/RemoveTask.cpp
@@ -16,32 +16,33 @@
 
 namespace mozilla {
 namespace dom {
 
 RemoveTask::RemoveTask(FileSystemBase* aFileSystem,
                        const nsAString& aDirPath,
                        nsIDOMFile* aTargetFile,
                        const nsAString& aTargetPath,
-                       bool aRecursive)
+                       bool aRecursive,
+                       ErrorResult& aRv)
   : FileSystemTaskBase(aFileSystem)
   , mDirRealPath(aDirPath)
   , mTargetFile(aTargetFile)
   , mTargetRealPath(aTargetPath)
   , mRecursive(aRecursive)
   , mReturnValue(false)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   MOZ_ASSERT(aFileSystem);
   nsCOMPtr<nsIGlobalObject> globalObject =
     do_QueryInterface(aFileSystem->GetWindow());
   if (!globalObject) {
     return;
   }
-  mPromise = new Promise(globalObject);
+  mPromise = Promise::Create(globalObject, aRv);
 }
 
 RemoveTask::RemoveTask(FileSystemBase* aFileSystem,
                        const FileSystemRemoveParams& aParam,
                        FileSystemRequestParent* aParent)
   : FileSystemTaskBase(aFileSystem, aParam, aParent)
   , mRecursive(false)
   , mReturnValue(false)
--- a/dom/filesystem/RemoveTask.h
+++ b/dom/filesystem/RemoveTask.h
@@ -4,31 +4,33 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_RemoveTask_h
 #define mozilla_dom_RemoveTask_h
 
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "nsAutoPtr.h"
+#include "mozilla/ErrorResult.h"
 
 namespace mozilla {
 namespace dom {
 
 class Promise;
 
 class RemoveTask MOZ_FINAL
   : public FileSystemTaskBase
 {
 public:
   RemoveTask(FileSystemBase* aFileSystem,
              const nsAString& aDirPath,
              nsIDOMFile* aTargetFile,
              const nsAString& aTargetPath,
-             bool aRecursive);
+             bool aRecursive,
+             ErrorResult& aRv);
   RemoveTask(FileSystemBase* aFileSystem,
              const FileSystemRemoveParams& aParam,
              FileSystemRequestParent* aParent);
 
   virtual
   ~RemoveTask();
 
   already_AddRefed<Promise>
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -2,19 +2,21 @@
 /* vim: set ts=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 "mozilla/dom/Promise.h"
 
 #include "jsfriendapi.h"
+#include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/OwningNonNull.h"
 #include "mozilla/dom/PromiseBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/Preferences.h"
 #include "PromiseCallback.h"
 #include "PromiseNativeHandler.h"
 #include "PromiseWorkerProxy.h"
 #include "nsContentUtils.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
@@ -256,17 +258,18 @@ public:
   }
 
 protected:
   void
   RunInternal()
   {
     NS_ASSERT_OWNINGTHREAD(ThenableResolverMixin);
     ThreadsafeAutoJSContext cx;
-    JS::Rooted<JSObject*> wrapper(cx, mPromise->GetOrCreateWrapper(cx));
+    JS::Rooted<JSObject*> wrapper(cx, mPromise->GetWrapper());
+    MOZ_ASSERT(wrapper); // It was preserved!
     if (!wrapper) {
       return;
     }
     JSAutoCompartment ac(cx, wrapper);
 
     JS::Rooted<JSObject*> resolveFunc(cx,
       mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Resolve));
 
@@ -429,41 +432,39 @@ Promise::~Promise()
 }
 
 JSObject*
 Promise::WrapObject(JSContext* aCx)
 {
   return PromiseBinding::Wrap(aCx, this);
 }
 
-JSObject*
-Promise::GetOrCreateWrapper(JSContext* aCx)
+already_AddRefed<Promise>
+Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
 {
-  if (JSObject* wrapper = GetWrapper()) {
-    return wrapper;
+  AutoJSAPI jsapi;
+  if (!jsapi.Init(aGlobal)) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
+  JSContext* cx = jsapi.cx();
 
-  nsIGlobalObject* global = GetParentObject();
-  MOZ_ASSERT(global);
+  nsRefPtr<Promise> p = new Promise(aGlobal);
 
-  JS::Rooted<JSObject*> scope(aCx, global->GetGlobalJSObject());
-  if (!scope) {
-    JS_ReportError(aCx, "can't get scope");
+  JS::Rooted<JS::Value> ignored(cx);
+  if (!WrapNewBindingObject(cx, p, &ignored)) {
+    JS_ClearPendingException(cx);
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return nullptr;
   }
 
-  JSAutoCompartment ac(aCx, scope);
+  // Need the .get() bit here to get template deduction working right
+  dom::PreserveWrapper(p.get());
 
-  JS::Rooted<JS::Value> val(aCx);
-  if (!WrapNewBindingObject(aCx, this, &val)) {
-    MOZ_ASSERT(JS_IsExceptionPending(aCx));
-    return nullptr;
-  }
-
-  return GetWrapper();
+  return p.forget();
 }
 
 void
 Promise::MaybeResolve(JSContext* aCx,
                       JS::Handle<JS::Value> aValue)
 {
   MaybeResolveInternal(aCx, aValue);
 }
@@ -601,17 +602,20 @@ Promise::Constructor(const GlobalObject&
 
   nsCOMPtr<nsIGlobalObject> global;
   global = do_QueryInterface(aGlobal.GetAsSupports());
   if (!global) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   JS::Rooted<JSObject*> resolveFunc(cx,
                                     CreateFunction(cx, aGlobal.Get(), promise,
                                                    PromiseCallback::Resolve));
   if (!resolveFunc) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
@@ -669,17 +673,20 @@ Promise::Resolve(const GlobalObject& aGl
 
   return Resolve(global, aGlobal.Context(), aValue, aRv);
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
                  JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise = new Promise(aGlobal);
+  nsRefPtr<Promise> promise = Create(aGlobal, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   promise->MaybeResolveInternal(aCx, aValue);
   return promise.forget();
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Reject(const GlobalObject& aGlobal,
                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
@@ -693,27 +700,33 @@ Promise::Reject(const GlobalObject& aGlo
 
   return Reject(global, aGlobal.Context(), aValue, aRv);
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise = new Promise(aGlobal);
+  nsRefPtr<Promise> promise = Create(aGlobal, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   promise->MaybeRejectInternal(aCx, aValue);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 Promise::Then(JSContext* aCx, AnyCallback* aResolveCallback,
-              AnyCallback* aRejectCallback)
+              AnyCallback* aRejectCallback, ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise = new Promise(GetParentObject());
+  nsRefPtr<Promise> promise = Create(GetParentObject(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
 
   nsRefPtr<PromiseCallback> resolveCb =
     PromiseCallback::Factory(promise, global, aResolveCallback,
                              PromiseCallback::Resolve);
 
   nsRefPtr<PromiseCallback> rejectCb =
@@ -721,20 +734,20 @@ Promise::Then(JSContext* aCx, AnyCallbac
                              PromiseCallback::Reject);
 
   AppendCallbacks(resolveCb, rejectCb);
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
-Promise::Catch(JSContext* aCx, AnyCallback* aRejectCallback)
+Promise::Catch(JSContext* aCx, AnyCallback* aRejectCallback, ErrorResult& aRv)
 {
   nsRefPtr<AnyCallback> resolveCb;
-  return Then(aCx, resolveCb, aRejectCallback);
+  return Then(aCx, resolveCb, aRejectCallback, aRv);
 }
 
 /**
  * The CountdownHolder class encapsulates Promise.all countdown functions and
  * the countdown holder parts of the Promises spec. It maintains the result
  * array and AllResolveHandlers use SetValue() to set the array indices.
  */
 class CountdownHolder MOZ_FINAL : public nsISupports
@@ -887,17 +900,20 @@ Promise::All(const GlobalObject& aGlobal
     if (!empty) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return nullptr;
     }
     JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*empty));
     return Promise::Resolve(aGlobal, value, aRv);
   }
 
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   nsRefPtr<CountdownHolder> holder =
     new CountdownHolder(aGlobal, promise, aIterable.Length());
 
   JS::Rooted<JSObject*> obj(cx, JS::CurrentGlobalOrNull(cx));
   if (!obj) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
@@ -937,17 +953,20 @@ Promise::Race(const GlobalObject& aGloba
   JSContext* cx = aGlobal.Context();
 
   JS::Rooted<JSObject*> obj(cx, JS::CurrentGlobalOrNull(cx));
   if (!obj) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<PromiseCallback> resolveCb =
     new ResolvePromiseCallback(promise, obj);
 
   nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise, obj);
 
   for (uint32_t i = 0; i < aIterable.Length(); ++i) {
     JS::Rooted<JS::Value> value(cx, aIterable.ElementAt(i));
@@ -1016,20 +1035,18 @@ Promise::RunTask()
   nsTArray<nsRefPtr<PromiseCallback>> callbacks;
   callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
                                             : mRejectCallbacks);
   mResolveCallbacks.Clear();
   mRejectCallbacks.Clear();
 
   ThreadsafeAutoJSContext cx;
   JS::Rooted<JS::Value> value(cx, mResult);
-  JS::Rooted<JSObject*> wrapper(cx, GetOrCreateWrapper(cx));
-  if (!wrapper) {
-    return;
-  }
+  JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
+  MOZ_ASSERT(wrapper); // We preserved it
 
   JSAutoCompartment ac(cx, wrapper);
   if (!MaybeWrapValue(cx, &value)) {
     return;
   }
 
   for (uint32_t i = 0; i < callbacks.Length(); ++i) {
     callbacks[i]->Call(cx, value);
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -67,17 +67,22 @@ class Promise MOZ_FINAL : public nsISupp
   friend class WrapperPromiseCallback;
 
   ~Promise();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
 
-  Promise(nsIGlobalObject* aGlobal);
+  // Promise creation tries to create a JS reflector for the Promise, so is
+  // fallible.  Furthermore, we don't want to do JS-wrapping on a 0-refcount
+  // object, so we addref before doing that and return the addrefed pointer
+  // here.
+  static already_AddRefed<Promise>
+  Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
 
   typedef void (Promise::*MaybeFunc)(JSContext* aCx,
                                      JS::Handle<JS::Value> aValue);
 
   void MaybeResolve(JSContext* aCx,
                     JS::Handle<JS::Value> aValue);
   void MaybeReject(JSContext* aCx,
                    JS::Handle<JS::Value> aValue);
@@ -134,32 +139,36 @@ public:
          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   already_AddRefed<Promise>
   Then(JSContext* aCx, AnyCallback* aResolveCallback,
-       AnyCallback* aRejectCallback);
+       AnyCallback* aRejectCallback, ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  Catch(JSContext* aCx, AnyCallback* aRejectCallback);
+  Catch(JSContext* aCx, AnyCallback* aRejectCallback, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   All(const GlobalObject& aGlobal,
       const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Race(const GlobalObject& aGlobal,
        const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
 
   void AppendNativeHandler(PromiseNativeHandler* aRunnable);
 
 private:
+  // Do NOT call this unless you're Promise::Create.  I wish we could enforce
+  // that from inside this class too, somehow.
+  Promise(nsIGlobalObject* aGlobal);
+
   friend class PromiseDebugging;
 
   enum PromiseState {
     Pending,
     Resolved,
     Rejected
   };
 
@@ -214,28 +223,21 @@ private:
   void ResolveInternal(JSContext* aCx,
                        JS::Handle<JS::Value> aValue,
                        PromiseTaskSync aSync = AsyncTask);
 
   void RejectInternal(JSContext* aCx,
                       JS::Handle<JS::Value> aValue,
                       PromiseTaskSync aSync = AsyncTask);
 
-  // Helper methods for using Promises from C++
-  JSObject* GetOrCreateWrapper(JSContext* aCx);
-
   template <typename T>
   void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
     ThreadsafeAutoJSContext cx;
-
-    JSObject* wrapper = GetOrCreateWrapper(cx);
-    if (!wrapper) {
-      HandleException(cx);
-      return;
-    }
+    JSObject* wrapper = GetWrapper();
+    MOZ_ASSERT(wrapper); // We preserved it!
 
     JSAutoCompartment ac(cx, wrapper);
     JS::Rooted<JS::Value> val(cx);
     if (!ToJSValue(cx, aArgument, &val)) {
       HandleException(cx);
       return;
     }
 
--- a/dom/promise/PromiseWorkerProxy.h
+++ b/dom/promise/PromiseWorkerProxy.h
@@ -21,17 +21,20 @@ class WorkerPrivate;
 // A proxy to catch the resolved/rejected Promise's result from the main thread
 // and resolve/reject that on the worker thread eventually.
 //
 // How to use:
 //
 //   1. Create a Promise on the worker thread and return it to the content
 //      script:
 //
-//        nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+//        nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+//        if (aRv.Failed()) {
+//          return nullptr;
+//        }
 //        // Pass |promise| around to the WorkerMainThreadRunnable
 //        return promise.forget();
 //
 //   2. In your WorkerMainThreadRunnable's ctor, create a PromiseWorkerProxy
 //      which holds a nsRefPtr<Promise> to the Promise created at #1.
 //
 //   3. In your WorkerMainThreadRunnable::MainThreadRun(), obtain a Promise on
 //      the main thread and call its AppendNativeHandler(PromiseNativeHandler*)
--- a/dom/src/notification/Notification.cpp
+++ b/dom/src/notification/Notification.cpp
@@ -739,17 +739,20 @@ Notification::Get(const GlobalObject& aG
   nsresult rv;
   nsCOMPtr<nsINotificationStorage> notificationStorage =
     do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID, &rv);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
   nsCOMPtr<nsINotificationStorageCallback> callback =
     new NotificationStorageCallback(aGlobal, window, promise);
   nsString tag = aFilter.mTag.WasPassed() ?
                  aFilter.mTag.Value() :
                  EmptyString();
   aRv = notificationStorage->Get(origin, tag, callback);
   if (aRv.Failed()) {
     return nullptr;
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -237,24 +237,27 @@ Telephony::HasDialingCall()
     }
   }
 
   return false;
 }
 
 already_AddRefed<Promise>
 Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
-                        bool aEmergency)
+                        bool aEmergency, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   if (!global) {
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = new Promise(global);
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   if (!IsValidNumber(aNumber) || !IsValidServiceId(aServiceId)) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return promise.forget();
   }
 
   // We only support one outgoing call at a time.
   if (HasDialingCall()) {
@@ -366,29 +369,31 @@ NS_IMPL_ADDREF_INHERITED(Telephony, DOME
 NS_IMPL_RELEASE_INHERITED(Telephony, DOMEventTargetHelper)
 
 NS_IMPL_ISUPPORTS(Telephony::Listener, nsITelephonyListener)
 NS_IMPL_ISUPPORTS(Telephony::Callback, nsITelephonyCallback)
 
 // Telephony WebIDL
 
 already_AddRefed<Promise>
-Telephony::Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId)
+Telephony::Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId,
+                ErrorResult& aRv)
 {
   uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
-  nsRefPtr<Promise> promise = DialInternal(serviceId, aNumber, false);
+  nsRefPtr<Promise> promise = DialInternal(serviceId, aNumber, false, aRv);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 Telephony::DialEmergency(const nsAString& aNumber,
-                         const Optional<uint32_t>& aServiceId)
+                         const Optional<uint32_t>& aServiceId,
+                         ErrorResult& aRv)
 {
   uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
-  nsRefPtr<Promise> promise = DialInternal(serviceId, aNumber, true);
+  nsRefPtr<Promise> promise = DialInternal(serviceId, aNumber, true, aRv);
   return promise.forget();
 }
 
 void
 Telephony::StartTone(const nsAString& aDTMFChar,
                      const Optional<uint32_t>& aServiceId,
                      ErrorResult& aRv)
 {
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -65,20 +65,22 @@ public:
   }
 
   // WrapperCache
   virtual JSObject*
   WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // WebIDL
   already_AddRefed<Promise>
-  Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId);
+  Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId,
+       ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  DialEmergency(const nsAString& aNumber, const Optional<uint32_t>& aServiceId);
+  DialEmergency(const nsAString& aNumber, const Optional<uint32_t>& aServiceId,
+                ErrorResult& aRv);
 
   void
   StartTone(const nsAString& aDTMFChar, const Optional<uint32_t>& aServiceId,
             ErrorResult& aRv);
 
   void
   StopTone(const Optional<uint32_t>& aServiceId, ErrorResult& aRv);
 
@@ -162,17 +164,18 @@ private:
 
   uint32_t
   ProvidedOrDefaultServiceId(const Optional<uint32_t>& aServiceId);
 
   bool
   HasDialingCall();
 
   already_AddRefed<Promise>
-  DialInternal(uint32_t aServiceId, const nsAString& aNumber, bool aEmergency);
+  DialInternal(uint32_t aServiceId, const nsAString& aNumber, bool aEmergency,
+               ErrorResult& aRv);
 
   already_AddRefed<TelephonyCallId>
   CreateCallId(const nsAString& aNumber,
                uint16_t aNumberPresentation = nsITelephonyService::CALL_PRESENTATION_ALLOWED,
                const nsAString& aName = EmptyString(),
                uint16_t aNamePresentation = nsITelephonyService::CALL_PRESENTATION_ALLOWED);
 
   already_AddRefed<TelephonyCall>
--- a/dom/webidl/DeviceStorage.webidl
+++ b/dom/webidl/DeviceStorage.webidl
@@ -77,11 +77,11 @@ interface DeviceStorage : EventTarget {
   // Indicates if the storage area denoted by storageName is capable of
   // being formatted.
   readonly attribute boolean canBeFormatted;
 
   // Determines if this storage area is the one which will be used by default
   // for storing new files.
   readonly attribute boolean default;
 
-  [NewObject]
+  [NewObject, Throws]
   Promise getRoot();
 };
--- a/dom/webidl/Directory.webidl
+++ b/dom/webidl/Directory.webidl
@@ -32,72 +32,72 @@ interface Directory {
    * a new file to replace the existing one;
    * If 'ifExists' is 'replace', the path already exists, but is a directory,
    * createFile must fail.
    * Otherwise, if no other error occurs, createFile will create a new file.
    * The 'data' property contains the new file's content.
    * @return If succeeds, the promise is resolved with the new created
    * File object. Otherwise, rejected with a DOM error.
    */
-  [NewObject]
+  [NewObject, Throws]
   // Promise<File>
   Promise createFile(DOMString path, optional CreateFileOptions options);
 
   /*
    * Creates a descendent directory. This method will create any intermediate
    * directories specified by the path segments.
    *
    * @param path The relative path of the new directory to current directory.
    * If path exists, createDirectory must fail.
    * @return If succeeds, the promise is resolved with the new created
    * Directory object. Otherwise, rejected with a DOM error.
    */
-  [NewObject]
+  [NewObject, Throws]
   // Promise<Directory>
   Promise createDirectory(DOMString path);
 
   /*
    * Gets a descendent file or directory with the given path.
    *
    * @param path The descendent entry's relative path to current directory.
    * @return If the path exists and no error occurs, the promise is resolved
    * with a File or Directory object, depending on the entry's type. Otherwise,
    * rejected with a DOM error.
    */
-  [NewObject]
+  [NewObject, Throws]
   // Promise<(File or Directory)>
   Promise get(DOMString path);
 
   /*
    * Deletes a file or an empty directory. The target must be a descendent of
    * current directory.
    * @param path If a DOM string is passed, it is the relative path of the
    * target. Otherwise, the File or Directory object of the target should be
    * passed.
    * @return If the target is a non-empty directory, or if deleting the target
    * fails, the promise is rejected with a DOM error. If the target did not
    * exist, the promise is resolved with boolean false. If the target did exist
    * and was successfully deleted, the promise is resolved with boolean true.
    */
-  [NewObject]
+  [NewObject, Throws]
   // Promise<boolean>
   Promise remove((DOMString or File or Directory) path);
 
   /*
    * Deletes a file or a directory recursively. The target should be a
    * descendent of current directory.
    * @param path If a DOM string is passed, it is the relative path of the
    * target. Otherwise, the File or Directory object of the target should be
    * passed.
    * @return If the target exists, but deleting the target fails, the promise is
    * rejected with a DOM error. If the target did not exist, the promise is
    * resolved with boolean false. If the target did exist and was successfully
    * deleted, the promise is resolved with boolean true.
    */
-  [NewObject]
+  [NewObject, Throws]
   // Promise<boolean>
   Promise removeDeep((DOMString or File or Directory) path);
 };
 
 enum CreateIfExistsMode { "replace", "fail" };
 
 dictionary CreateFileOptions {
   CreateIfExistsMode ifExists = "fail";
--- a/dom/webidl/MediaKeySession.webidl
+++ b/dom/webidl/MediaKeySession.webidl
@@ -25,19 +25,19 @@ interface MediaKeySession : EventTarget 
 
   readonly attribute unrestricted double expiration;
 
   // Promise<any>
   readonly attribute Promise closed;
 
   // session operations
   //Promise<any>
-  [NewObject]
+  [NewObject, Throws]
   Promise update(Uint8Array response);
 
   // Promise<any>
-  [NewObject]
+  [NewObject, Throws]
   Promise close();
 
   // Promise<any>
-  [NewObject]
+  [NewObject, Throws]
   Promise remove();
 };
--- a/dom/webidl/MediaKeys.webidl
+++ b/dom/webidl/MediaKeys.webidl
@@ -13,25 +13,25 @@
 enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" };
 enum SessionType { "temporary", "persistent" };
 
 [Pref="media.eme.enabled"]
 interface MediaKeys {
   readonly attribute DOMString keySystem;
 
   // Promise<MediaKeySession>
-  [NewObject]
+  [NewObject, Throws]
   Promise createSession(DOMString initDataType, Uint8Array initData, optional SessionType sessionType = "temporary");
 
   // Promise<MediaKeySession>
-  [NewObject]
+  [NewObject, Throws]
   Promise loadSession(DOMString sessionId);
 
   // Promise<any>
-  [NewObject]
+  [NewObject, Throws]
   Promise setServerCertificate(Uint8Array serverCertificate);
 
   // Promise<MediaKeys>
   [Throws,NewObject]
   static Promise create(DOMString keySystem);
   static IsTypeSupportedResult isTypeSupported(DOMString keySystem, optional DOMString initDataType, optional DOMString contentType, optional DOMString capability);
 
 };
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -78,17 +78,17 @@ interface NavigatorContentUtils {
 [NoInterfaceObject]
 interface NavigatorStorageUtils {
   // NOT IMPLEMENTED
   //void yieldForStorageUpdates();
 };
 
 [NoInterfaceObject]
 interface NavigatorFeatures {
-  [CheckPermissions="feature-detection"]
+  [CheckPermissions="feature-detection", Throws]
   Promise getFeature(DOMString name);
 };
 
 // Things that definitely need to be in the spec and and are not for some
 // reason.  See https://www.w3.org/Bugs/Public/show_bug.cgi?id=22406
 partial interface Navigator {
   [Throws]
   readonly attribute MimeTypeArray mimeTypes;
--- a/dom/webidl/Promise.webidl
+++ b/dom/webidl/Promise.webidl
@@ -27,21 +27,21 @@ interface Promise {
   // first.
   [NewObject, Throws]
   static Promise resolve(optional any value);
   [NewObject, Throws]
   static Promise reject(optional any value);
 
   // The [TreatNonCallableAsNull] annotation is required since then() should do
   // nothing instead of throwing errors when non-callable arguments are passed.
-  [NewObject]
+  [NewObject, Throws]
   Promise then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
                [TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
 
-  [NewObject]
+  [NewObject, Throws]
   Promise catch([TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
 
   [NewObject, Throws]
   static Promise all(sequence<any> iterable);
 
   [NewObject, Throws]
   static Promise race(sequence<any> iterable);
 };
--- a/dom/webidl/ServiceWorkerContainer.webidl
+++ b/dom/webidl/ServiceWorkerContainer.webidl
@@ -14,16 +14,17 @@ interface ServiceWorkerContainer {
   // https://github.com/slightlyoff/ServiceWorker/issues/198
   // and discussion at https://etherpad.mozilla.org/serviceworker07apr
   [Unforgeable] readonly attribute ServiceWorker? installing;
   [Unforgeable] readonly attribute ServiceWorker? waiting;
   [Unforgeable] readonly attribute ServiceWorker? active;
   [Unforgeable] readonly attribute ServiceWorker? controller;
 
   // Promise<ServiceWorker>
+  [Throws]
   readonly attribute Promise ready;
 
   // Promise<sequence<ServiceWorker>?>
   [Throws]
   Promise getAll();
 
   // Promise<ServiceWorker>
   [Throws]
--- a/dom/webidl/SubtleCrypto.webidl
+++ b/dom/webidl/SubtleCrypto.webidl
@@ -127,44 +127,54 @@ interface CryptoKeyPair {
 
 typedef DOMString KeyFormat;
 typedef (ArrayBufferView or ArrayBuffer) CryptoOperationData;
 typedef (ArrayBufferView or ArrayBuffer) KeyData;
 typedef (object or DOMString) AlgorithmIdentifier;
 
 [Pref="dom.webcrypto.enabled"]
 interface SubtleCrypto {
+  [Throws]
   Promise encrypt(AlgorithmIdentifier algorithm,
                   CryptoKey key,
                   CryptoOperationData data);
+  [Throws]
   Promise decrypt(AlgorithmIdentifier algorithm,
                   CryptoKey key,
                   CryptoOperationData data);
+  [Throws]
   Promise sign(AlgorithmIdentifier algorithm,
                CryptoKey key,
                CryptoOperationData data);
+  [Throws]
   Promise verify(AlgorithmIdentifier algorithm,
                  CryptoKey key,
                  CryptoOperationData signature,
                  CryptoOperationData data);
+  [Throws]
   Promise digest(AlgorithmIdentifier algorithm,
                  CryptoOperationData data);
 
+  [Throws]
   Promise generateKey(AlgorithmIdentifier algorithm,
                       boolean extractable,
                       sequence<KeyUsage> keyUsages );
+  [Throws]
   Promise deriveKey(AlgorithmIdentifier algorithm,
                     CryptoKey baseKey,
                     AlgorithmIdentifier derivedKeyType,
                     boolean extractable,
                     sequence<KeyUsage> keyUsages );
+  [Throws]
   Promise deriveBits(AlgorithmIdentifier algorithm,
                      CryptoKey baseKey,
                      unsigned long length);
 
+  [Throws]
   Promise importKey(KeyFormat format,
                     KeyData keyData,
                     AlgorithmIdentifier algorithm,
                     boolean extractable,
                     sequence<KeyUsage> keyUsages );
+  [Throws]
   Promise exportKey(KeyFormat format, CryptoKey key);
 };
 
--- a/dom/webidl/Telephony.webidl
+++ b/dom/webidl/Telephony.webidl
@@ -12,19 +12,21 @@ interface Telephony : EventTarget {
    * the implementation MUST use the default service.
    *
    * Possible values of |serviceId| are 0 ~ (number of services - 1), which is
    * simply the index of a service. Get number of services by acquiring
    * |navigator.mozMobileConnections.length|.
    */
 
   // Promise<TelephonyCall>
+  [Throws]
   Promise dial(DOMString number, optional unsigned long serviceId);
 
   // Promise<TelephonyCall>
+  [Throws]
   Promise dialEmergency(DOMString number, optional unsigned long serviceId);
 
   [Throws]
   void startTone(DOMString tone, optional unsigned long serviceId);
 
   [Throws]
   void stopTone(optional unsigned long serviceId);
 
--- a/dom/workers/DataStore.cpp
+++ b/dom/workers/DataStore.cpp
@@ -474,17 +474,20 @@ already_AddRefed<Promise>
 WorkerDataStore::Get(JSContext* aCx,
                      const Sequence<OwningStringOrUnsignedLong>& aId,
                      ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<DataStoreGetRunnable> runnable =
     new DataStoreGetRunnable(workerPrivate,
                              mBackingStore,
                              promise,
                              aId,
                              aRv);
   runnable->Dispatch(aCx);
@@ -498,17 +501,20 @@ WorkerDataStore::Put(JSContext* aCx,
                      const StringOrUnsignedLong& aId,
                      const nsAString& aRevisionId,
                      ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<DataStorePutRunnable> runnable =
     new DataStorePutRunnable(workerPrivate,
                              mBackingStore,
                              promise,
                              aCx,
                              aObj,
                              aId,
@@ -525,17 +531,20 @@ WorkerDataStore::Add(JSContext* aCx,
                      const Optional<StringOrUnsignedLong>& aId,
                      const nsAString& aRevisionId,
                      ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<DataStoreAddRunnable> runnable =
     new DataStoreAddRunnable(workerPrivate,
                              mBackingStore,
                              promise,
                              aCx,
                              aObj,
                              aId,
@@ -551,17 +560,20 @@ WorkerDataStore::Remove(JSContext* aCx,
                         const StringOrUnsignedLong& aId,
                         const nsAString& aRevisionId,
                         ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<DataStoreRemoveRunnable> runnable =
     new DataStoreRemoveRunnable(workerPrivate,
                                 mBackingStore,
                                 promise,
                                 aId,
                                 aRevisionId,
                                 aRv);
@@ -574,17 +586,20 @@ already_AddRefed<Promise>
 WorkerDataStore::Clear(JSContext* aCx,
                        const nsAString& aRevisionId,
                        ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<DataStoreClearRunnable> runnable =
     new DataStoreClearRunnable(workerPrivate,
                                mBackingStore,
                                promise,
                                aRevisionId,
                                aRv);
   runnable->Dispatch(aCx);
@@ -645,17 +660,20 @@ protected:
 
 already_AddRefed<Promise>
 WorkerDataStore::GetLength(JSContext* aCx, ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<DataStoreGetLengthRunnable> runnable =
     new DataStoreGetLengthRunnable(workerPrivate,
                                    mBackingStore,
                                    promise,
                                    aRv);
   runnable->Dispatch(aCx);
 
--- a/dom/workers/DataStoreCursor.cpp
+++ b/dom/workers/DataStoreCursor.cpp
@@ -142,17 +142,20 @@ WorkerDataStoreCursor::GetStore(JSContex
 
 already_AddRefed<Promise>
 WorkerDataStoreCursor::Next(JSContext* aCx, ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<DataStoreCursorNextRunnable> runnable =
     new DataStoreCursorNextRunnable(workerPrivate,
                                     mBackingCursor,
                                     promise,
                                     aRv);
   runnable->Dispatch(aCx);
 
--- a/dom/workers/Navigator.cpp
+++ b/dom/workers/Navigator.cpp
@@ -256,17 +256,20 @@ already_AddRefed<Promise>
 WorkerNavigator::GetDataStores(JSContext* aCx,
                                const nsAString& aName,
                                ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
 
-  nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
+  nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   nsRefPtr<NavigatorGetDataStoresRunnable> runnable =
     new NavigatorGetDataStoresRunnable(workerPrivate, promise, aName, aRv);
   runnable->Dispatch(aCx);
 
   return promise.forget();
 }
 
--- a/dom/workers/ServiceWorkerContainer.cpp
+++ b/dom/workers/ServiceWorkerContainer.cpp
@@ -114,22 +114,21 @@ already_AddRefed<Promise>
 ServiceWorkerContainer::GetAll(ErrorResult& aRv)
 {
   // FIXME(nsm): Bug 1002571
   aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   return nullptr;
 }
 
 already_AddRefed<Promise>
-ServiceWorkerContainer::Ready()
+ServiceWorkerContainer::GetReady(ErrorResult& aRv)
 {
   // FIXME(nsm): Bug 1025077
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
-  nsRefPtr<Promise> promise = new Promise(global);
-  return promise.forget();
+  return Promise::Create(global, aRv);
 }
 
 // XXXnsm, maybe this can be optimized to only add when a event handler is
 // registered.
 void
 ServiceWorkerContainer::StartListeningForEvents()
 {
   nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
--- a/dom/workers/ServiceWorkerContainer.h
+++ b/dom/workers/ServiceWorkerContainer.h
@@ -68,17 +68,17 @@ public:
 
   already_AddRefed<ServiceWorker>
   GetController();
 
   already_AddRefed<Promise>
   GetAll(ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  Ready();
+  GetReady(ErrorResult& aRv);
 
   nsIURI*
   GetDocumentURI() const
   {
     return mWindow->GetDocumentURI();
   }
 
   // Testing only.
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -450,17 +450,21 @@ ServiceWorkerManager::Register(nsIDOMWin
   MOZ_ASSERT(!nsContentUtils::IsCallerChrome());
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
   if (!window) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIGlobalObject> sgo = do_QueryInterface(window);
-  nsRefPtr<Promise> promise = new Promise(sgo);
+  ErrorResult result;
+  nsRefPtr<Promise> promise = Promise::Create(sgo, result);
+  if (result.Failed()) {
+    return result.ErrorCode();
+  }
 
   nsCOMPtr<nsIURI> documentURI = window->GetDocumentURI();
   if (!documentURI) {
     return NS_ERROR_FAILURE;
   }
 
   // Although the spec says that the same-origin checks should also be done
   // asynchronously, we do them in sync because the Promise created by the