Bug 1322920 - Remove DOM Promise implementation. r=bz
authorTill Schneidereit <till@tillschneidereit.net>
Sun, 11 Dec 2016 09:12:01 -0800
changeset 325892 918e37b44bddf0ab04f59887a1bb753aa586b3d9
parent 325891 38470e52b9d3beb7f648d8726d0c731684ddb75c
child 325893 da76054452f3306b159d30584d4307ac3d612485
push id31078
push userkwierso@gmail.com
push dateThu, 15 Dec 2016 00:06:52 +0000
treeherdermozilla-central@b1ab720c6d3e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1322920
milestone53.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 1322920 - Remove DOM Promise implementation. r=bz MozReview-Commit-ID: 1zzd0x2LNNb
build/docs/mozinfo.rst
dom/bindings/BindingUtils.cpp
dom/bindings/Codegen.py
dom/bindings/ToJSValue.cpp
dom/bindings/ToJSValue.h
dom/promise/Promise.cpp
dom/promise/Promise.h
dom/promise/PromiseCallback.cpp
dom/promise/PromiseCallback.h
dom/promise/PromiseDebugging.cpp
dom/promise/PromiseDebugging.h
dom/promise/moz.build
dom/webidl/Promise.webidl
dom/webidl/PromiseDebugging.webidl
dom/webidl/moz.build
js/moz.configure
js/src/builtin/TestingFunctions.cpp
js/src/jsapi-tests/moz.build
js/src/jsprototypes.h
js/src/moz.build
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
js/src/vm/GlobalObject.cpp
js/src/wasm/WasmJS.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCConvert.cpp
python/mozbuild/mozbuild/mozinfo.py
xpcom/base/CycleCollectedJSContext.cpp
xpcom/base/CycleCollectedJSContext.h
--- a/build/docs/mozinfo.rst
+++ b/build/docs/mozinfo.rst
@@ -131,24 +131,16 @@ processor
 
 release_or_beta
    Whether this is a release or beta build.
 
    Values are ``true`` and ``false``.
 
    Always defined.
 
-sm_promise
-   Whether spidermonkey promises have been enabled or not.  This is set
-   by adding --enable-sm-promise to the mozconfig file.
-
-   Values are ``true`` and ``false``.
-
-   Always defined.
-
 stylo
    Whether the Stylo styling system is being used.
 
    Values are ``true`` and ``false``.
 
    Always defined.
 
 tests_enabled
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2956,52 +2956,16 @@ StaticMethodPromiseWrapper(JSContext* cx
                                    args.rval());
 }
 
 bool
 ConvertExceptionToPromise(JSContext* cx,
                           JSObject* promiseScope,
                           JS::MutableHandle<JS::Value> rval)
 {
-#ifndef SPIDERMONKEY_PROMISE
-  GlobalObject global(cx, promiseScope);
-  if (global.Failed()) {
-    return false;
-  }
-
-  JS::Rooted<JS::Value> exn(cx);
-  if (!JS_GetPendingException(cx, &exn)) {
-    // This is very important: if there is no pending exception here but we're
-    // ending up in this code, that means the callee threw an uncatchable
-    // exception.  Just propagate that out as-is.
-    return false;
-  }
-
-  JS_ClearPendingException(cx);
-
-  nsCOMPtr<nsIGlobalObject> globalObj =
-    do_QueryInterface(global.GetAsSupports());
-  if (!globalObj) {
-    ErrorResult rv;
-    rv.Throw(NS_ERROR_UNEXPECTED);
-    return !rv.MaybeSetPendingException(cx);
-  }
-
-  ErrorResult rv;
-  RefPtr<Promise> promise = Promise::Reject(globalObj, cx, exn, rv);
-  if (rv.MaybeSetPendingException(cx)) {
-    // We just give up.  We put the exception from the ErrorResult on
-    // the JSContext just to make sure to not leak memory on the
-    // ErrorResult, but now just put the original exception back.
-    JS_SetPendingException(cx, exn);
-    return false;
-  }
-
-  return GetOrCreateDOMReflector(cx, promise, rval);
-#else // SPIDERMONKEY_PROMISE
   {
     JSAutoCompartment ac(cx, promiseScope);
 
     JS::Rooted<JS::Value> exn(cx);
     if (!JS_GetPendingException(cx, &exn)) {
       // This is very important: if there is no pending exception here but we're
       // ending up in this code, that means the callee threw an uncatchable
       // exception.  Just propagate that out as-is.
@@ -3017,17 +2981,16 @@ ConvertExceptionToPromise(JSContext* cx,
       return false;
     }
 
     rval.setObject(*promise);
   }
 
   // Now make sure we rewrap promise back into the compartment we want
   return JS_WrapValue(cx, rval);
-#endif // SPIDERMONKEY_PROMISE
 }
 
 /* static */
 void
 CreateGlobalOptions<nsGlobalWindow>::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
 {
   xpc::TraceXPCGlobal(aTrc, aObj);
 }
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3033,33 +3033,16 @@ class CGCreateInterfaceObjectsMethod(CGA
                 }
                 """))
 
             unforgeableHolderSetup = CGList(
                 [createUnforgeableHolder, installUnforgeableHolder], "\n")
         else:
             unforgeableHolderSetup = None
 
-        if self.descriptor.name == "Promise":
-            speciesSetup = CGGeneric(fill(
-                """
-                #ifndef SPIDERMONKEY_PROMISE
-                JS::Rooted<JSObject*> promiseConstructor(aCx, *interfaceCache);
-                JS::Rooted<jsid> species(aCx,
-                  SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::species)));
-                if (!JS_DefinePropertyById(aCx, promiseConstructor, species, JS::UndefinedHandleValue,
-                                           JSPROP_SHARED, Promise::PromiseSpecies, nullptr)) {
-                  $*{failureCode}
-                }
-                #endif // SPIDERMONKEY_PROMISE
-                """,
-                failureCode=failureCode))
-        else:
-            speciesSetup = None
-
         if (self.descriptor.interface.isOnGlobalProtoChain() and
             needInterfacePrototypeObject):
             makeProtoPrototypeImmutable = CGGeneric(fill(
                 """
                 if (*${protoCache}) {
                   bool succeeded;
                   JS::Handle<JSObject*> prot = GetProtoObjectHandle(aCx);
                   if (!JS_SetImmutablePrototype(aCx, prot, &succeeded)) {
@@ -3075,17 +3058,17 @@ class CGCreateInterfaceObjectsMethod(CGA
                 protoCache=protoCache,
                 failureCode=failureCode))
         else:
             makeProtoPrototypeImmutable = None
 
         return CGList(
             [getParentProto, getConstructorProto, initIds,
              prefCache, CGGeneric(call), defineAliases, unforgeableHolderSetup,
-             speciesSetup, makeProtoPrototypeImmutable],
+             makeProtoPrototypeImmutable],
             "\n").define()
 
 
 class CGGetPerInterfaceObject(CGAbstractMethod):
     """
     A method for getting a per-interface object (a prototype object or interface
     constructor object).
     """
@@ -5314,49 +5297,28 @@ def getJSToNativeConversionInfo(type, de
                     $*{exceptionCode}
                   }
 
                   JS::Rooted<JS::Value> valueToResolve(cx, $${val});
                   if (!JS_WrapValue(cx, &valueToResolve)) {
                     $*{exceptionCode}
                   }
                   binding_detail::FastErrorResult promiseRv;
-                #ifdef SPIDERMONKEY_PROMISE
                   nsCOMPtr<nsIGlobalObject> global =
                     do_QueryInterface(promiseGlobal.GetAsSupports());
                   if (!global) {
                     promiseRv.Throw(NS_ERROR_UNEXPECTED);
                     promiseRv.MaybeSetPendingException(cx);
                     $*{exceptionCode}
                   }
                   $${declName} = Promise::Resolve(global, cx, valueToResolve,
                                                   promiseRv);
                   if (promiseRv.MaybeSetPendingException(cx)) {
                     $*{exceptionCode}
                   }
-                #else
-                  JS::Handle<JSObject*> promiseCtor =
-                    PromiseBinding::GetConstructorObjectHandle(cx);
-                  if (!promiseCtor) {
-                    $*{exceptionCode}
-                  }
-                  JS::Rooted<JS::Value> resolveThisv(cx, JS::ObjectValue(*promiseCtor));
-                  JS::Rooted<JS::Value> resolveResult(cx);
-                  Promise::Resolve(promiseGlobal, resolveThisv, valueToResolve,
-                                   &resolveResult, promiseRv);
-                  if (promiseRv.MaybeSetPendingException(cx)) {
-                    $*{exceptionCode}
-                  }
-                  nsresult unwrapRv = UNWRAP_OBJECT(Promise, &resolveResult.toObject(), $${declName});
-                  if (NS_FAILED(unwrapRv)) { // Quite odd
-                    promiseRv.Throw(unwrapRv);
-                    promiseRv.MaybeSetPendingException(cx);
-                    $*{exceptionCode}
-                  }
-                #endif // SPIDERMONKEY_PROMISE
                 }
                 """,
                 getPromiseGlobal=getPromiseGlobal,
                 exceptionCode=exceptionCode)
         elif not descriptor.interface.isConsequential() and not descriptor.interface.isExternal():
             if failureCode is not None:
                 templateBody += str(CastableObjectUnwrapper(
                     descriptor,
--- a/dom/bindings/ToJSValue.cpp
+++ b/dom/bindings/ToJSValue.cpp
@@ -2,19 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/Exceptions.h"
-#ifdef SPIDERMONKEY_PROMISE
 #include "mozilla/dom/Promise.h"
-#endif // SPIDERMONKEY_PROMISE
 #include "nsAString.h"
 #include "nsContentUtils.h"
 #include "nsStringBuffer.h"
 #include "xpcpublic.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -61,20 +59,18 @@ ToJSValue(JSContext* aCx,
   DebugOnly<bool> throwResult = aArgument.MaybeSetPendingException(aCx);
   MOZ_ASSERT(throwResult);
   DebugOnly<bool> getPendingResult = JS_GetPendingException(aCx, aValue);
   MOZ_ASSERT(getPendingResult);
   JS_ClearPendingException(aCx);
   return true;
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 bool
 ToJSValue(JSContext* aCx, Promise& aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   aValue.setObject(*aArgument.PromiseObj());
   return true;
 }
-#endif // SPIDERMONKEY_PROMISE
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -301,23 +301,21 @@ MOZ_MUST_USE
 typename EnableIf<IsPointer<T>::value, bool>::Type
 ToJSValue(JSContext* aCx,
           T aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   return ToJSValue(aCx, *aArgument, aValue);
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 // Accept Promise objects, which need special handling.
 MOZ_MUST_USE bool
 ToJSValue(JSContext* aCx,
           Promise& aArgument,
           JS::MutableHandle<JS::Value> aValue);
-#endif // SPIDERMONKEY_PROMISE
 
 // Accept arrays of other things we accept
 template <typename T>
 MOZ_MUST_USE bool
 ToJSValue(JSContext* aCx,
           T* aArguments,
           size_t aLength,
           JS::MutableHandle<JS::Value> aValue)
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -25,17 +25,16 @@
 #include "js/StructuredClone.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsJSEnvironment.h"
 #include "nsJSPrincipals.h"
 #include "nsJSUtils.h"
 #include "nsPIDOMWindow.h"
-#include "PromiseCallback.h"
 #include "PromiseDebugging.h"
 #include "PromiseNativeHandler.h"
 #include "PromiseWorkerProxy.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "WrapperFactory.h"
 #include "xpcpublic.h"
 #ifdef MOZ_CRASHREPORTER
@@ -47,466 +46,56 @@ namespace dom {
 
 namespace {
 // Generator used by Promise::GetID.
 Atomic<uintptr_t> gIDGenerator(0);
 } // namespace
 
 using namespace workers;
 
-#ifndef SPIDERMONKEY_PROMISE
-// This class processes the promise's callbacks with promise's result.
-class PromiseReactionJob final : public Runnable
-{
-public:
-  PromiseReactionJob(Promise* aPromise,
-                     PromiseCallback* aCallback,
-                     const JS::Value& aValue)
-    : mPromise(aPromise)
-    , mCallback(aCallback)
-    , mValue(CycleCollectedJSContext::Get()->Context(), aValue)
-  {
-    MOZ_ASSERT(aPromise);
-    MOZ_ASSERT(aCallback);
-    MOZ_COUNT_CTOR(PromiseReactionJob);
-  }
-
-  virtual
-  ~PromiseReactionJob()
-  {
-    NS_ASSERT_OWNINGTHREAD(PromiseReactionJob);
-    MOZ_COUNT_DTOR(PromiseReactionJob);
-  }
-
-protected:
-  NS_IMETHOD
-  Run() override
-  {
-    NS_ASSERT_OWNINGTHREAD(PromiseReactionJob);
-
-    MOZ_ASSERT(mPromise->GetWrapper()); // It was preserved!
-
-    AutoJSAPI jsapi;
-    if (!jsapi.Init(mPromise->GetWrapper())) {
-      return NS_ERROR_FAILURE;
-    }
-    JSContext* cx = jsapi.cx();
-
-    JS::Rooted<JS::Value> value(cx, mValue);
-    if (!MaybeWrapValue(cx, &value)) {
-      NS_WARNING("Failed to wrap value into the right compartment.");
-      JS_ClearPendingException(cx);
-      return NS_OK;
-    }
-
-    JS::Rooted<JSObject*> asyncStack(cx, mPromise->mAllocationStack);
-
-    {
-      Maybe<JS::AutoSetAsyncStackForNewCalls> sas;
-      if (asyncStack) {
-        sas.emplace(cx, asyncStack, "Promise");
-      }
-      mCallback->Call(cx, value);
-    }
-
-    return NS_OK;
-  }
-
-private:
-  RefPtr<Promise> mPromise;
-  RefPtr<PromiseCallback> mCallback;
-  JS::PersistentRooted<JS::Value> mValue;
-  NS_DECL_OWNINGTHREAD;
-};
-
-/*
- * Utilities for thenable callbacks.
- *
- * A thenable is a { then: function(resolve, reject) { } }.
- * `then` is called with a resolve and reject callback pair.
- * Since only one of these should be called at most once (first call wins), the
- * two keep a reference to each other in SLOT_DATA. When either of them is
- * called, the references are cleared. Further calls are ignored.
- */
-namespace {
-void
-LinkThenableCallables(JSContext* aCx, JS::Handle<JSObject*> aResolveFunc,
-                      JS::Handle<JSObject*> aRejectFunc)
-{
-  js::SetFunctionNativeReserved(aResolveFunc, Promise::SLOT_DATA,
-                                JS::ObjectValue(*aRejectFunc));
-  js::SetFunctionNativeReserved(aRejectFunc, Promise::SLOT_DATA,
-                                JS::ObjectValue(*aResolveFunc));
-}
-
-/*
- * Returns false if callback was already called before, otherwise breaks the
- * links and returns true.
- */
-bool
-MarkAsCalledIfNotCalledBefore(JSContext* aCx, JS::Handle<JSObject*> aFunc)
-{
-  JS::Value otherFuncVal =
-    js::GetFunctionNativeReserved(aFunc, Promise::SLOT_DATA);
-
-  if (!otherFuncVal.isObject()) {
-    return false;
-  }
-
-  JSObject* otherFuncObj = &otherFuncVal.toObject();
-  MOZ_ASSERT(js::GetFunctionNativeReserved(otherFuncObj,
-                                           Promise::SLOT_DATA).isObject());
-
-  // Break both references.
-  js::SetFunctionNativeReserved(aFunc, Promise::SLOT_DATA,
-                                JS::UndefinedValue());
-  js::SetFunctionNativeReserved(otherFuncObj, Promise::SLOT_DATA,
-                                JS::UndefinedValue());
-
-  return true;
-}
-
-Promise*
-GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
-{
-  JS::Value promiseVal = js::GetFunctionNativeReserved(aFunc,
-                                                       Promise::SLOT_PROMISE);
-
-  MOZ_ASSERT(promiseVal.isObject());
-
-  Promise* promise;
-  UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
-  return promise;
-}
-} // namespace
-
-// Runnable to resolve thenables.
-// Equivalent to the specification's ResolvePromiseViaThenableTask.
-class PromiseResolveThenableJob final : public Runnable
-{
-public:
-  PromiseResolveThenableJob(Promise* aPromise,
-                            JS::Handle<JSObject*> aThenable,
-                            PromiseInit* aThen)
-    : mPromise(aPromise)
-    , mThenable(CycleCollectedJSContext::Get()->Context(), aThenable)
-    , mThen(aThen)
-  {
-    MOZ_ASSERT(aPromise);
-    MOZ_COUNT_CTOR(PromiseResolveThenableJob);
-  }
-
-  virtual
-  ~PromiseResolveThenableJob()
-  {
-    NS_ASSERT_OWNINGTHREAD(PromiseResolveThenableJob);
-    MOZ_COUNT_DTOR(PromiseResolveThenableJob);
-  }
-
-protected:
-  NS_IMETHOD
-  Run() override
-  {
-    NS_ASSERT_OWNINGTHREAD(PromiseResolveThenableJob);
-
-    MOZ_ASSERT(mPromise->GetWrapper()); // It was preserved!
-
-    AutoJSAPI jsapi;
-    // If we ever change which compartment we're working in here, make sure to
-    // fix the fast-path for resolved-with-a-Promise in ResolveInternal.
-    if (!jsapi.Init(mPromise->GetWrapper())) {
-      return NS_ERROR_FAILURE;
-    }
-    JSContext* cx = jsapi.cx();
-
-    JS::Rooted<JSObject*> resolveFunc(cx,
-      mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Resolve));
-
-    if (!resolveFunc) {
-      mPromise->HandleException(cx);
-      return NS_OK;
-    }
-
-    JS::Rooted<JSObject*> rejectFunc(cx,
-      mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Reject));
-    if (!rejectFunc) {
-      mPromise->HandleException(cx);
-      return NS_OK;
-    }
-
-    LinkThenableCallables(cx, resolveFunc, rejectFunc);
-
-    ErrorResult rv;
-
-    JS::Rooted<JSObject*> rootedThenable(cx, mThenable);
-
-    mThen->Call(rootedThenable, resolveFunc, rejectFunc, rv,
-                "promise thenable", CallbackObject::eRethrowExceptions,
-                mPromise->Compartment());
-
-    rv.WouldReportJSException();
-    if (rv.Failed()) {
-      JS::Rooted<JS::Value> exn(cx);
-      { // Scope for JSAutoCompartment
-
-        // Convert the ErrorResult to a JS exception object that we can reject
-        // ourselves with.  This will be exactly the exception that would get
-        // thrown from a binding method whose ErrorResult ended up with
-        // whatever is on "rv" right now.
-        JSAutoCompartment ac(cx, mPromise->GlobalJSObject());
-        DebugOnly<bool> conversionResult = ToJSValue(cx, rv, &exn);
-        MOZ_ASSERT(conversionResult);
-      }
-
-      bool couldMarkAsCalled = MarkAsCalledIfNotCalledBefore(cx, resolveFunc);
-
-      // If we could mark as called, neither of the callbacks had been called
-      // when the exception was thrown. So we can reject the Promise.
-      if (couldMarkAsCalled) {
-        bool ok = JS_WrapValue(cx, &exn);
-        MOZ_ASSERT(ok);
-        if (!ok) {
-          NS_WARNING("Failed to wrap value into the right compartment.");
-        }
-
-        mPromise->RejectInternal(cx, exn);
-      }
-      // At least one of resolveFunc or rejectFunc have been called, so ignore
-      // the exception. FIXME(nsm): This should be reported to the error
-      // console though, for debugging.
-    }
-
-    return rv.StealNSResult();
-  }
-
-private:
-  RefPtr<Promise> mPromise;
-  JS::PersistentRooted<JSObject*> mThenable;
-  RefPtr<PromiseInit> mThen;
-  NS_DECL_OWNINGTHREAD;
-};
-
-// A struct implementing
-// <http://www.ecma-international.org/ecma-262/6.0/#sec-promisecapability-records>.
-// While the spec holds on to these in some places, in practice those places
-// don't actually need everything from this struct, so we explicitly grab
-// members from it as needed in those situations.  That allows us to make this a
-// stack-only struct and keep the rooting simple.
-//
-// We also add an optimization for the (common) case when we discover that the
-// Promise constructor we're supposed to use is in fact the canonical Promise
-// constructor.  In that case we will just set mNativePromise in our
-// PromiseCapability and not set mPromise/mResolve/mReject; the correct
-// callbacks will be the standard Promise ones, and we don't really want to
-// synthesize JSFunctions for them in that situation.
-struct MOZ_STACK_CLASS Promise::PromiseCapability
-{
-  explicit PromiseCapability(JSContext* aCx)
-    : mPromise(aCx)
-    , mResolve(aCx)
-    , mReject(aCx)
-  {}
-
-  // Take an exception on aCx and try to convert it into a promise rejection.
-  // Note that this can result in a new exception being thrown on aCx, or an
-  // exception getting thrown on aRv.  On entry to this method, aRv is assumed
-  // to not be a failure.  This should only be called if NewPromiseCapability
-  // succeeded on this PromiseCapability.
-  void RejectWithException(JSContext* aCx, ErrorResult& aRv);
-
-  // Return a JS::Value representing the promise.  This should only be called if
-  // NewPromiseCapability succeeded on this PromiseCapability.  It makes no
-  // guarantees about compartments (e.g. in the mNativePromise case it's in the
-  // compartment of the reflector, but in the mPromise case it might be in the
-  // compartment of some cross-compartment wrapper for a reflector).
-  JS::Value PromiseValue() const;
-
-  // All the JS::Value fields of this struct are actually objects, but for our
-  // purposes it's simpler to store them as JS::Value.
-
-  // [[Promise]].
-  JS::Rooted<JSObject*> mPromise;
-  // [[Resolve]].  Value in the context compartment.
-  JS::Rooted<JS::Value> mResolve;
-  // [[Reject]].  Value in the context compartment.
-  JS::Rooted<JS::Value> mReject;
-  // If mNativePromise is non-null, we should use it, not mPromise.
-  RefPtr<Promise> mNativePromise;
-
-private:
-  // We don't want to allow creation of temporaries of this type, ever.
-  PromiseCapability(const PromiseCapability&) = delete;
-  PromiseCapability(PromiseCapability&&) = delete;
-};
-
-void
-Promise::PromiseCapability::RejectWithException(JSContext* aCx,
-                                                ErrorResult& aRv)
-{
-  // This method basically implements
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-ifabruptrejectpromise
-  // or at least the parts of it that happen if we have an abrupt completion.
-
-  MOZ_ASSERT(!aRv.Failed());
-  MOZ_ASSERT(mNativePromise || mPromise,
-             "NewPromiseCapability didn't succeed");
-
-  JS::Rooted<JS::Value> exn(aCx);
-  if (!JS_GetPendingException(aCx, &exn)) {
-    // This is an uncatchable exception, so can't be converted into a rejection.
-    // Just rethrow that on aRv.
-    aRv.ThrowUncatchableException();
-    return;
-  }
-
-  JS_ClearPendingException(aCx);
-
-  // If we have a native promise, just reject it without trying to call out into
-  // JS.
-  if (mNativePromise) {
-    mNativePromise->MaybeRejectInternal(aCx, exn);
-    return;
-  }
-
-  JS::Rooted<JS::Value> ignored(aCx);
-  if (!JS::Call(aCx, JS::UndefinedHandleValue, mReject, JS::HandleValueArray(exn),
-                &ignored)) {
-    aRv.NoteJSContextException(aCx);
-  }
-}
-
-JS::Value
-Promise::PromiseCapability::PromiseValue() const
-{
-  MOZ_ASSERT(mNativePromise || mPromise,
-             "NewPromiseCapability didn't succeed");
-
-  if (mNativePromise) {
-    return JS::ObjectValue(*mNativePromise->GetWrapper());
-  }
-
-  return JS::ObjectValue(*mPromise);
-}
-
-#endif // SPIDERMONKEY_PROMISE
-
 // Promise
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Promise)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Promise)
-#ifndef SPIDERMONKEY_PROMISE
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  tmp->MaybeReportRejectedOnce();
-#else
-  tmp->mResult = JS::UndefinedValue();
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-#endif // SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
-#ifndef SPIDERMONKEY_PROMISE
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveCallbacks)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectCallbacks)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-#else // SPIDERMONKEY_PROMISE
   tmp->mPromiseObj = nullptr;
-#endif // SPIDERMONKEY_PROMISE
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Promise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
-#ifndef SPIDERMONKEY_PROMISE
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveCallbacks)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectCallbacks)
-#endif // SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Promise)
-#ifndef SPIDERMONKEY_PROMISE
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResult)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAllocationStack)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRejectionStack)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mFullfillmentStack)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-#else // SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPromiseObj);
-#endif // SPIDERMONKEY_PROMISE
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
-#ifndef SPIDERMONKEY_PROMISE
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Promise)
-  if (tmp->IsBlack()) {
-    tmp->mResult.exposeToActiveJS();
-    tmp->mAllocationStack.exposeToActiveJS();
-    tmp->mRejectionStack.exposeToActiveJS();
-    tmp->mFullfillmentStack.exposeToActiveJS();
-    return true;
-  }
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
-
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Promise)
-  return tmp->IsBlackAndDoesNotNeedTracing(tmp);
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
-
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Promise)
-  return tmp->IsBlack();
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
-#endif // SPIDERMONKEY_PROMISE
-
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Promise)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Promise)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Promise)
-#ifndef SPIDERMONKEY_PROMISE
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-#endif // SPIDERMONKEY_PROMISE
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(Promise)
 NS_INTERFACE_MAP_END
 
 Promise::Promise(nsIGlobalObject* aGlobal)
   : mGlobal(aGlobal)
-#ifndef SPIDERMONKEY_PROMISE
-  , mResult(JS::UndefinedValue())
-  , mAllocationStack(nullptr)
-  , mRejectionStack(nullptr)
-  , mFullfillmentStack(nullptr)
-  , mState(Pending)
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  , mHadRejectCallback(false)
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  , mTaskPending(false)
-  , mResolvePending(false)
-  , mIsLastInChain(true)
-  , mWasNotifiedAsUncaught(false)
-  , mID(0)
-#else // SPIDERMONKEY_PROMISE
   , mPromiseObj(nullptr)
-#endif // SPIDERMONKEY_PROMISE
 {
   MOZ_ASSERT(mGlobal);
 
   mozilla::HoldJSObjects(this);
-
-#ifndef SPIDERMONKEY_PROMISE
-  mCreationTimestamp = TimeStamp::Now();
-#endif // SPIDERMONKEY_PROMISE
 }
 
 Promise::~Promise()
 {
-#ifndef SPIDERMONKEY_PROMISE
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  MaybeReportRejectedOnce();
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-#endif // SPIDERMONKEY_PROMISE
   mozilla::DropJSObjects(this);
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 
 bool
 Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
                     JS::MutableHandle<JSObject*> aWrapper)
 {
 #ifdef DEBUG
   binding_detail::AssertReflectorHasGivenProto(aCx, mPromiseObj, aGivenProto);
 #endif // DEBUG
@@ -881,107 +470,33 @@ Promise::AppendNativeHandler(PromiseNati
 }
 
 void
 Promise::HandleException(JSContext* aCx)
 {
   JS::Rooted<JS::Value> exn(aCx);
   if (JS_GetPendingException(aCx, &exn)) {
     JS_ClearPendingException(aCx);
-    // This is only called from MaybeSomething, so it's OK to MaybeReject here,
-    // unlike in the version that's used when !SPIDERMONKEY_PROMISE.
+    // This is only called from MaybeSomething, so it's OK to MaybeReject here.
     MaybeReject(aCx, exn);
   }
 }
 
 // static
 already_AddRefed<Promise>
 Promise::CreateFromExisting(nsIGlobalObject* aGlobal,
                             JS::Handle<JSObject*> aPromiseObj)
 {
   MOZ_ASSERT(js::GetObjectCompartment(aGlobal->GetGlobalJSObject()) ==
              js::GetObjectCompartment(aPromiseObj));
   RefPtr<Promise> p = new Promise(aGlobal);
   p->mPromiseObj = aPromiseObj;
   return p.forget();
 }
 
-#else // SPIDERMONKEY_PROMISE
-
-JSObject*
-Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return PromiseBinding::Wrap(aCx, this, aGivenProto);
-}
-
-already_AddRefed<Promise>
-Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
-                JS::Handle<JSObject*> aDesiredProto)
-{
-  if (!aGlobal) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-  RefPtr<Promise> p = new Promise(aGlobal);
-  p->CreateWrapper(aDesiredProto, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  return p.forget();
-}
-
-void
-Promise::CreateWrapper(JS::Handle<JSObject*> aDesiredProto, ErrorResult& aRv)
-{
-  AutoJSAPI jsapi;
-  if (!jsapi.Init(mGlobal)) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-  JSContext* cx = jsapi.cx();
-
-  JS::Rooted<JS::Value> wrapper(cx);
-  if (!GetOrCreateDOMReflector(cx, this, &wrapper, aDesiredProto)) {
-    JS_ClearPendingException(cx);
-    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-    return;
-  }
-
-  dom::PreserveWrapper(this);
-
-  // Now grab our allocation stack
-  if (!CaptureStack(cx, mAllocationStack)) {
-    JS_ClearPendingException(cx);
-    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-    return;
-  }
-
-  JS::RootedObject obj(cx, &wrapper.toObject());
-  JS::dbg::onNewPromise(cx, obj);
-}
-
-void
-Promise::MaybeResolve(JSContext* aCx,
-                      JS::Handle<JS::Value> aValue)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  MaybeResolveInternal(aCx, aValue);
-}
-
-void
-Promise::MaybeReject(JSContext* aCx,
-                     JS::Handle<JS::Value> aValue)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  MaybeRejectInternal(aCx, aValue);
-}
-
-#endif // SPIDERMONKEY_PROMISE
 
 void
 Promise::MaybeResolveWithUndefined()
 {
   NS_ASSERT_OWNINGTHREAD(Promise);
 
   MaybeResolve(JS::UndefinedHandleValue);
 }
@@ -996,17 +511,16 @@ Promise::MaybeReject(const RefPtr<MediaS
 void
 Promise::MaybeRejectWithUndefined()
 {
   NS_ASSERT_OWNINGTHREAD(Promise);
 
   MaybeSomething(JS::UndefinedHandleValue, &Promise::MaybeReject);
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 void
 Promise::ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise)
 {
   MOZ_ASSERT(!js::IsWrapper(aPromise));
 
   MOZ_ASSERT(JS::GetPromiseState(aPromise) == JS::PromiseState::Rejected);
 
   JS::Rooted<JS::Value> result(aCx, JS::GetPromiseResult(aPromise));
@@ -1023,17 +537,16 @@ Promise::ReportRejectedPromise(JSContext
                                : GetCurrentThreadWorkerPrivate()->IsChromeWorker();
   nsGlobalWindow* win = isMainThread ? xpc::WindowGlobalOrNull(aPromise) : nullptr;
   xpcReport->Init(report.report(), report.toStringResult().c_str(), isChrome,
                   win ? win->AsInner()->WindowID() : 0);
 
   // Now post an event to do the real reporting async
   NS_DispatchToMainThread(new AsyncErrorReporter(xpcReport));
 }
-#endif // defined(SPIDERMONKEY_PROMISE)
 
 bool
 Promise::PerformMicroTaskCheckpoint()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
 
   CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
 
@@ -1123,1821 +636,28 @@ Promise::PerformWorkerDebuggerMicroTaskC
     nsresult rv = runnable->Run();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
     context->AfterProcessMicrotask();
   }
 }
 
-#ifndef SPIDERMONKEY_PROMISE
-
-/* static */ bool
-Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
-{
-  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
-
-  JS::Rooted<JS::Value> v(aCx,
-                          js::GetFunctionNativeReserved(&args.callee(),
-                                                        SLOT_PROMISE));
-  MOZ_ASSERT(v.isObject());
-
-  Promise* promise;
-  if (NS_FAILED(UNWRAP_OBJECT(Promise, &v.toObject(), promise))) {
-    return Throw(aCx, NS_ERROR_UNEXPECTED);
-  }
-
-  v = js::GetFunctionNativeReserved(&args.callee(), SLOT_DATA);
-  PromiseCallback::Task task = static_cast<PromiseCallback::Task>(v.toInt32());
-
-  if (task == PromiseCallback::Resolve) {
-    if (!promise->CaptureStack(aCx, promise->mFullfillmentStack)) {
-      return false;
-    }
-    promise->MaybeResolveInternal(aCx, args.get(0));
-  } else {
-    promise->MaybeRejectInternal(aCx, args.get(0));
-    if (!promise->CaptureStack(aCx, promise->mRejectionStack)) {
-      return false;
-    }
-  }
-
-  args.rval().setUndefined();
-  return true;
-}
-
-/*
- * Common bits of (JSCallbackThenableResolver/JSCallbackThenableRejecter).
- * Resolves/rejects the Promise if it is ok to do so, based on whether either of
- * the callbacks have been called before or not.
- */
-/* static */ bool
-Promise::ThenableResolverCommon(JSContext* aCx, uint32_t aTask,
-                                unsigned aArgc, JS::Value* aVp)
-{
-  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
-  JS::Rooted<JSObject*> thisFunc(aCx, &args.callee());
-  if (!MarkAsCalledIfNotCalledBefore(aCx, thisFunc)) {
-    // A function from this pair has been called before.
-    args.rval().setUndefined();
-    return true;
-  }
-
-  Promise* promise = GetPromise(aCx, thisFunc);
-  MOZ_ASSERT(promise);
-
-  if (aTask == PromiseCallback::Resolve) {
-    promise->ResolveInternal(aCx, args.get(0));
-  } else {
-    promise->RejectInternal(aCx, args.get(0));
-  }
-
-  args.rval().setUndefined();
-  return true;
-}
-
-/* static */ bool
-Promise::JSCallbackThenableResolver(JSContext* aCx,
-                                    unsigned aArgc, JS::Value* aVp)
-{
-  return ThenableResolverCommon(aCx, PromiseCallback::Resolve, aArgc, aVp);
-}
-
-/* static */ bool
-Promise::JSCallbackThenableRejecter(JSContext* aCx,
-                                    unsigned aArgc, JS::Value* aVp)
-{
-  return ThenableResolverCommon(aCx, PromiseCallback::Reject, aArgc, aVp);
-}
-
-/* static */ JSObject*
-Promise::CreateFunction(JSContext* aCx, Promise* aPromise, int32_t aTask)
-{
-  // If this function ever changes, make sure to update
-  // WrapperPromiseCallback::GetDependentPromise.
-  JSFunction* func = js::NewFunctionWithReserved(aCx, JSCallback,
-                                                 1 /* nargs */, 0 /* flags */,
-                                                 nullptr);
-  if (!func) {
-    return nullptr;
-  }
-
-  JS::Rooted<JSObject*> obj(aCx, JS_GetFunctionObject(func));
-
-  JS::Rooted<JS::Value> promiseObj(aCx);
-  if (!dom::GetOrCreateDOMReflector(aCx, aPromise, &promiseObj)) {
-    return nullptr;
-  }
-
-  JS::ExposeValueToActiveJS(promiseObj);
-  js::SetFunctionNativeReserved(obj, SLOT_PROMISE, promiseObj);
-  js::SetFunctionNativeReserved(obj, SLOT_DATA, JS::Int32Value(aTask));
-
-  return obj;
-}
-
-/* static */ JSObject*
-Promise::CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask)
-{
-  JSNative whichFunc =
-    aTask == PromiseCallback::Resolve ? JSCallbackThenableResolver :
-                                        JSCallbackThenableRejecter ;
-
-  JSFunction* func = js::NewFunctionWithReserved(aCx, whichFunc,
-                                                 1 /* nargs */, 0 /* flags */,
-                                                 nullptr);
-  if (!func) {
-    return nullptr;
-  }
-
-  JS::Rooted<JSObject*> obj(aCx, JS_GetFunctionObject(func));
-
-  JS::Rooted<JS::Value> promiseObj(aCx);
-  if (!dom::GetOrCreateDOMReflector(aCx, aPromise, &promiseObj)) {
-    return nullptr;
-  }
-
-  JS::ExposeValueToActiveJS(promiseObj);
-  js::SetFunctionNativeReserved(obj, SLOT_PROMISE, promiseObj);
-
-  return obj;
-}
-
-/* static */ already_AddRefed<Promise>
-Promise::Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
-                     ErrorResult& aRv, JS::Handle<JSObject*> aDesiredProto)
-{
-  nsCOMPtr<nsIGlobalObject> global;
-  global = do_QueryInterface(aGlobal.GetAsSupports());
-  if (!global) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<Promise> promise = Create(global, aRv, aDesiredProto);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  promise->CallInitFunction(aGlobal, aInit, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  return promise.forget();
-}
-
-void
-Promise::CallInitFunction(const GlobalObject& aGlobal,
-                          PromiseInit& aInit, ErrorResult& aRv)
-{
-  JSContext* cx = aGlobal.Context();
-
-  JS::Rooted<JSObject*> resolveFunc(cx,
-                                    CreateFunction(cx, this,
-                                                   PromiseCallback::Resolve));
-  if (!resolveFunc) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  JS::Rooted<JSObject*> rejectFunc(cx,
-                                   CreateFunction(cx, this,
-                                                  PromiseCallback::Reject));
-  if (!rejectFunc) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  aInit.Call(resolveFunc, rejectFunc, aRv, "promise initializer",
-             CallbackObject::eRethrowExceptions, Compartment());
-  aRv.WouldReportJSException();
-
-  if (aRv.Failed()) {
-    if (aRv.IsUncatchableException()) {
-      // Just propagate this to the caller.
-      return;
-    }
-
-    // There are two possibilities here.  Either we've got a rethrown exception,
-    // or we reported that already and synthesized a generic NS_ERROR_FAILURE on
-    // the ErrorResult.  In the former case, it doesn't much matter how we get
-    // the exception JS::Value from the ErrorResult to us, since we'll just end
-    // up wrapping it into the right compartment as needed if we hand it to
-    // someone.  But in the latter case we have to ensure that the new exception
-    // object we create is created in our reflector compartment, not in our
-    // current compartment, because in the case when we're a Promise constructor
-    // called over Xrays creating it in the current compartment would mean
-    // rejecting with a value that can't be accessed by code that can call
-    // then() on this Promise.
-    //
-    // Luckily, MaybeReject(aRv) does exactly what we want here: it enters our
-    // reflector compartment before trying to produce a JS::Value from the
-    // ErrorResult.
-    MaybeReject(aRv);
-  }
-}
-
-#define GET_CAPABILITIES_EXECUTOR_RESOLVE_SLOT 0
-#define GET_CAPABILITIES_EXECUTOR_REJECT_SLOT 1
-
-namespace {
-bool
-GetCapabilitiesExecutor(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
-{
-  // Implements
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-getcapabilitiesexecutor-functions
-  // except we store the [[Resolve]] and [[Reject]] in our own internal slots,
-  // not in a PromiseCapability.  The PromiseCapability will then read them from
-  // us.
-  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
-
-  // Step 1 is an assert.
-
-  // Step 2 doesn't need to be done, because it's just giving a name to the
-  // PromiseCapability record which is supposed to be stored in an internal
-  // slot.  But we don't store that at all, per the comment above; we just
-  // directly store its [[Resolve]] and [[Reject]] members.
-
-  // Steps 3 and 4.
-  if (!js::GetFunctionNativeReserved(&args.callee(),
-                                     GET_CAPABILITIES_EXECUTOR_RESOLVE_SLOT).isUndefined() ||
-      !js::GetFunctionNativeReserved(&args.callee(),
-                                     GET_CAPABILITIES_EXECUTOR_REJECT_SLOT).isUndefined()) {
-    ErrorResult rv;
-    rv.ThrowTypeError<MSG_PROMISE_CAPABILITY_HAS_SOMETHING_ALREADY>();
-    return !rv.MaybeSetPendingException(aCx);
-  }
-
-  // Step 5.
-  js::SetFunctionNativeReserved(&args.callee(),
-                                GET_CAPABILITIES_EXECUTOR_RESOLVE_SLOT,
-                                args.get(0));
-
-  // Step 6.
-  js::SetFunctionNativeReserved(&args.callee(),
-                                GET_CAPABILITIES_EXECUTOR_REJECT_SLOT,
-                                args.get(1));
-
-  // Step 7.
-  args.rval().setUndefined();
-  return true;
-}
-} // anonymous namespace
-
-/* static */ void
-Promise::NewPromiseCapability(JSContext* aCx, nsIGlobalObject* aGlobal,
-                              JS::Handle<JS::Value> aConstructor,
-                              bool aForceCallbackCreation,
-                              PromiseCapability& aCapability,
-                              ErrorResult& aRv)
-{
-  // Implements
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-newpromisecapability
-
-  if (!aConstructor.isObject() ||
-      !JS::IsConstructor(&aConstructor.toObject())) {
-    aRv.ThrowTypeError<MSG_ILLEGAL_PROMISE_CONSTRUCTOR>();
-    return;
-  }
-
-  // Step 2 is a note.
-  // Step 3 is already done because we got the PromiseCapability passed in.
-
-  // Optimization: Check whether constructor is in fact the canonical
-  // Promise constructor for aGlobal.
-  JS::Rooted<JSObject*> global(aCx, aGlobal->GetGlobalJSObject());
-  {
-    // Scope for the JSAutoCompartment, since we need to enter the compartment
-    // of global to get constructors from it.  Save the compartment we used to
-    // be in, though; we'll need it later.
-    JS::Rooted<JSObject*> callerGlobal(aCx, JS::CurrentGlobalOrNull(aCx));
-    JSAutoCompartment ac(aCx, global);
-
-    // Now wrap aConstructor into the compartment of aGlobal, so comparing it to
-    // the canonical Promise for that compartment actually makes sense.
-    JS::Rooted<JS::Value> constructorValue(aCx, aConstructor);
-    if (!MaybeWrapObjectValue(aCx, &constructorValue)) {
-      aRv.NoteJSContextException(aCx);
-      return;
-    }
-
-    JSObject* defaultCtor = PromiseBinding::GetConstructorObject(aCx);
-    if (!defaultCtor) {
-      aRv.NoteJSContextException(aCx);
-      return;
-    }
-    if (defaultCtor == &constructorValue.toObject()) {
-      // This is the canonical Promise constructor.
-      aCapability.mNativePromise = Promise::Create(aGlobal, aRv);
-      if (aForceCallbackCreation) {
-        // We have to be a bit careful here.  We want to create these functions
-        // in the compartment in which they would be created if we actually
-        // invoked the constructor via JS::Construct below.  That means our
-        // callerGlobal compartment if aConstructor is an Xray and the reflector
-        // compartment of the promise we're creating otherwise.  But note that
-        // our callerGlobal compartment is precisely the reflector compartment
-        // unless the call was done over Xrays, because the reflector
-        // compartment comes from xpc::XrayAwareCalleeGlobal.  So we really just
-        // want to create these functions in the callerGlobal compartment.
-        MOZ_ASSERT(xpc::WrapperFactory::IsXrayWrapper(&aConstructor.toObject()) ||
-                   callerGlobal == global);
-        JSAutoCompartment ac2(aCx, callerGlobal);
-
-        JSObject* resolveFuncObj =
-          CreateFunction(aCx, aCapability.mNativePromise,
-                         PromiseCallback::Resolve);
-        if (!resolveFuncObj) {
-          aRv.NoteJSContextException(aCx);
-          return;
-        }
-        aCapability.mResolve.setObject(*resolveFuncObj);
-
-        JSObject* rejectFuncObj =
-          CreateFunction(aCx, aCapability.mNativePromise,
-                         PromiseCallback::Reject);
-        if (!rejectFuncObj) {
-          aRv.NoteJSContextException(aCx);
-          return;
-        }
-        aCapability.mReject.setObject(*rejectFuncObj);
-      }
-      return;
-    }
-  }
-
-  // Step 4.
-  // We can create our get-capabilities function in the calling compartment.  It
-  // will work just as if we did |new promiseConstructor(function(a,b){}).
-  // Notably, if we're called over Xrays that's all fine, because we will end up
-  // creating the callbacks in the caller compartment in that case.
-  JSFunction* getCapabilitiesFunc =
-    js::NewFunctionWithReserved(aCx, GetCapabilitiesExecutor,
-                                2 /* nargs */,
-                                0 /* flags */,
-                                nullptr);
-  if (!getCapabilitiesFunc) {
-    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-    return;
-  }
-
-  JS::Rooted<JSObject*> getCapabilitiesObj(aCx);
-  getCapabilitiesObj = JS_GetFunctionObject(getCapabilitiesFunc);
-
-  // Step 5 doesn't need to be done, since we're not actually storing a
-  // PromiseCapability in the executor; see the comments in
-  // GetCapabilitiesExecutor above.
-
-  // Step 6 and step 7.
-  JS::Rooted<JS::Value> getCapabilities(aCx,
-                                        JS::ObjectValue(*getCapabilitiesObj));
-  JS::Rooted<JSObject*> promiseObj(aCx);
-  if (!JS::Construct(aCx, aConstructor,
-                     JS::HandleValueArray(getCapabilities),
-                     &promiseObj)) {
-    aRv.NoteJSContextException(aCx);
-    return;
-  }
-
-  // Step 8 plus copying over the value to the PromiseCapability.
-  JS::Rooted<JS::Value> v(aCx);
-  v = js::GetFunctionNativeReserved(getCapabilitiesObj,
-                                    GET_CAPABILITIES_EXECUTOR_RESOLVE_SLOT);
-  if (!v.isObject() || !JS::IsCallable(&v.toObject())) {
-    aRv.ThrowTypeError<MSG_PROMISE_RESOLVE_FUNCTION_NOT_CALLABLE>();
-    return;
-  }
-  aCapability.mResolve = v;
-
-  // Step 9 plus copying over the value to the PromiseCapability.
-  v = js::GetFunctionNativeReserved(getCapabilitiesObj,
-                                    GET_CAPABILITIES_EXECUTOR_REJECT_SLOT);
-  if (!v.isObject() || !JS::IsCallable(&v.toObject())) {
-    aRv.ThrowTypeError<MSG_PROMISE_REJECT_FUNCTION_NOT_CALLABLE>();
-    return;
-  }
-  aCapability.mReject = v;
-
-  // Step 10.
-  aCapability.mPromise = promiseObj;
-
-  // Step 11 doesn't need anything, since the PromiseCapability was passed in.
-}
-
-/* static */ void
-Promise::Resolve(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-                 JS::Handle<JS::Value> aValue,
-                 JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)
-{
-  // Implementation of
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-promise.resolve
-
-  JSContext* cx = aGlobal.Context();
-
-  nsCOMPtr<nsIGlobalObject> global =
-    do_QueryInterface(aGlobal.GetAsSupports());
-  if (!global) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  // Steps 1 and 2.
-  if (!aThisv.isObject()) {
-    aRv.ThrowTypeError<MSG_ILLEGAL_PROMISE_CONSTRUCTOR>();
-    return;
-  }
-
-  // Step 3.  If a Promise was passed and matches our constructor, just return it.
-  if (aValue.isObject()) {
-    JS::Rooted<JSObject*> valueObj(cx, &aValue.toObject());
-    Promise* nextPromise;
-    nsresult rv = UNWRAP_OBJECT(Promise, valueObj, nextPromise);
-
-    if (NS_SUCCEEDED(rv)) {
-      JS::Rooted<JS::Value> constructor(cx);
-      if (!JS_GetProperty(cx, valueObj, "constructor", &constructor)) {
-        aRv.NoteJSContextException(cx);
-        return;
-      }
-
-      // Cheat instead of calling JS_SameValue, since we know one's an object.
-      if (aThisv == constructor) {
-        aRetval.setObject(*valueObj);
-        return;
-      }
-    }
-  }
-
-  // Step 4.
-  PromiseCapability capability(cx);
-  NewPromiseCapability(cx, global, aThisv, false, capability, aRv);
-  // Step 5.
-  if (aRv.Failed()) {
-    return;
-  }
-
-  // Step 6.
-  Promise* p = capability.mNativePromise;
-  if (p) {
-    p->MaybeResolveInternal(cx, aValue);
-    p->mFullfillmentStack = p->mAllocationStack;
-  } else {
-    JS::Rooted<JS::Value> value(cx, aValue);
-    JS::Rooted<JS::Value> ignored(cx);
-    if (!JS::Call(cx, JS::UndefinedHandleValue /* thisVal */,
-                  capability.mResolve, JS::HandleValueArray(value),
-                  &ignored)) {
-      // Step 7.
-      aRv.NoteJSContextException(cx);
-      return;
-    }
-  }
-
-  // Step 8.
-  aRetval.set(capability.PromiseValue());
-}
-
-/* static */ already_AddRefed<Promise>
-Promise::Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
-                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
-{
-  RefPtr<Promise> promise = Create(aGlobal, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  promise->MaybeResolveInternal(aCx, aValue);
-  return promise.forget();
-}
-
-/* static */ void
-Promise::Reject(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-                JS::Handle<JS::Value> aValue,
-                JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)
-{
-  // Implementation of
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-promise.reject
-
-  JSContext* cx = aGlobal.Context();
-
-  nsCOMPtr<nsIGlobalObject> global =
-    do_QueryInterface(aGlobal.GetAsSupports());
-  if (!global) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  // Steps 1 and 2.
-  if (!aThisv.isObject()) {
-    aRv.ThrowTypeError<MSG_ILLEGAL_PROMISE_CONSTRUCTOR>();
-    return;
-  }
-
-  // Step 3.
-  PromiseCapability capability(cx);
-  NewPromiseCapability(cx, global, aThisv, false, capability, aRv);
-  // Step 4.
-  if (aRv.Failed()) {
-    return;
-  }
-
-  // Step 5.
-  Promise* p = capability.mNativePromise;
-  if (p) {
-    p->MaybeRejectInternal(cx, aValue);
-    p->mRejectionStack = p->mAllocationStack;
-  } else {
-    JS::Rooted<JS::Value> value(cx, aValue);
-    JS::Rooted<JS::Value> ignored(cx);
-    if (!JS::Call(cx, JS::UndefinedHandleValue /* thisVal */,
-                  capability.mReject, JS::HandleValueArray(value),
-                  &ignored)) {
-      // Step 6.
-      aRv.NoteJSContextException(cx);
-      return;
-    }
-  }
-
-  // Step 7.
-  aRetval.set(capability.PromiseValue());
-}
-
-/* static */ already_AddRefed<Promise>
-Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
-                JS::Handle<JS::Value> aValue, ErrorResult& aRv)
-{
-  RefPtr<Promise> promise = Create(aGlobal, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  promise->MaybeRejectInternal(aCx, aValue);
-  return promise.forget();
-}
-
-namespace {
-void
-SpeciesConstructor(JSContext* aCx,
-                   JS::Handle<JSObject*> promise,
-                   JS::Handle<JS::Value> defaultCtor,
-                   JS::MutableHandle<JS::Value> ctor,
-                   ErrorResult& aRv)
-{
-  // Implements
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-speciesconstructor
-
-  // Step 1.
-  MOZ_ASSERT(promise);
-
-  // Step 2.
-  JS::Rooted<JS::Value> constructorVal(aCx);
-  if (!JS_GetProperty(aCx, promise, "constructor", &constructorVal)) {
-    // Step 3.
-    aRv.NoteJSContextException(aCx);
-    return;
-  }
-
-  // Step 4.
-  if (constructorVal.isUndefined()) {
-    ctor.set(defaultCtor);
-    return;
-  }
-
-  // Step 5.
-  if (!constructorVal.isObject()) {
-    aRv.ThrowTypeError<MSG_ILLEGAL_PROMISE_CONSTRUCTOR>();
-    return;
-  }
-
-  // Step 6.
-  JS::Rooted<jsid> species(aCx,
-    SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::species)));
-  JS::Rooted<JS::Value> speciesVal(aCx);
-  JS::Rooted<JSObject*> constructorObj(aCx, &constructorVal.toObject());
-  if (!JS_GetPropertyById(aCx, constructorObj, species, &speciesVal)) {
-    // Step 7.
-    aRv.NoteJSContextException(aCx);
-    return;
-  }
-
-  // Step 8.
-  if (speciesVal.isNullOrUndefined()) {
-    ctor.set(defaultCtor);
-    return;
-  }
-
-  // Step 9.
-  if (speciesVal.isObject() && JS::IsConstructor(&speciesVal.toObject())) {
-    ctor.set(speciesVal);
-    return;
-  }
-
-  // Step 10.
-  aRv.ThrowTypeError<MSG_ILLEGAL_PROMISE_CONSTRUCTOR>();
-}
-} // anonymous namespace
-
-void
-Promise::Then(JSContext* aCx, JS::Handle<JSObject*> aCalleeGlobal,
-              AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
-              JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  // Implements
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-promise.prototype.then
-
-  // Step 1.
-  JS::Rooted<JS::Value> promiseVal(aCx, JS::ObjectValue(*GetWrapper()));
-  if (!MaybeWrapObjectValue(aCx, &promiseVal)) {
-    aRv.NoteJSContextException(aCx);
-    return;
-  }
-  JS::Rooted<JSObject*> promiseObj(aCx, &promiseVal.toObject());
-  MOZ_ASSERT(promiseObj);
-
-  // Step 2 was done by the bindings.
-
-  // Step 3.  We want to use aCalleeGlobal here because it will do the
-  // right thing for us via Xrays (where we won't find @@species on
-  // our promise constructor for now).
-  JS::Rooted<JS::Value> defaultCtorVal(aCx);
-  { // Scope for JSAutoCompartment
-    JSAutoCompartment ac(aCx, aCalleeGlobal);
-    JSObject* defaultCtor = PromiseBinding::GetConstructorObject(aCx);
-    if (!defaultCtor) {
-      aRv.NoteJSContextException(aCx);
-      return;
-    }
-    defaultCtorVal.setObject(*defaultCtor);
-  }
-  if (!MaybeWrapObjectValue(aCx, &defaultCtorVal)) {
-    aRv.NoteJSContextException(aCx);
-    return;
-  }
-
-  JS::Rooted<JS::Value> constructor(aCx);
-  SpeciesConstructor(aCx, promiseObj, defaultCtorVal, &constructor, aRv);
-  if (aRv.Failed()) {
-    // Step 4.
-    return;
-  }
-
-  // Step 5.
-  GlobalObject globalObj(aCx, GetWrapper());
-  if (globalObj.Failed()) {
-    aRv.NoteJSContextException(aCx);
-    return;
-  }
-  nsCOMPtr<nsIGlobalObject> globalObject =
-    do_QueryInterface(globalObj.GetAsSupports());
-  if (!globalObject) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-  PromiseCapability capability(aCx);
-  NewPromiseCapability(aCx, globalObject, constructor, false, capability, aRv);
-  if (aRv.Failed()) {
-    // Step 6.
-    return;
-  }
-
-  // Now step 7: start
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-performpromisethen
-
-  // Step 1 and step 2 are just assertions.
-
-  // Step 3 and step 4 are kinda handled for us already; we use null
-  // to represent "Identity" and "Thrower".
-
-  // Steps 5 and 6.  These branch based on whether we know we have a
-  // vanilla Promise or not.
-  JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
-  if (capability.mNativePromise) {
-    Promise* promise = capability.mNativePromise;
-
-    RefPtr<PromiseCallback> resolveCb =
-      PromiseCallback::Factory(promise, global, aResolveCallback,
-                               PromiseCallback::Resolve);
-
-    RefPtr<PromiseCallback> rejectCb =
-      PromiseCallback::Factory(promise, global, aRejectCallback,
-                               PromiseCallback::Reject);
-
-    AppendCallbacks(resolveCb, rejectCb);
-  } else {
-    JS::Rooted<JSObject*> resolveObj(aCx, &capability.mResolve.toObject());
-    RefPtr<AnyCallback> resolveFunc =
-      new AnyCallback(aCx, resolveObj, GetIncumbentGlobal());
-
-    JS::Rooted<JSObject*> rejectObj(aCx, &capability.mReject.toObject());
-    RefPtr<AnyCallback> rejectFunc =
-      new AnyCallback(aCx, rejectObj, GetIncumbentGlobal());
-
-    if (!capability.mPromise) {
-      aRv.ThrowTypeError<MSG_ILLEGAL_PROMISE_CONSTRUCTOR>();
-      return;
-    }
-    JS::Rooted<JSObject*> newPromiseObj(aCx, capability.mPromise);
-    // We want to store the reflector itself.
-    newPromiseObj = js::CheckedUnwrap(newPromiseObj);
-    if (!newPromiseObj) {
-      // Just throw something.
-      aRv.ThrowTypeError<MSG_ILLEGAL_PROMISE_CONSTRUCTOR>();
-      return;
-    }
-
-    RefPtr<PromiseCallback> resolveCb;
-    if (aResolveCallback) {
-      resolveCb = new WrapperPromiseCallback(global, aResolveCallback,
-                                             newPromiseObj,
-                                             resolveFunc, rejectFunc);
-    } else {
-      resolveCb = new InvokePromiseFuncCallback(global, newPromiseObj,
-                                                resolveFunc);
-    }
-
-    RefPtr<PromiseCallback> rejectCb;
-    if (aRejectCallback) {
-      rejectCb = new WrapperPromiseCallback(global, aRejectCallback,
-                                            newPromiseObj,
-                                            resolveFunc, rejectFunc);
-    } else {
-      rejectCb = new InvokePromiseFuncCallback(global, newPromiseObj,
-                                               rejectFunc);
-    }
-
-    AppendCallbacks(resolveCb, rejectCb);
-  }
-
-  aRetval.set(capability.PromiseValue());
-}
-
-void
-Promise::Catch(JSContext* aCx, AnyCallback* aRejectCallback,
-               JS::MutableHandle<JS::Value> aRetval,
-               ErrorResult& aRv)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  // Implements
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-promise.prototype.catch
-
-  // We can't call Promise::Then directly, because someone might have
-  // overridden Promise.prototype.then.
-  JS::Rooted<JS::Value> promiseVal(aCx, JS::ObjectValue(*GetWrapper()));
-  if (!MaybeWrapObjectValue(aCx, &promiseVal)) {
-    aRv.NoteJSContextException(aCx);
-    return;
-  }
-  JS::Rooted<JSObject*> promiseObj(aCx, &promiseVal.toObject());
-  MOZ_ASSERT(promiseObj);
-  JS::AutoValueArray<2> callbacks(aCx);
-  callbacks[0].setUndefined();
-  if (aRejectCallback) {
-    callbacks[1].setObject(*aRejectCallback->Callable());
-    // It could be in any compartment, so put it in ours.
-    if (!MaybeWrapObjectValue(aCx, callbacks[1])) {
-      aRv.NoteJSContextException(aCx);
-      return;
-    }
-  } else {
-    callbacks[1].setNull();
-  }
-  if (!JS_CallFunctionName(aCx, promiseObj, "then", callbacks, aRetval)) {
-    aRv.NoteJSContextException(aCx);
-  }
-}
-
-/**
- * The CountdownHolder class encapsulates Promise.all countdown functions and
- * the countdown holder parts of the Promises spec. It maintains the result
- * array and AllResolveElementFunctions use SetValue() to set the array indices.
- */
-class CountdownHolder final : public nsISupports
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CountdownHolder)
-
-  CountdownHolder(const GlobalObject& aGlobal, Promise* aPromise,
-                  uint32_t aCountdown)
-    : mPromise(aPromise), mCountdown(aCountdown)
-  {
-    MOZ_ASSERT(aCountdown != 0);
-    JSContext* cx = aGlobal.Context();
-
-    // The only time aGlobal.Context() and aGlobal.Get() are not
-    // same-compartment is when we're called via Xrays, and in that situation we
-    // in fact want to create the array in the callee compartment
-
-    JSAutoCompartment ac(cx, aGlobal.Get());
-    mValues = JS_NewArrayObject(cx, aCountdown);
-    mozilla::HoldJSObjects(this);
-  }
-
-private:
-  ~CountdownHolder()
-  {
-    mozilla::DropJSObjects(this);
-  }
-
-public:
-  void SetValue(uint32_t index, const JS::Handle<JS::Value> aValue)
-  {
-    MOZ_ASSERT(mCountdown > 0);
-
-    AutoJSAPI jsapi;
-    if (!jsapi.Init(mValues)) {
-      return;
-    }
-    JSContext* cx = jsapi.cx();
-
-    JS::Rooted<JS::Value> value(cx, aValue);
-    JS::Rooted<JSObject*> values(cx, mValues);
-    if (!JS_WrapValue(cx, &value) ||
-        !JS_DefineElement(cx, values, index, value, JSPROP_ENUMERATE)) {
-      MOZ_ASSERT(JS_IsExceptionPending(cx));
-      JS::Rooted<JS::Value> exn(cx);
-      if (!jsapi.StealException(&exn)) {
-        mPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
-      } else {
-        mPromise->MaybeReject(cx, exn);
-      }
-    }
-
-    --mCountdown;
-    if (mCountdown == 0) {
-      JS::Rooted<JS::Value> result(cx, JS::ObjectValue(*mValues));
-      mPromise->MaybeResolve(cx, result);
-    }
-  }
-
-private:
-  RefPtr<Promise> mPromise;
-  uint32_t mCountdown;
-  JS::Heap<JSObject*> mValues;
-};
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(CountdownHolder)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(CountdownHolder)
-NS_IMPL_CYCLE_COLLECTION_CLASS(CountdownHolder)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CountdownHolder)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CountdownHolder)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mValues)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CountdownHolder)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CountdownHolder)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
-  tmp->mValues = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-/**
- * An AllResolveElementFunction is the per-promise
- * part of the Promise.all() algorithm.
- * Every Promise in the handler is handed an instance of this as a resolution
- * handler and it sets the relevant index in the CountdownHolder.
- */
-class AllResolveElementFunction final : public PromiseNativeHandler
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(AllResolveElementFunction)
-
-  AllResolveElementFunction(CountdownHolder* aHolder, uint32_t aIndex)
-    : mCountdownHolder(aHolder), mIndex(aIndex)
-  {
-    MOZ_ASSERT(aHolder);
-  }
-
-  void
-  ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
-  {
-    mCountdownHolder->SetValue(mIndex, aValue);
-  }
-
-  void
-  RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
-  {
-    // Should never be attached to Promise as a reject handler.
-    MOZ_CRASH("AllResolveElementFunction should never be attached to a Promise's reject handler!");
-  }
-
-private:
-  ~AllResolveElementFunction()
-  {
-  }
-
-  RefPtr<CountdownHolder> mCountdownHolder;
-  uint32_t mIndex;
-};
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(AllResolveElementFunction)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(AllResolveElementFunction)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AllResolveElementFunction)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION(AllResolveElementFunction, mCountdownHolder)
-
-static const JSClass PromiseAllDataHolderClass = {
-  "PromiseAllDataHolder", JSCLASS_HAS_RESERVED_SLOTS(3)
-};
-
-// Slot indices for objects of class PromiseAllDataHolderClass.
-#define DATA_HOLDER_REMAINING_ELEMENTS_SLOT 0
-#define DATA_HOLDER_VALUES_ARRAY_SLOT 1
-#define DATA_HOLDER_RESOLVE_FUNCTION_SLOT 2
-
-// Slot indices for PromiseAllResolveElement.
-// The RESOLVE_ELEMENT_INDEX_SLOT stores our index unless we've already been
-// called.  Then it stores INT32_MIN (which is never a valid index value).
-#define RESOLVE_ELEMENT_INDEX_SLOT 0
-// The RESOLVE_ELEMENT_DATA_HOLDER_SLOT slot stores an object of class
-// PromiseAllDataHolderClass.
-#define RESOLVE_ELEMENT_DATA_HOLDER_SLOT 1
-
-static bool
-PromiseAllResolveElement(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
-{
-  // Implements
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-promise.all-resolve-element-functions
-  //
-  // See the big comment about compartments in Promise::All "Substep 4" that
-  // explains what compartments the various stuff here lives in.
-  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
-
-  // Step 1.
-  int32_t index =
-    js::GetFunctionNativeReserved(&args.callee(),
-                                  RESOLVE_ELEMENT_INDEX_SLOT).toInt32();
-  // Step 2.
-  if (index == INT32_MIN) {
-    args.rval().setUndefined();
-    return true;
-  }
-
-  // Step 3.
-  js::SetFunctionNativeReserved(&args.callee(),
-                                RESOLVE_ELEMENT_INDEX_SLOT,
-                                JS::Int32Value(INT32_MIN));
-
-  // Step 4 already done.
-
-  // Step 5.
-  JS::Rooted<JSObject*> dataHolder(aCx,
-    &js::GetFunctionNativeReserved(&args.callee(),
-                                   RESOLVE_ELEMENT_DATA_HOLDER_SLOT).toObject());
-
-  JS::Rooted<JS::Value> values(aCx,
-    js::GetReservedSlot(dataHolder, DATA_HOLDER_VALUES_ARRAY_SLOT));
-
-  // Step 6, effectively.
-  JS::Rooted<JS::Value> resolveFunc(aCx,
-    js::GetReservedSlot(dataHolder, DATA_HOLDER_RESOLVE_FUNCTION_SLOT));
-
-  // Step 7.
-  int32_t remainingElements =
-    js::GetReservedSlot(dataHolder, DATA_HOLDER_REMAINING_ELEMENTS_SLOT).toInt32();
-
-  // Step 8.
-  JS::Rooted<JSObject*> valuesObj(aCx, &values.toObject());
-  if (!JS_DefineElement(aCx, valuesObj, index, args.get(0), JSPROP_ENUMERATE)) {
-    return false;
-  }
-
-  // Step 9.
-  remainingElements -= 1;
-  js::SetReservedSlot(dataHolder, DATA_HOLDER_REMAINING_ELEMENTS_SLOT,
-                      JS::Int32Value(remainingElements));
-
-  // Step 10.
-  if (remainingElements == 0) {
-    return JS::Call(aCx, JS::UndefinedHandleValue, resolveFunc,
-                    JS::HandleValueArray(values), args.rval());
-  }
-
-  // Step 11.
-  args.rval().setUndefined();
-  return true;
-}
-
-
-/* static */ void
-Promise::All(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-             JS::Handle<JS::Value> aIterable,
-             JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)
-{
-  // Implements http://www.ecma-international.org/ecma-262/6.0/#sec-promise.all
-  nsCOMPtr<nsIGlobalObject> global =
-    do_QueryInterface(aGlobal.GetAsSupports());
-  if (!global) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  JSContext* cx = aGlobal.Context();
-
-  // Steps 1-5: nothing to do.  Note that the @@species bits got removed in
-  // https://github.com/tc39/ecma262/pull/211
-
-  // Step 6.
-  PromiseCapability capability(cx);
-  NewPromiseCapability(cx, global, aThisv, true, capability, aRv);
-  // Step 7.
-  if (aRv.Failed()) {
-    return;
-  }
-
-  MOZ_ASSERT(aThisv.isObject(), "How did NewPromiseCapability succeed?");
-  JS::Rooted<JSObject*> constructorObj(cx, &aThisv.toObject());
-
-  // After this point we have a useful promise value in "capability", so just go
-  // ahead and put it in our retval now.  Every single return path below would
-  // want to do that anyway.
-  aRetval.set(capability.PromiseValue());
-  if (!MaybeWrapValue(cx, aRetval)) {
-    aRv.NoteJSContextException(cx);
-    return;
-  }
-
-  // The arguments we're going to be passing to "then" on each loop iteration.
-  // The second one we know already; the first one will be created on each
-  // iteration of the loop.
-  JS::AutoValueArray<2> callbackFunctions(cx);
-  callbackFunctions[1].set(capability.mReject);
-
-  // Steps 8 and 9.
-  JS::ForOfIterator iter(cx);
-  if (!iter.init(aIterable, JS::ForOfIterator::AllowNonIterable)) {
-    capability.RejectWithException(cx, aRv);
-    return;
-  }
-
-  if (!iter.valueIsIterable()) {
-    ThrowErrorMessage(cx, MSG_PROMISE_ARG_NOT_ITERABLE,
-                      "Argument of Promise.all");
-    capability.RejectWithException(cx, aRv);
-    return;
-  }
-
-  // Step 10 doesn't need to be done, because ForOfIterator handles it
-  // for us.
-
-  // Now we jump over to
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-performpromiseall
-  // and do its steps.
-
-  // Substep 4. Create our data holder that holds all the things shared across
-  // every step of the iterator.  In particular, this holds the
-  // remainingElementsCount (as an integer reserved slot), the array of values,
-  // and the resolve function from our PromiseCapability.
-  //
-  // We have to be very careful about which compartments we create things in
-  // here.  In particular, we have to maintain the invariant that anything
-  // stored in a reserved slot is same-compartment with the object whose
-  // reserved slot it's in.  But we want to create the values array in the
-  // Promise reflector compartment, because that array can get exposed to code
-  // that has access to the Promise reflector (in particular code from that
-  // compartment), and that should work, even if the Promise reflector
-  // compartment is less-privileged than our caller compartment.
-  //
-  // So the plan is as follows: Create the values array in the promise reflector
-  // compartment.  Create the PromiseAllResolveElement function and the data
-  // holder in our current compartment.  Store a cross-compartment wrapper to
-  // the values array in the holder.  This should be OK because the only things
-  // we hand the PromiseAllResolveElement function to are the "then" calls we do
-  // and in the case when the reflector compartment is not the current
-  // compartment those are happening over Xrays anyway, which means they get the
-  // canonical "then" function and content can't see our
-  // PromiseAllResolveElement.
-  JS::Rooted<JSObject*> dataHolder(cx);
-  dataHolder = JS_NewObjectWithGivenProto(cx, &PromiseAllDataHolderClass,
-                                          nullptr);
-  if (!dataHolder) {
-    capability.RejectWithException(cx, aRv);
-    return;
-  }
-
-  JS::Rooted<JSObject*> reflectorGlobal(cx, global->GetGlobalJSObject());
-  JS::Rooted<JSObject*> valuesArray(cx);
-  { // Scope for JSAutoCompartment.
-    JSAutoCompartment ac(cx, reflectorGlobal);
-    valuesArray = JS_NewArrayObject(cx, 0);
-  }
-  if (!valuesArray) {
-    // It's important that we've exited the JSAutoCompartment by now, before
-    // calling RejectWithException and possibly invoking capability.mReject.
-    capability.RejectWithException(cx, aRv);
-    return;
-  }
-
-  // The values array as a value we can pass to a function in our current
-  // compartment, or store in the holder's reserved slot.
-  JS::Rooted<JS::Value> valuesArrayVal(cx, JS::ObjectValue(*valuesArray));
-  if (!MaybeWrapObjectValue(cx, &valuesArrayVal)) {
-    capability.RejectWithException(cx, aRv);
-    return;
-  }
-
-  js::SetReservedSlot(dataHolder, DATA_HOLDER_REMAINING_ELEMENTS_SLOT,
-                      JS::Int32Value(1));
-  js::SetReservedSlot(dataHolder, DATA_HOLDER_VALUES_ARRAY_SLOT,
-                      valuesArrayVal);
-  js::SetReservedSlot(dataHolder, DATA_HOLDER_RESOLVE_FUNCTION_SLOT,
-                      capability.mResolve);
-
-  // Substep 5.
-  CheckedInt32 index = 0;
-
-  // Substep 6.
-  JS::Rooted<JS::Value> nextValue(cx);
-  while (true) {
-    bool done;
-    // Steps a, b, c, e, f, g.
-    if (!iter.next(&nextValue, &done)) {
-      capability.RejectWithException(cx, aRv);
-      return;
-    }
-
-    // Step d.
-    if (done) {
-      int32_t remainingCount =
-        js::GetReservedSlot(dataHolder,
-                            DATA_HOLDER_REMAINING_ELEMENTS_SLOT).toInt32();
-      remainingCount -= 1;
-      if (remainingCount == 0) {
-        JS::Rooted<JS::Value> ignored(cx);
-        if (!JS::Call(cx, JS::UndefinedHandleValue, capability.mResolve,
-                      JS::HandleValueArray(valuesArrayVal), &ignored)) {
-          capability.RejectWithException(cx, aRv);
-        }
-        return;
-      }
-      js::SetReservedSlot(dataHolder, DATA_HOLDER_REMAINING_ELEMENTS_SLOT,
-                          JS::Int32Value(remainingCount));
-      // We're all set for now!
-      return;
-    }
-
-    // Step h.
-    { // Scope for the JSAutoCompartment we need to work with valuesArray.  We
-      // mostly do this for performance; we could go ahead and do the define via
-      // a cross-compartment proxy instead...
-      JSAutoCompartment ac(cx, valuesArray);
-      if (!JS_DefineElement(cx, valuesArray, index.value(),
-                            JS::UndefinedHandleValue, JSPROP_ENUMERATE)) {
-        // Have to go back into the caller compartment before we try to touch
-        // capability.mReject.  Luckily, capability.mReject is guaranteed to be
-        // an object in the right compartment here.
-        JSAutoCompartment ac2(cx, &capability.mReject.toObject());
-        capability.RejectWithException(cx, aRv);
-        return;
-      }
-    }
-
-    // Step i.  Sadly, we can't take a shortcut here even if
-    // capability.mNativePromise exists, because someone could have overridden
-    // "resolve" on the canonical Promise constructor.
-    JS::Rooted<JS::Value> nextPromise(cx);
-    if (!JS_CallFunctionName(cx, constructorObj, "resolve",
-                             JS::HandleValueArray(nextValue),
-                             &nextPromise)) {
-      // Step j.
-      capability.RejectWithException(cx, aRv);
-      return;
-    }
-
-    // Step k.
-    JS::Rooted<JSObject*> resolveElement(cx);
-    JSFunction* resolveFunc =
-      js::NewFunctionWithReserved(cx, PromiseAllResolveElement,
-                                  1 /* nargs */, 0 /* flags */, nullptr);
-    if (!resolveFunc) {
-      capability.RejectWithException(cx, aRv);
-      return;
-    }
-
-    resolveElement = JS_GetFunctionObject(resolveFunc);
-    // Steps l-p.
-    js::SetFunctionNativeReserved(resolveElement,
-                                  RESOLVE_ELEMENT_INDEX_SLOT,
-                                  JS::Int32Value(index.value()));
-    js::SetFunctionNativeReserved(resolveElement,
-                                  RESOLVE_ELEMENT_DATA_HOLDER_SLOT,
-                                  JS::ObjectValue(*dataHolder));
-
-    // Step q.
-    int32_t remainingElements =
-      js::GetReservedSlot(dataHolder, DATA_HOLDER_REMAINING_ELEMENTS_SLOT).toInt32();
-    js::SetReservedSlot(dataHolder, DATA_HOLDER_REMAINING_ELEMENTS_SLOT,
-                        JS::Int32Value(remainingElements + 1));
-
-    // Step r.  And now we don't know whether nextPromise has an overridden
-    // "then" method, so no shortcuts here either.
-    callbackFunctions[0].setObject(*resolveElement);
-    JS::Rooted<JSObject*> nextPromiseObj(cx);
-    JS::Rooted<JS::Value> ignored(cx);
-    if (!JS_ValueToObject(cx, nextPromise, &nextPromiseObj) ||
-        !JS_CallFunctionName(cx, nextPromiseObj, "then", callbackFunctions,
-                             &ignored)) {
-      // Step s.
-      capability.RejectWithException(cx, aRv);
-    }
-
-    // Step t.
-    index += 1;
-    if (!index.isValid()) {
-      // Let's just claim OOM.
-      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-      capability.RejectWithException(cx, aRv);
-    }
-  }
-}
-
-/* static */ already_AddRefed<Promise>
-Promise::All(const GlobalObject& aGlobal,
-             const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv)
-{
-  nsCOMPtr<nsIGlobalObject> global =
-    do_QueryInterface(aGlobal.GetAsSupports());
-  if (!global) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  JSContext* cx = aGlobal.Context();
-
-  if (aPromiseList.IsEmpty()) {
-    JS::Rooted<JSObject*> empty(cx, JS_NewArrayObject(cx, 0));
-    if (!empty) {
-      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-      return nullptr;
-    }
-    JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*empty));
-    // We know "value" is not a promise, so call the Resolve function
-    // that doesn't have to check for that.
-    return Promise::Resolve(global, cx, value, aRv);
-  }
-
-  RefPtr<Promise> promise = Create(global, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  RefPtr<CountdownHolder> holder =
-    new CountdownHolder(aGlobal, promise, aPromiseList.Length());
-
-  JS::Rooted<JSObject*> obj(cx, JS::CurrentGlobalOrNull(cx));
-  if (!obj) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise, obj);
-
-  for (uint32_t i = 0; i < aPromiseList.Length(); ++i) {
-    RefPtr<PromiseNativeHandler> resolveHandler =
-      new AllResolveElementFunction(holder, i);
-
-    RefPtr<PromiseCallback> resolveCb =
-      new NativePromiseCallback(resolveHandler, Resolved);
-
-    // Every promise gets its own resolve callback, which will set the right
-    // index in the array to the resolution value.
-    aPromiseList[i]->AppendCallbacks(resolveCb, rejectCb);
-  }
-
-  return promise.forget();
-}
-
-/* static */ void
-Promise::Race(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-              JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
-              ErrorResult& aRv)
-{
-  // Implements http://www.ecma-international.org/ecma-262/6.0/#sec-promise.race
-  nsCOMPtr<nsIGlobalObject> global =
-    do_QueryInterface(aGlobal.GetAsSupports());
-  if (!global) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  JSContext* cx = aGlobal.Context();
-
-  // Steps 1-5: nothing to do.  Note that the @@species bits got removed in
-  // https://github.com/tc39/ecma262/pull/211
-  PromiseCapability capability(cx);
-
-  // Step 6.
-  NewPromiseCapability(cx, global, aThisv, true, capability, aRv);
-  // Step 7.
-  if (aRv.Failed()) {
-    return;
-  }
-
-  MOZ_ASSERT(aThisv.isObject(), "How did NewPromiseCapability succeed?");
-  JS::Rooted<JSObject*> constructorObj(cx, &aThisv.toObject());
-
-  // After this point we have a useful promise value in "capability", so just go
-  // ahead and put it in our retval now.  Every single return path below would
-  // want to do that anyway.
-  aRetval.set(capability.PromiseValue());
-  if (!MaybeWrapValue(cx, aRetval)) {
-    aRv.NoteJSContextException(cx);
-    return;
-  }
-
-  // The arguments we're going to be passing to "then" on each loop iteration.
-  JS::AutoValueArray<2> callbackFunctions(cx);
-  callbackFunctions[0].set(capability.mResolve);
-  callbackFunctions[1].set(capability.mReject);
-
-  // Steps 8 and 9.
-  JS::ForOfIterator iter(cx);
-  if (!iter.init(aIterable, JS::ForOfIterator::AllowNonIterable)) {
-    capability.RejectWithException(cx, aRv);
-    return;
-  }
-
-  if (!iter.valueIsIterable()) {
-    ThrowErrorMessage(cx, MSG_PROMISE_ARG_NOT_ITERABLE,
-                      "Argument of Promise.race");
-    capability.RejectWithException(cx, aRv);
-    return;
-  }
-
-  // Step 10 doesn't need to be done, because ForOfIterator handles it
-  // for us.
-
-  // Now we jump over to
-  // http://www.ecma-international.org/ecma-262/6.0/#sec-performpromiserace
-  // and do its steps.
-  JS::Rooted<JS::Value> nextValue(cx);
-  while (true) {
-    bool done;
-    // Steps a, b, c, e, f, g.
-    if (!iter.next(&nextValue, &done)) {
-      capability.RejectWithException(cx, aRv);
-      return;
-    }
-
-    // Step d.
-    if (done) {
-      // We're all set!
-      return;
-    }
-
-    // Step h.  Sadly, we can't take a shortcut here even if
-    // capability.mNativePromise exists, because someone could have overridden
-    // "resolve" on the canonical Promise constructor.
-    JS::Rooted<JS::Value> nextPromise(cx);
-    if (!JS_CallFunctionName(cx, constructorObj, "resolve",
-                             JS::HandleValueArray(nextValue), &nextPromise)) {
-      // Step i.
-      capability.RejectWithException(cx, aRv);
-      return;
-    }
-
-    // Step j.  And now we don't know whether nextPromise has an overridden
-    // "then" method, so no shortcuts here either.
-    JS::Rooted<JSObject*> nextPromiseObj(cx);
-    JS::Rooted<JS::Value> ignored(cx);
-    if (!JS_ValueToObject(cx, nextPromise, &nextPromiseObj) ||
-        !JS_CallFunctionName(cx, nextPromiseObj, "then", callbackFunctions,
-                             &ignored)) {
-      // Step k.
-      capability.RejectWithException(cx, aRv);
-    }
-  }
-}
-
-/* static */
-bool
-Promise::PromiseSpecies(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
-{
-  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
-  args.rval().set(args.thisv());
-  return true;
-}
-
-void
-Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  RefPtr<PromiseCallback> resolveCb =
-    new NativePromiseCallback(aRunnable, Resolved);
-
-  RefPtr<PromiseCallback> rejectCb =
-    new NativePromiseCallback(aRunnable, Rejected);
-
-  AppendCallbacks(resolveCb, rejectCb);
-}
-
-#endif // SPIDERMONKEY_PROMISE
-
 JSObject*
 Promise::GlobalJSObject() const
 {
   return mGlobal->GetGlobalJSObject();
 }
 
 JSCompartment*
 Promise::Compartment() const
 {
   return js::GetObjectCompartment(GlobalJSObject());
 }
 
-#ifndef SPIDERMONKEY_PROMISE
-void
-Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
-                         PromiseCallback* aRejectCallback)
-{
-  if (!mGlobal || mGlobal->IsDying()) {
-    return;
-  }
-
-  MOZ_ASSERT(aResolveCallback);
-  MOZ_ASSERT(aRejectCallback);
-
-  if (mIsLastInChain && mState == PromiseState::Rejected) {
-    // This rejection is now consumed.
-    PromiseDebugging::AddConsumedRejection(*this);
-    // Note that we may not have had the opportunity to call
-    // RunResolveTask() yet, so we may never have called
-    // `PromiseDebugging:AddUncaughtRejection`.
-  }
-  mIsLastInChain = false;
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  // Now that there is a callback, we don't need to report anymore.
-  mHadRejectCallback = true;
-  RemoveWorkerHolder();
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
-  mResolveCallbacks.AppendElement(aResolveCallback);
-  mRejectCallbacks.AppendElement(aRejectCallback);
-
-  // If promise's state is fulfilled, queue a task to process our fulfill
-  // callbacks with promise's result. If promise's state is rejected, queue a
-  // task to process our reject callbacks with promise's result.
-  if (mState != Pending) {
-    TriggerPromiseReactions();
-  }
-}
-#endif // SPIDERMONKEY_PROMISE
-
-#ifndef SPIDERMONKEY_PROMISE
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-void
-Promise::MaybeReportRejected()
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  if (mState != Rejected || mHadRejectCallback || mResult.isUndefined()) {
-    return;
-  }
-
-  AutoJSAPI jsapi;
-  // We may not have a usable global by now (if it got unlinked
-  // already), so don't init with it.
-  jsapi.Init();
-  JSContext* cx = jsapi.cx();
-  JS::Rooted<JSObject*> obj(cx, GetWrapper());
-  MOZ_ASSERT(obj); // We preserve our wrapper, so should always have one here.
-  JS::Rooted<JS::Value> val(cx, mResult);
-
-  JSAutoCompartment ac(cx, obj);
-  if (!JS_WrapValue(cx, &val)) {
-    JS_ClearPendingException(cx);
-    return;
-  }
-
-  js::ErrorReport report(cx);
-  RefPtr<Exception> exp;
-  bool isObject = val.isObject();
-  if (!isObject || NS_FAILED(UNWRAP_OBJECT(Exception, &val.toObject(), exp))) {
-    if (!isObject ||
-        NS_FAILED(UNWRAP_OBJECT(DOMException, &val.toObject(), exp))) {
-      if (!report.init(cx, val, js::ErrorReport::NoSideEffects)) {
-        NS_WARNING("Couldn't convert the unhandled rejected value to an exception.");
-        JS_ClearPendingException(cx);
-        return;
-      }
-    }
-  }
-
-  RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
-  bool isMainThread = MOZ_LIKELY(NS_IsMainThread());
-  bool isChrome = isMainThread ? nsContentUtils::IsSystemPrincipal(nsContentUtils::ObjectPrincipal(obj))
-                               : GetCurrentThreadWorkerPrivate()->IsChromeWorker();
-  nsGlobalWindow* win = isMainThread ? xpc::WindowGlobalOrNull(obj) : nullptr;
-  uint64_t windowID = win ? win->AsInner()->WindowID() : 0;
-  if (exp) {
-    xpcReport->Init(cx, exp, isChrome, windowID);
-  } else {
-    xpcReport->Init(report.report(), report.toStringResult(),
-                    isChrome, windowID);
-  }
-
-  // Now post an event to do the real reporting async
-  // Since Promises preserve their wrapper, it is essential to RefPtr<> the
-  // AsyncErrorReporter, otherwise if the call to DispatchToMainThread fails, it
-  // will leak. See Bug 958684.  So... don't use DispatchToMainThread()
-  nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
-  if (NS_WARN_IF(!mainThread)) {
-    // Would prefer NS_ASSERTION, but that causes failure in xpcshell tests
-    NS_WARNING("!!! Trying to report rejected Promise after MainThread shutdown");
-  }
-  if (mainThread) {
-    RefPtr<AsyncErrorReporter> r = new AsyncErrorReporter(xpcReport);
-    mainThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
-  }
-}
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
-void
-Promise::MaybeResolveInternal(JSContext* aCx,
-                              JS::Handle<JS::Value> aValue)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  if (mResolvePending) {
-    return;
-  }
-
-  ResolveInternal(aCx, aValue);
-}
-
-void
-Promise::MaybeRejectInternal(JSContext* aCx,
-                             JS::Handle<JS::Value> aValue)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  if (mResolvePending) {
-    return;
-  }
-
-  RejectInternal(aCx, aValue);
-}
-
-void
-Promise::HandleException(JSContext* aCx)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  JS::Rooted<JS::Value> exn(aCx);
-  if (JS_GetPendingException(aCx, &exn)) {
-    JS_ClearPendingException(aCx);
-    RejectInternal(aCx, exn);
-  }
-}
-
-void
-Promise::ResolveInternal(JSContext* aCx,
-                         JS::Handle<JS::Value> aValue)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
-
-  mResolvePending = true;
-
-  if (aValue.isObject()) {
-    JS::Rooted<JSObject*> valueObj(aCx, &aValue.toObject());
-
-    // Thenables.
-    JS::Rooted<JS::Value> then(aCx);
-    if (!JS_GetProperty(aCx, valueObj, "then", &then)) {
-      HandleException(aCx);
-      return;
-    }
-
-    if (then.isObject() && JS::IsCallable(&then.toObject())) {
-      // This is the then() function of the thenable aValueObj.
-      JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
-
-      // We used to have a fast path here for the case when the following
-      // requirements held:
-      //
-      // 1) valueObj is a Promise.
-      // 2) thenObj is a JSFunction backed by our actual Promise::Then
-      //    implementation.
-      //
-      // But now that we're doing subclassing in Promise.prototype.then we would
-      // also need the following requirements:
-      //
-      // 3) Getting valueObj.constructor has no side-effects.
-      // 4) Getting valueObj.constructor[@@species] has no side-effects.
-      // 5) valueObj.constructor[@@species] is a function and calling it has no
-      //    side-effects (e.g. it's the canonical Promise constructor) and it
-      //    provides some callback functions to call as arguments to its
-      //    argument.
-      //
-      // Ensuring that stuff while not inside SpiderMonkey is painful, so let's
-      // drop the fast path for now.
-
-      RefPtr<PromiseInit> thenCallback =
-        new PromiseInit(nullptr, thenObj, mozilla::dom::GetIncumbentGlobal());
-      RefPtr<PromiseResolveThenableJob> task =
-        new PromiseResolveThenableJob(this, valueObj, thenCallback);
-      context->DispatchToMicroTask(task.forget());
-      return;
-    }
-  }
-
-  MaybeSettle(aValue, Resolved);
-}
-
-void
-Promise::RejectInternal(JSContext* aCx,
-                        JS::Handle<JS::Value> aValue)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  mResolvePending = true;
-
-  MaybeSettle(aValue, Rejected);
-}
-
-void
-Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
-{
-  MOZ_ASSERT(mGlobal,
-             "We really should have a global here.  Except we sometimes don't "
-             "in the wild for some odd reason");
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  if (!mGlobal || mGlobal->IsDying()) {
-    return;
-  }
-
-  mSettlementTimestamp = TimeStamp::Now();
-
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  JSContext* cx = jsapi.cx();
-  JS::RootedObject wrapper(cx, GetWrapper());
-  MOZ_ASSERT(wrapper); // We preserved it
-  JSAutoCompartment ac(cx, wrapper);
-
-  JS::Rooted<JS::Value> value(cx, aValue);
-
-  if (!JS_WrapValue(cx, &value)) {
-    JS_ClearPendingException(cx);
-    value = JS::UndefinedValue();
-  }
-  SetResult(value);
-  SetState(aState);
-
-  JS::dbg::onPromiseSettled(cx, wrapper);
-
-  if (aState == PromiseState::Rejected &&
-      mIsLastInChain) {
-    // The Promise has just been rejected, and it is last in chain.
-    // We need to inform PromiseDebugging.
-    // If the Promise is eventually not the last in chain anymore,
-    // we will need to inform PromiseDebugging again.
-    PromiseDebugging::AddUncaughtRejection(*this);
-  }
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  // If the Promise was rejected, and there is no reject handler already setup,
-  // watch for thread shutdown.
-  if (aState == PromiseState::Rejected &&
-      !mHadRejectCallback &&
-      !NS_IsMainThread()) {
-    WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
-    MOZ_ASSERT(worker);
-    worker->AssertIsOnWorkerThread();
-
-    mWorkerHolder = new PromiseReportRejectWorkerHolder(this);
-    if (NS_WARN_IF(!mWorkerHolder->HoldWorker(worker, Closing))) {
-      mWorkerHolder = nullptr;
-      // Worker is shutting down, report rejection immediately since it is
-      // unlikely that reject callbacks will be added after this point.
-      MaybeReportRejectedOnce();
-    }
-  }
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
-  TriggerPromiseReactions();
-}
-
-void
-Promise::MaybeSettle(JS::Handle<JS::Value> aValue,
-                     PromiseState aState)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  // Promise.all() or Promise.race() implementations will repeatedly call
-  // Resolve/RejectInternal rather than using the Maybe... forms. Stop SetState
-  // from asserting.
-  if (mState != Pending) {
-    return;
-  }
-
-  Settle(aValue, aState);
-}
-
-void
-Promise::TriggerPromiseReactions()
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  CycleCollectedJSContext* runtime = CycleCollectedJSContext::Get();
-
-  nsTArray<RefPtr<PromiseCallback>> callbacks;
-  callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
-                                            : mRejectCallbacks);
-  mResolveCallbacks.Clear();
-  mRejectCallbacks.Clear();
-
-  for (uint32_t i = 0; i < callbacks.Length(); ++i) {
-    RefPtr<PromiseReactionJob> task =
-      new PromiseReactionJob(this, callbacks[i], mResult);
-    runtime->DispatchToMicroTask(task.forget());
-  }
-}
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-void
-Promise::RemoveWorkerHolder()
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  // The DTOR of this WorkerHolder will release the worker for us.
-  mWorkerHolder = nullptr;
-}
-
-bool
-PromiseReportRejectWorkerHolder::Notify(Status aStatus)
-{
-  MOZ_ASSERT(aStatus > Running);
-  mPromise->MaybeReportRejectedOnce();
-  // After this point, `this` has been deleted by RemoveWorkerHolder!
-  return true;
-}
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
-bool
-Promise::CaptureStack(JSContext* aCx, JS::Heap<JSObject*>& aTarget)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  JS::Rooted<JSObject*> stack(aCx);
-  if (!JS::CaptureCurrentStack(aCx, &stack)) {
-    return false;
-  }
-  aTarget = stack;
-  return true;
-}
-
-void
-Promise::GetDependentPromises(nsTArray<RefPtr<Promise>>& aPromises)
-{
-  NS_ASSERT_OWNINGTHREAD(Promise);
-
-  // We want to return promises that correspond to then() calls, Promise.all()
-  // calls, and Promise.race() calls.
-  //
-  // For the then() case, we have both resolve and reject callbacks that know
-  // what the next promise is.
-  //
-  // For the race() case, likewise.
-  //
-  // For the all() case, our reject callback knows what the next promise is, but
-  // our resolve callback just knows it needs to notify some
-  // PromiseNativeHandler, which itself only has an indirect relationship to the
-  // next promise.
-  //
-  // So we walk over our _reject_ callbacks and ask each of them what promise
-  // its dependent promise is.
-  for (size_t i = 0; i < mRejectCallbacks.Length(); ++i) {
-    Promise* p = mRejectCallbacks[i]->GetDependentPromise();
-    if (p) {
-      aPromises.AppendElement(p);
-    }
-  }
-}
-
-#endif // SPIDERMONKEY_PROMISE
-
 // A WorkerRunnable to resolve/reject the Promise on the worker thread.
 // Calling thread MUST hold PromiseWorkerProxy's mutex before creating this.
 class PromiseWorkerProxyRunnable : public WorkerRunnable
 {
 public:
   PromiseWorkerProxyRunnable(PromiseWorkerProxy* aPromiseWorkerProxy,
                              PromiseWorkerProxy::RunCallbackFunc aFunc)
     : WorkerRunnable(aPromiseWorkerProxy->GetWorkerPrivate(),
@@ -3225,45 +945,27 @@ template<>
 void Promise::MaybeRejectBrokenly(const RefPtr<DOMError>& aArg) {
   MaybeSomething(aArg, &Promise::MaybeReject);
 }
 template<>
 void Promise::MaybeRejectBrokenly(const nsAString& aArg) {
   MaybeSomething(aArg, &Promise::MaybeReject);
 }
 
-#ifndef SPIDERMONKEY_PROMISE
-uint64_t
-Promise::GetID() {
-  if (mID != 0) {
-    return mID;
-  }
-  return mID = ++gIDGenerator;
-}
-#endif // SPIDERMONKEY_PROMISE
-
-#ifndef SPIDERMONKEY_PROMISE
-Promise::PromiseState
-Promise::State() const
-{
-  return mState;
-}
-#else // SPIDERMONKEY_PROMISE
 Promise::PromiseState
 Promise::State() const
 {
   JS::Rooted<JSObject*> p(RootingCx(), PromiseObj());
   const JS::PromiseState state = JS::GetPromiseState(p);
 
   if (state == JS::PromiseState::Fulfilled) {
       return PromiseState::Resolved;
   }
 
   if (state == JS::PromiseState::Rejected) {
       return PromiseState::Rejected;
   }
 
   return PromiseState::Pending;
 }
-#endif // SPIDERMONKEY_PROMISE
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -16,117 +16,54 @@
 #include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/WeakPtr.h"
 #include "nsWrapperCache.h"
 #include "nsAutoPtr.h"
 #include "js/TypeDecls.h"
 #include "jspubtd.h"
 
-// Bug 1083361 introduces a new mechanism for tracking uncaught
-// rejections. This #define serves to track down the parts of code
-// that need to be removed once clients have been put together
-// to take advantage of the new mechanism. New code should not
-// depend on code #ifdefed to this #define.
-#define DOM_PROMISE_DEPRECATED_REPORTING !SPIDERMONKEY_PROMISE
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-#include "mozilla/dom/workers/bindings/WorkerHolder.h"
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
 class nsIGlobalObject;
 
 namespace mozilla {
 namespace dom {
 
 class AnyCallback;
 class DOMError;
 class MediaStreamError;
-class PromiseCallback;
 class PromiseInit;
 class PromiseNativeHandler;
 class PromiseDebugging;
 
-class Promise;
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-class PromiseReportRejectWorkerHolder : public workers::WorkerHolder
-{
-  // PromiseReportRejectWorkerHolder is held by an nsAutoPtr on the Promise
-  // which means that this object will be destroyed before the Promise is
-  // destroyed.
-  Promise* MOZ_NON_OWNING_REF mPromise;
-
-public:
-  explicit PromiseReportRejectWorkerHolder(Promise* aPromise)
-    : mPromise(aPromise)
-  {
-    MOZ_ASSERT(mPromise);
-  }
-
-  virtual bool
-  Notify(workers::Status aStatus) override;
-};
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
 #define NS_PROMISE_IID \
   { 0x1b8d6215, 0x3e67, 0x43ba, \
     { 0x8a, 0xf9, 0x31, 0x5e, 0x8f, 0xce, 0x75, 0x65 } }
 
 class Promise : public nsISupports,
-#ifndef SPIDERMONKEY_PROMISE
-                // Only wrappercached when we're not using SpiderMonkey
-                // promises, because those don't have a useful object moved
-                // hook, which wrappercache needs.
-                public nsWrapperCache,
-#endif // SPIDERMONKEY_PROMISE
                 public SupportsWeakPtr<Promise>
 {
-  friend class NativePromiseCallback;
-  friend class PromiseReactionJob;
-  friend class PromiseResolverTask;
   friend class PromiseTask;
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  friend class PromiseReportRejectWorkerHolder;
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
   friend class PromiseWorkerProxy;
   friend class PromiseWorkerProxyRunnable;
-  friend class RejectPromiseCallback;
-  friend class ResolvePromiseCallback;
-  friend class PromiseResolveThenableJob;
-  friend class FastPromiseResolveThenableJob;
-  friend class WrapperPromiseCallback;
 
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROMISE_IID)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-#ifdef SPIDERMONKEY_PROMISE
-  // We're not skippable, since we're not owned from JS to start with.
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
-#else // SPIDERMONKEY_PROMISE
-  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(Promise)
-#endif // SPIDERMONKEY_PROMISE
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Promise)
 
   // 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.
-#ifdef SPIDERMONKEY_PROMISE
   static already_AddRefed<Promise>
   Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
 
   // Reports a rejected Promise by sending an error report.
   static void ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise);
-#else
-  static already_AddRefed<Promise>
-  Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
-         // Passing null for aDesiredProto will use Promise.prototype.
-         JS::Handle<JSObject*> aDesiredProto = nullptr);
-#endif // SPIDERMONKEY_PROMISE
 
   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);
@@ -178,17 +115,16 @@ public:
 
   // WebIDL
 
   nsIGlobalObject* GetParentObject() const
   {
     return mGlobal;
   }
 
-#ifdef SPIDERMONKEY_PROMISE
   bool
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
              JS::MutableHandle<JSObject*> aWrapper);
 
   // Do the equivalent of Promise.resolve in the current compartment of aCx.
   // Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this
   // function MUST return a non-null value.
   static already_AddRefed<Promise>
@@ -215,105 +151,27 @@ public:
        JS::MutableHandle<JS::Value> aRetval,
        ErrorResult& aRv);
 
   JSObject* PromiseObj() const
   {
     return mPromiseObj;
   }
 
-#else // SPIDERMONKEY_PROMISE
-  JSObject* PromiseObj()
-  {
-    return GetWrapper();
-  }
-
-  virtual JSObject*
-  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-  static already_AddRefed<Promise>
-  Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
-              ErrorResult& aRv, JS::Handle<JSObject*> aDesiredProto);
-
-  static void
-  Resolve(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-          JS::Handle<JS::Value> aValue,
-          JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
-
-  static already_AddRefed<Promise>
-  Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
-          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
-
-  static void
-  Reject(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-         JS::Handle<JS::Value> aValue,
-         JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
-
-  static already_AddRefed<Promise>
-  Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
-         JS::Handle<JS::Value> aValue, ErrorResult& aRv);
-
-  void
-  Then(JSContext* aCx,
-       // aCalleeGlobal may not be in the compartment of aCx, when called over
-       // Xrays.
-       JS::Handle<JSObject*> aCalleeGlobal,
-       AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
-       JS::MutableHandle<JS::Value> aRetval,
-       ErrorResult& aRv);
-
-  void
-  Catch(JSContext* aCx,
-        AnyCallback* aRejectCallback,
-        JS::MutableHandle<JS::Value> aRetval,
-        ErrorResult& aRv);
-
-  static void
-  All(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-      JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
-      ErrorResult& aRv);
-
-  static already_AddRefed<Promise>
-  All(const GlobalObject& aGlobal,
-      const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv);
-
-  static void
-  Race(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
-       JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
-       ErrorResult& aRv);
-
-  static bool
-  PromiseSpecies(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
-#endif // SPIDERMONKEY_PROMISE
-
   void AppendNativeHandler(PromiseNativeHandler* aRunnable);
 
   JSObject* GlobalJSObject() const;
 
   JSCompartment* Compartment() const;
 
-#ifndef SPIDERMONKEY_PROMISE
-  // Return a unique-to-the-process identifier for this Promise.
-  uint64_t GetID();
-#endif // SPIDERMONKEY_PROMISE
-
-#ifndef SPIDERMONKEY_PROMISE
-  enum JSCallbackSlots {
-    SLOT_PROMISE = 0,
-    SLOT_DATA
-  };
-#endif // SPIDERMONKEY_PROMISE
-
-#ifdef SPIDERMONKEY_PROMISE
   // Create a dom::Promise from a given SpiderMonkey Promise object.
   // aPromiseObj MUST be in the compartment of aGlobal's global JS object.
   static already_AddRefed<Promise>
   CreateFromExisting(nsIGlobalObject* aGlobal,
                      JS::Handle<JSObject*> aPromiseObj);
-#endif // SPIDERMONKEY_PROMISE
 
   enum class PromiseState {
     Pending,
     Resolved,
     Rejected
   };
 
   PromiseState State() const;
@@ -327,211 +185,38 @@ protected:
   explicit Promise(nsIGlobalObject* aGlobal);
 
   virtual ~Promise();
 
   // Do JS-wrapping after Promise creation.  Passing null for aDesiredProto will
   // use the default prototype for the sort of Promise we have.
   void CreateWrapper(JS::Handle<JSObject*> aDesiredProto, ErrorResult& aRv);
 
-#ifndef SPIDERMONKEY_PROMISE
-  // Create the JS resolving functions of resolve() and reject(). And provide
-  // references to the two functions by calling PromiseInit passed from Promise
-  // constructor.
-  void CallInitFunction(const GlobalObject& aGlobal, PromiseInit& aInit,
-                        ErrorResult& aRv);
-
-  // The NewPromiseCapability function from
-  // <http://www.ecma-international.org/ecma-262/6.0/#sec-newpromisecapability>.
-  // Errors are communicated via aRv.  If aForceCallbackCreation is
-  // true, then this function will ensure that aCapability has a
-  // useful mResolve/mReject even if mNativePromise is non-null.
-  static void NewPromiseCapability(JSContext* aCx, nsIGlobalObject* aGlobal,
-                                   JS::Handle<JS::Value> aConstructor,
-                                   bool aForceCallbackCreation,
-                                   PromiseCapability& aCapability,
-                                   ErrorResult& aRv);
-
-  bool IsPending()
-  {
-    return mResolvePending;
-  }
-
-  void GetDependentPromises(nsTArray<RefPtr<Promise>>& aPromises);
-
-  bool IsLastInChain() const
-  {
-    return mIsLastInChain;
-  }
-
-  void SetNotifiedAsUncaught()
-  {
-    mWasNotifiedAsUncaught = true;
-  }
-
-  bool WasNotifiedAsUncaught() const
-  {
-    return mWasNotifiedAsUncaught;
-  }
-#endif // SPIDERMONKEY_PROMISE
-
 private:
-#ifndef SPIDERMONKEY_PROMISE
-  friend class PromiseDebugging;
-
-  void SetState(PromiseState aState)
-  {
-    MOZ_ASSERT(mState == Pending);
-    MOZ_ASSERT(aState != Pending);
-    mState = aState;
-  }
-
-  void SetResult(JS::Handle<JS::Value> aValue)
-  {
-    mResult = aValue;
-  }
-
-  // This method enqueues promise's resolve/reject callbacks with promise's
-  // result. It's executed when the resolver.resolve() or resolver.reject() is
-  // called or when the promise already has a result and new callbacks are
-  // appended by then() or catch().
-  void TriggerPromiseReactions();
-
-  void Settle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);
-  void MaybeSettle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);
-
-  void AppendCallbacks(PromiseCallback* aResolveCallback,
-                       PromiseCallback* aRejectCallback);
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  // If we have been rejected and our mResult is a JS exception,
-  // report it to the error console.
-  // Use MaybeReportRejectedOnce() for actual calls.
-  void MaybeReportRejected();
-
-  void MaybeReportRejectedOnce() {
-    MaybeReportRejected();
-    RemoveWorkerHolder();
-    mResult.setUndefined();
-  }
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
-  void MaybeResolveInternal(JSContext* aCx,
-                            JS::Handle<JS::Value> aValue);
-  void MaybeRejectInternal(JSContext* aCx,
-                           JS::Handle<JS::Value> aValue);
-
-  void ResolveInternal(JSContext* aCx,
-                       JS::Handle<JS::Value> aValue);
-  void RejectInternal(JSContext* aCx,
-                      JS::Handle<JS::Value> aValue);
-#endif // SPIDERMONKEY_PROMISE
-
   template <typename T>
   void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
     MOZ_ASSERT(PromiseObj()); // It was preserved!
 
     AutoEntryScript aes(mGlobal, "Promise resolution or rejection");
     JSContext* cx = aes.cx();
 
     JS::Rooted<JS::Value> val(cx);
     if (!ToJSValue(cx, aArgument, &val)) {
       HandleException(cx);
       return;
     }
 
     (this->*aFunc)(cx, val);
   }
 
-#ifndef SPIDERMONKEY_PROMISE
-  // Static methods for the PromiseInit functions.
-  static bool
-  JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
-
-  static bool
-  ThenableResolverCommon(JSContext* aCx, uint32_t /* PromiseCallback::Task */ aTask,
-                         unsigned aArgc, JS::Value* aVp);
-  static bool
-  JSCallbackThenableResolver(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
-  static bool
-  JSCallbackThenableRejecter(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
-
-  static JSObject*
-  CreateFunction(JSContext* aCx, Promise* aPromise, int32_t aTask);
-
-  static JSObject*
-  CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask);
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  void RemoveWorkerHolder();
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
-  // Capture the current stack and store it in aTarget.  If false is
-  // returned, an exception is presumably pending on aCx.
-  bool CaptureStack(JSContext* aCx, JS::Heap<JSObject*>& aTarget);
-#endif // SPIDERMONKEY_PROMISE
-
   void HandleException(JSContext* aCx);
 
   RefPtr<nsIGlobalObject> mGlobal;
 
-#ifndef SPIDERMONKEY_PROMISE
-  nsTArray<RefPtr<PromiseCallback> > mResolveCallbacks;
-  nsTArray<RefPtr<PromiseCallback> > mRejectCallbacks;
-
-  JS::Heap<JS::Value> mResult;
-  // A stack that shows where this promise was allocated, if there was
-  // JS running at the time.  Otherwise null.
-  JS::Heap<JSObject*> mAllocationStack;
-  // mRejectionStack is only set when the promise is rejected directly from
-  // script, by calling Promise.reject() or the rejection callback we pass to
-  // the PromiseInit function.  Promises that are rejected internally do not
-  // have a rejection stack.
-  JS::Heap<JSObject*> mRejectionStack;
-  // mFullfillmentStack is only set when the promise is fulfilled directly from
-  // script, by calling Promise.resolve() or the fulfillment callback we pass to
-  // the PromiseInit function.  Promises that are fulfilled internally do not
-  // have a fulfillment stack.
-  JS::Heap<JSObject*> mFullfillmentStack;
-  PromiseState mState;
-
-#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
-  bool mHadRejectCallback;
-
-  // If a rejected promise on a worker has no reject callbacks attached, it
-  // needs to know when the worker is shutting down, to report the error on the
-  // console before the worker's context is deleted. This feature is used for
-  // that purpose.
-  nsAutoPtr<PromiseReportRejectWorkerHolder> mWorkerHolder;
-#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
-
-  bool mTaskPending;
-  bool mResolvePending;
-
-  // `true` if this Promise is the last in the chain, or `false` if
-  // another Promise has been created from this one by a call to
-  // `then`, `all`, `race`, etc.
-  bool mIsLastInChain;
-
-  // `true` if PromiseDebugging has already notified at least one observer that
-  // this promise was left uncaught, `false` otherwise.
-  bool mWasNotifiedAsUncaught;
-
-  // The time when this promise was created.
-  TimeStamp mCreationTimestamp;
-
-  // The time when this promise transitioned out of the pending state.
-  TimeStamp mSettlementTimestamp;
-
-  // Once `GetID()` has been called, a unique-to-the-process identifier for this
-  // promise. Until then, `0`.
-  uint64_t mID;
-#else // SPIDERMONKEY_PROMISE
   JS::Heap<JSObject*> mPromiseObj;
-#endif // SPIDERMONKEY_PROMISE
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(Promise, NS_PROMISE_IID)
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Promise_h
deleted file mode 100644
--- a/dom/promise/PromiseCallback.cpp
+++ /dev/null
@@ -1,575 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "PromiseCallback.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/PromiseNativeHandler.h"
-
-#include "jsapi.h"
-#include "jsfriendapi.h"
-#include "jswrapper.h"
-
-namespace mozilla {
-namespace dom {
-
-#ifndef SPIDERMONKEY_PROMISE
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_0(PromiseCallback)
-
-PromiseCallback::PromiseCallback()
-{
-}
-
-PromiseCallback::~PromiseCallback()
-{
-}
-
-// ResolvePromiseCallback
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(ResolvePromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ResolvePromiseCallback,
-                                                PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
-  tmp->mGlobal = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ResolvePromiseCallback,
-                                                  PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResolvePromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ResolvePromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(ResolvePromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(ResolvePromiseCallback, PromiseCallback)
-
-ResolvePromiseCallback::ResolvePromiseCallback(Promise* aPromise,
-                                               JS::Handle<JSObject*> aGlobal)
-  : mPromise(aPromise)
-  , mGlobal(aGlobal)
-{
-  MOZ_ASSERT(aPromise);
-  MOZ_ASSERT(aGlobal);
-  HoldJSObjects(this);
-}
-
-ResolvePromiseCallback::~ResolvePromiseCallback()
-{
-  DropJSObjects(this);
-}
-
-nsresult
-ResolvePromiseCallback::Call(JSContext* aCx,
-                             JS::Handle<JS::Value> aValue)
-{
-  // Run resolver's algorithm with value and the synchronous flag set.
-
-  JS::ExposeValueToActiveJS(aValue);
-
-  JSAutoCompartment ac(aCx, mGlobal);
-  JS::Rooted<JS::Value> value(aCx, aValue);
-  if (!JS_WrapValue(aCx, &value)) {
-    NS_WARNING("Failed to wrap value into the right compartment.");
-    return NS_ERROR_FAILURE;
-  }
-
-  mPromise->ResolveInternal(aCx, value);
-  return NS_OK;
-}
-
-// RejectPromiseCallback
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(RejectPromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RejectPromiseCallback,
-                                                PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
-  tmp->mGlobal = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RejectPromiseCallback,
-                                                  PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(RejectPromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(RejectPromiseCallback,
-                                               PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_ADDREF_INHERITED(RejectPromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(RejectPromiseCallback, PromiseCallback)
-
-RejectPromiseCallback::RejectPromiseCallback(Promise* aPromise,
-                                             JS::Handle<JSObject*> aGlobal)
-  : mPromise(aPromise)
-  , mGlobal(aGlobal)
-{
-  MOZ_ASSERT(aPromise);
-  MOZ_ASSERT(mGlobal);
-  HoldJSObjects(this);
-}
-
-RejectPromiseCallback::~RejectPromiseCallback()
-{
-  DropJSObjects(this);
-}
-
-nsresult
-RejectPromiseCallback::Call(JSContext* aCx,
-                            JS::Handle<JS::Value> aValue)
-{
-  // Run resolver's algorithm with value and the synchronous flag set.
-
-  JS::ExposeValueToActiveJS(aValue);
-
-  JSAutoCompartment ac(aCx, mGlobal);
-  JS::Rooted<JS::Value> value(aCx, aValue);
-  if (!JS_WrapValue(aCx, &value)) {
-    NS_WARNING("Failed to wrap value into the right compartment.");
-    return NS_ERROR_FAILURE;
-  }
-
-
-  mPromise->RejectInternal(aCx, value);
-  return NS_OK;
-}
-
-// InvokePromiseFuncCallback
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(InvokePromiseFuncCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(InvokePromiseFuncCallback,
-                                                PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromiseFunc)
-  tmp->mGlobal = nullptr;
-  tmp->mNextPromiseObj = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InvokePromiseFuncCallback,
-                                                  PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromiseFunc)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(InvokePromiseFuncCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(InvokePromiseFuncCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
-
-InvokePromiseFuncCallback::InvokePromiseFuncCallback(JS::Handle<JSObject*> aGlobal,
-                                                     JS::Handle<JSObject*> aNextPromiseObj,
-                                                     AnyCallback* aPromiseFunc)
-  : mGlobal(aGlobal)
-  , mNextPromiseObj(aNextPromiseObj)
-  , mPromiseFunc(aPromiseFunc)
-{
-  MOZ_ASSERT(aGlobal);
-  MOZ_ASSERT(aNextPromiseObj);
-  MOZ_ASSERT(aPromiseFunc);
-  HoldJSObjects(this);
-}
-
-InvokePromiseFuncCallback::~InvokePromiseFuncCallback()
-{
-  DropJSObjects(this);
-}
-
-nsresult
-InvokePromiseFuncCallback::Call(JSContext* aCx,
-                                JS::Handle<JS::Value> aValue)
-{
-  // Run resolver's algorithm with value and the synchronous flag set.
-
-  JS::ExposeValueToActiveJS(aValue);
-
-  JSAutoCompartment ac(aCx, mGlobal);
-  JS::Rooted<JS::Value> value(aCx, aValue);
-  if (!JS_WrapValue(aCx, &value)) {
-    NS_WARNING("Failed to wrap value into the right compartment.");
-    return NS_ERROR_FAILURE;
-  }
-
-  ErrorResult rv;
-  JS::Rooted<JS::Value> ignored(aCx);
-  mPromiseFunc->Call(value, &ignored, rv);
-  // Useful exceptions already got reported.
-  rv.SuppressException();
-  return NS_OK;
-}
-
-Promise*
-InvokePromiseFuncCallback::GetDependentPromise()
-{
-  Promise* promise;
-  if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
-    return promise;
-  }
-
-  // Oh, well.
-  return nullptr;
-}
-
-// WrapperPromiseCallback
-NS_IMPL_CYCLE_COLLECTION_CLASS(WrapperPromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WrapperPromiseCallback,
-                                                PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mNextPromise)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveFunc)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectFunc)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
-  tmp->mGlobal = nullptr;
-  tmp->mNextPromiseObj = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WrapperPromiseCallback,
-                                                  PromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNextPromise)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveFunc)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectFunc)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WrapperPromiseCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WrapperPromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(WrapperPromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(WrapperPromiseCallback, PromiseCallback)
-
-WrapperPromiseCallback::WrapperPromiseCallback(Promise* aNextPromise,
-                                               JS::Handle<JSObject*> aGlobal,
-                                               AnyCallback* aCallback)
-  : mNextPromise(aNextPromise)
-  , mGlobal(aGlobal)
-  , mCallback(aCallback)
-{
-  MOZ_ASSERT(aNextPromise);
-  MOZ_ASSERT(aGlobal);
-  HoldJSObjects(this);
-}
-
-WrapperPromiseCallback::WrapperPromiseCallback(JS::Handle<JSObject*> aGlobal,
-                                               AnyCallback* aCallback,
-                                               JS::Handle<JSObject*> aNextPromiseObj,
-                                               AnyCallback* aResolveFunc,
-                                               AnyCallback* aRejectFunc)
-  : mNextPromiseObj(aNextPromiseObj)
-  , mResolveFunc(aResolveFunc)
-  , mRejectFunc(aRejectFunc)
-  , mGlobal(aGlobal)
-  , mCallback(aCallback)
-{
-  MOZ_ASSERT(mNextPromiseObj);
-  MOZ_ASSERT(aResolveFunc);
-  MOZ_ASSERT(aRejectFunc);
-  MOZ_ASSERT(aGlobal);
-  HoldJSObjects(this);
-}
-
-WrapperPromiseCallback::~WrapperPromiseCallback()
-{
-  DropJSObjects(this);
-}
-
-nsresult
-WrapperPromiseCallback::Call(JSContext* aCx,
-                             JS::Handle<JS::Value> aValue)
-{
-  JS::ExposeValueToActiveJS(aValue);
-
-  JSAutoCompartment ac(aCx, mGlobal);
-  JS::Rooted<JS::Value> value(aCx, aValue);
-  if (!JS_WrapValue(aCx, &value)) {
-    NS_WARNING("Failed to wrap value into the right compartment.");
-    return NS_ERROR_FAILURE;
-  }
-
-  ErrorResult rv;
-
-  // PromiseReactionTask step 6
-  JS::Rooted<JS::Value> retValue(aCx);
-  JSCompartment* compartment;
-  if (mNextPromise) {
-    compartment = mNextPromise->Compartment();
-  } else {
-    MOZ_ASSERT(mNextPromiseObj);
-    compartment = js::GetObjectCompartment(mNextPromiseObj);
-  }
-  mCallback->Call(value, &retValue, rv, "promise callback",
-                  CallbackObject::eRethrowExceptions,
-                  compartment);
-
-  rv.WouldReportJSException();
-
-  // PromiseReactionTask step 7
-  if (rv.Failed()) {
-    if (rv.IsUncatchableException()) {
-      // We have nothing to resolve/reject the promise with.
-      return rv.StealNSResult();
-    }
-
-    JS::Rooted<JS::Value> value(aCx);
-    { // Scope for JSAutoCompartment
-      // Convert the ErrorResult to a JS exception object that we can reject
-      // ourselves with.  This will be exactly the exception that would get
-      // thrown from a binding method whose ErrorResult ended up with whatever
-      // is on "rv" right now.  Do this in the promise reflector compartment.
-      Maybe<JSAutoCompartment> ac;
-      if (mNextPromise) {
-        ac.emplace(aCx, mNextPromise->GlobalJSObject());
-      } else {
-        ac.emplace(aCx, mNextPromiseObj);
-      }
-      DebugOnly<bool> conversionResult = ToJSValue(aCx, rv, &value);
-      MOZ_ASSERT(conversionResult);
-    }
-
-    if (mNextPromise) {
-      mNextPromise->RejectInternal(aCx, value);
-    } else {
-      JS::Rooted<JS::Value> ignored(aCx);
-      ErrorResult rejectRv;
-      mRejectFunc->Call(value, &ignored, rejectRv);
-      // This reported any JS exceptions; we just have a pointless exception on
-      // there now.
-      rejectRv.SuppressException();
-    }
-    return NS_OK;
-  }
-
-  // If the return value is the same as the promise itself, throw TypeError.
-  if (retValue.isObject()) {
-    JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
-    valueObj = js::CheckedUnwrap(valueObj);
-    JS::Rooted<JSObject*> nextPromiseObj(aCx);
-    if (mNextPromise) {
-      nextPromiseObj = mNextPromise->GetWrapper();
-    } else {
-      MOZ_ASSERT(mNextPromiseObj);
-      nextPromiseObj = mNextPromiseObj;
-    }
-    // XXXbz shouldn't this check be over in ResolveInternal anyway?
-    if (valueObj == nextPromiseObj) {
-      const char* fileName = nullptr;
-      uint32_t lineNumber = 0;
-
-      // Try to get some information about the callback to report a sane error,
-      // but don't try too hard (only deals with scripted functions).
-      JS::Rooted<JSObject*> unwrapped(aCx,
-        js::CheckedUnwrap(mCallback->Callback()));
-
-      if (unwrapped) {
-        JSAutoCompartment ac(aCx, unwrapped);
-        if (JS_ObjectIsFunction(aCx, unwrapped)) {
-          JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped));
-          JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue));
-
-          MOZ_ASSERT(func);
-          JSScript* script = JS_GetFunctionScript(aCx, func);
-          if (script) {
-            fileName = JS_GetScriptFilename(script);
-            lineNumber = JS_GetScriptBaseLineNumber(aCx, script);
-          }
-        }
-      }
-
-      // We're back in aValue's compartment here.
-      JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName));
-      if (!fn) {
-        // Out of memory. Promise will stay unresolved.
-        JS_ClearPendingException(aCx);
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-
-      JS::Rooted<JSString*> message(aCx,
-        JS_NewStringCopyZ(aCx,
-          "then() cannot return same Promise that it resolves."));
-      if (!message) {
-        // Out of memory. Promise will stay unresolved.
-        JS_ClearPendingException(aCx);
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-
-      JS::Rooted<JS::Value> typeError(aCx);
-      if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, fn, lineNumber, 0,
-                           nullptr, message, &typeError)) {
-        // Out of memory. Promise will stay unresolved.
-        JS_ClearPendingException(aCx);
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-
-      if (mNextPromise) {
-        mNextPromise->RejectInternal(aCx, typeError);
-      } else {
-        JS::Rooted<JS::Value> ignored(aCx);
-        ErrorResult rejectRv;
-        mRejectFunc->Call(typeError, &ignored, rejectRv);
-        // This reported any JS exceptions; we just have a pointless exception
-        // on there now.
-        rejectRv.SuppressException();
-      }
-      return NS_OK;
-    }
-  }
-
-  // Otherwise, run resolver's resolve with value.
-  if (!JS_WrapValue(aCx, &retValue)) {
-    NS_WARNING("Failed to wrap value into the right compartment.");
-    return NS_ERROR_FAILURE;
-  }
-
-  if (mNextPromise) {
-    mNextPromise->ResolveInternal(aCx, retValue);
-  } else {
-    JS::Rooted<JS::Value> ignored(aCx);
-    ErrorResult resolveRv;
-    mResolveFunc->Call(retValue, &ignored, resolveRv);
-    // This reported any JS exceptions; we just have a pointless exception
-    // on there now.
-    resolveRv.SuppressException();
-  }
-    
-  return NS_OK;
-}
-
-Promise*
-WrapperPromiseCallback::GetDependentPromise()
-{
-  // Per spec, various algorithms like all() and race() are actually implemented
-  // in terms of calling then() but passing it the resolve/reject functions that
-  // are passed as arguments to function passed to the Promise constructor.
-  // That will cause the promise in question to hold on to a
-  // WrapperPromiseCallback, but the dependent promise should really be the one
-  // whose constructor those functions came from, not the about-to-be-ignored
-  // return value of "then".  So try to determine whether we're in that case and
-  // if so go ahead and dig the dependent promise out of the function we have.
-  JSObject* callable = mCallback->Callable();
-  // Unwrap it, in case it's a cross-compartment wrapper.  Our caller here is
-  // system, so it's really ok to just go and unwrap.
-  callable = js::UncheckedUnwrap(callable);
-  if (JS_IsNativeFunction(callable, Promise::JSCallback)) {
-    JS::Value promiseVal =
-      js::GetFunctionNativeReserved(callable, Promise::SLOT_PROMISE);
-    Promise* promise;
-    UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
-    return promise;
-  }
-
-  if (mNextPromise) {
-    return mNextPromise;
-  }
-
-  Promise* promise;
-  if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
-    return promise;
-  }
-
-  // Oh, well.
-  return nullptr;
-}
-
-// NativePromiseCallback
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(NativePromiseCallback,
-                                   PromiseCallback, mHandler)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(NativePromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(NativePromiseCallback, PromiseCallback)
-
-NativePromiseCallback::NativePromiseCallback(PromiseNativeHandler* aHandler,
-                                             Promise::PromiseState aState)
-  : mHandler(aHandler)
-  , mState(aState)
-{
-  MOZ_ASSERT(aHandler);
-}
-
-NativePromiseCallback::~NativePromiseCallback()
-{
-}
-
-nsresult
-NativePromiseCallback::Call(JSContext* aCx,
-                            JS::Handle<JS::Value> aValue)
-{
-  JS::ExposeValueToActiveJS(aValue);
-
-  if (mState == Promise::Resolved) {
-    mHandler->ResolvedCallback(aCx, aValue);
-    return NS_OK;
-  }
-
-  if (mState == Promise::Rejected) {
-    mHandler->RejectedCallback(aCx, aValue);
-    return NS_OK;
-  }
-
-  NS_NOTREACHED("huh?");
-  return NS_ERROR_FAILURE;
-}
-
-/* static */ PromiseCallback*
-PromiseCallback::Factory(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
-                         AnyCallback* aCallback, Task aTask)
-{
-  MOZ_ASSERT(aNextPromise);
-
-  // If we have a callback and a next resolver, we have to exec the callback and
-  // then propagate the return value to the next resolver->resolve().
-  if (aCallback) {
-    return new WrapperPromiseCallback(aNextPromise, aGlobal, aCallback);
-  }
-
-  if (aTask == Resolve) {
-    return new ResolvePromiseCallback(aNextPromise, aGlobal);
-  }
-
-  if (aTask == Reject) {
-    return new RejectPromiseCallback(aNextPromise, aGlobal);
-  }
-
-  MOZ_ASSERT(false, "This should not happen");
-  return nullptr;
-}
-
-#endif // SPIDERMONKEY_PROMISE
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/promise/PromiseCallback.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_PromiseCallback_h
-#define mozilla_dom_PromiseCallback_h
-
-#include "mozilla/dom/Promise.h"
-#include "nsCycleCollectionParticipant.h"
-
-namespace mozilla {
-namespace dom {
-
-#ifndef SPIDERMONKEY_PROMISE
-// This is the base class for any PromiseCallback.
-// It's a logical step in the promise chain of callbacks.
-class PromiseCallback : public nsISupports
-{
-protected:
-  virtual ~PromiseCallback();
-
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(PromiseCallback)
-
-  PromiseCallback();
-
-  virtual nsresult Call(JSContext* aCx,
-                        JS::Handle<JS::Value> aValue) = 0;
-
-  // Return the Promise that this callback will end up resolving or
-  // rejecting, if any.
-  virtual Promise* GetDependentPromise() = 0;
-
-  enum Task {
-    Resolve,
-    Reject
-  };
-
-  // This factory returns a PromiseCallback object with refcount of 0.
-  static PromiseCallback*
-  Factory(Promise* aNextPromise, JS::Handle<JSObject*> aObject,
-          AnyCallback* aCallback, Task aTask);
-};
-
-// WrapperPromiseCallback execs a JS Callback with a value, and then the return
-// value is sent to either:
-// a) If aNextPromise is non-null, the aNextPromise->ResolveFunction() or to
-//    aNextPromise->RejectFunction() if the JS Callback throws.
-// or
-// b) If aNextPromise is null, in which case aResolveFunc and aRejectFunc must
-//    be non-null, then to aResolveFunc, unless aCallback threw, in which case
-//    aRejectFunc.
-class WrapperPromiseCallback final : public PromiseCallback
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WrapperPromiseCallback,
-                                                         PromiseCallback)
-
-  nsresult Call(JSContext* aCx,
-                JS::Handle<JS::Value> aValue) override;
-
-  Promise* GetDependentPromise() override;
-
-  // Constructor for when we know we have a vanilla Promise.
-  WrapperPromiseCallback(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
-                         AnyCallback* aCallback);
-
-  // Constructor for when all we have to work with are resolve/reject functions.
-  WrapperPromiseCallback(JS::Handle<JSObject*> aGlobal,
-                         AnyCallback* aCallback,
-                         JS::Handle<JSObject*> mNextPromiseObj,
-                         AnyCallback* aResolveFunc,
-                         AnyCallback* aRejectFunc);
-
-private:
-  ~WrapperPromiseCallback();
-
-  // Either mNextPromise is non-null or all three of mNextPromiseObj,
-  // mResolveFund and mRejectFunc must are non-null.
-  RefPtr<Promise> mNextPromise;
-  // mNextPromiseObj is the reflector itself; it may not be in the
-  // same compartment as anything else we have.
-  JS::Heap<JSObject*> mNextPromiseObj;
-  RefPtr<AnyCallback> mResolveFunc;
-  RefPtr<AnyCallback> mRejectFunc;
-  JS::Heap<JSObject*> mGlobal;
-  RefPtr<AnyCallback> mCallback;
-};
-
-// ResolvePromiseCallback calls aPromise->ResolveFunction() with the value
-// received by Call().
-class ResolvePromiseCallback final : public PromiseCallback
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ResolvePromiseCallback,
-                                                         PromiseCallback)
-
-  nsresult Call(JSContext* aCx,
-                JS::Handle<JS::Value> aValue) override;
-
-  Promise* GetDependentPromise() override
-  {
-    return mPromise;
-  }
-
-  ResolvePromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
-
-private:
-  ~ResolvePromiseCallback();
-
-  RefPtr<Promise> mPromise;
-  JS::Heap<JSObject*> mGlobal;
-};
-
-// RejectPromiseCallback calls aPromise->RejectFunction() with the value
-// received by Call().
-class RejectPromiseCallback final : public PromiseCallback
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RejectPromiseCallback,
-                                                         PromiseCallback)
-
-  nsresult Call(JSContext* aCx,
-                JS::Handle<JS::Value> aValue) override;
-
-  Promise* GetDependentPromise() override
-  {
-    return mPromise;
-  }
-
-  RejectPromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
-
-private:
-  ~RejectPromiseCallback();
-
-  RefPtr<Promise> mPromise;
-  JS::Heap<JSObject*> mGlobal;
-};
-
-// InvokePromiseFuncCallback calls the given function with the value
-// received by Call().
-class InvokePromiseFuncCallback final : public PromiseCallback
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(InvokePromiseFuncCallback,
-                                                         PromiseCallback)
-
-  nsresult Call(JSContext* aCx,
-                JS::Handle<JS::Value> aValue) override;
-
-  Promise* GetDependentPromise() override;
-
-  InvokePromiseFuncCallback(JS::Handle<JSObject*> aGlobal,
-                            JS::Handle<JSObject*> aNextPromiseObj,
-                            AnyCallback* aPromiseFunc);
-
-private:
-  ~InvokePromiseFuncCallback();
-
-  JS::Heap<JSObject*> mGlobal;
-  JS::Heap<JSObject*> mNextPromiseObj;
-  RefPtr<AnyCallback> mPromiseFunc;
-};
-
-// NativePromiseCallback wraps a PromiseNativeHandler.
-class NativePromiseCallback final : public PromiseCallback
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback,
-                                           PromiseCallback)
-
-  nsresult Call(JSContext* aCx,
-                JS::Handle<JS::Value> aValue) override;
-
-  Promise* GetDependentPromise() override
-  {
-    return nullptr;
-  }
-
-  NativePromiseCallback(PromiseNativeHandler* aHandler,
-                        Promise::PromiseState aState);
-
-private:
-  ~NativePromiseCallback();
-
-  RefPtr<PromiseNativeHandler> mHandler;
-  Promise::PromiseState mState;
-};
-
-#endif // SPIDERMONKEY_PROMISE
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_PromiseCallback_h
--- a/dom/promise/PromiseDebugging.cpp
+++ b/dom/promise/PromiseDebugging.cpp
@@ -61,30 +61,16 @@ private:
   // `true` if an instance of `FlushRejections` is currently dispatched
   // and has not been executed yet.
   static MOZ_THREAD_LOCAL(bool) sDispatched;
 };
 
 /* static */ MOZ_THREAD_LOCAL(bool)
 FlushRejections::sDispatched;
 
-#ifndef SPIDERMONKEY_PROMISE
-static Promise*
-UnwrapPromise(JS::Handle<JSObject*> aPromise, ErrorResult& aRv)
-{
-  Promise* promise;
-  if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Promise, aPromise, promise)))) {
-    aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING("Argument"));
-    return nullptr;
-  }
-  return promise;
-}
-#endif // SPIDERMONKEY_PROMISE
-
-#ifdef SPIDERMONKEY_PROMISE
 /* static */ void
 PromiseDebugging::GetState(GlobalObject& aGlobal, JS::Handle<JSObject*> aPromise,
                            PromiseDebuggingStateHolder& aState,
                            ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
   JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(aPromise));
   if (!obj || !JS::IsPromiseObject(obj)) {
@@ -168,44 +154,16 @@ PromiseDebugging::GetFullfillmentStack(G
   if (!obj || !JS::IsPromiseObject(obj)) {
     aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING(
         "Argument of PromiseDebugging.getFulfillmentStack"));
     return;
   }
   aStack.set(JS::GetPromiseResolutionSite(obj));
 }
 
-#else
-
-/* static */ void
-PromiseDebugging::GetState(GlobalObject&, JS::Handle<JSObject*> aPromise,
-                           PromiseDebuggingStateHolder& aState,
-                           ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-  switch (promise->mState) {
-  case Promise::Pending:
-    aState.mState = PromiseDebuggingState::Pending;
-    break;
-  case Promise::Resolved:
-    aState.mState = PromiseDebuggingState::Fulfilled;
-    aState.mValue = promise->mResult;
-    break;
-  case Promise::Rejected:
-    aState.mState = PromiseDebuggingState::Rejected;
-    aState.mReason = promise->mResult;
-    break;
-  }
-}
-
-#endif // SPIDERMONKEY_PROMISE
-
 /*static */ nsString
 PromiseDebugging::sIDPrefix;
 
 /* static */ void
 PromiseDebugging::Init()
 {
   FlushRejections::Init();
 
@@ -227,96 +185,16 @@ PromiseDebugging::Shutdown()
 
 /* static */ void
 PromiseDebugging::FlushUncaughtRejections()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   FlushRejections::FlushSync();
 }
 
-#ifndef SPIDERMONKEY_PROMISE
-
-/* static */ void
-PromiseDebugging::GetAllocationStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
-                                     JS::MutableHandle<JSObject*> aStack,
-                                     ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-  aStack.set(promise->mAllocationStack);
-}
-
-/* static */ void
-PromiseDebugging::GetRejectionStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
-                                    JS::MutableHandle<JSObject*> aStack,
-                                    ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-  aStack.set(promise->mRejectionStack);
-}
-
-/* static */ void
-PromiseDebugging::GetFullfillmentStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
-                                       JS::MutableHandle<JSObject*> aStack,
-                                       ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-  aStack.set(promise->mFullfillmentStack);
-}
-
-/* static */ void
-PromiseDebugging::GetDependentPromises(GlobalObject&, JS::Handle<JSObject*> aPromise,
-                                       nsTArray<RefPtr<Promise>>& aPromises,
-                                       ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-  promise->GetDependentPromises(aPromises);
-}
-
-/* static */ double
-PromiseDebugging::GetPromiseLifetime(GlobalObject&,
-                                     JS::Handle<JSObject*> aPromise,
-                                     ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return 0;
-  }
-  return (TimeStamp::Now() - promise->mCreationTimestamp).ToMilliseconds();
-}
-
-/* static */ double
-PromiseDebugging::GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
-                                  ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return 0;
-  }
-  if (promise->mState == Promise::Pending) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return 0;
-  }
-  return (promise->mSettlementTimestamp -
-          promise->mCreationTimestamp).ToMilliseconds();
-}
-
-#endif // SPIDERMONKEY_PROMISE
-
 /* static */ void
 PromiseDebugging::AddUncaughtRejectionObserver(GlobalObject&,
                                                UncaughtRejectionObserver& aObserver)
 {
   CycleCollectedJSContext* storage = CycleCollectedJSContext::Get();
   nsTArray<nsCOMPtr<nsISupports>>& observers = storage->mUncaughtRejectionObservers;
   observers.AppendElement(&aObserver);
 }
@@ -332,18 +210,16 @@ PromiseDebugging::RemoveUncaughtRejectio
     if (*observer == aObserver) {
       observers.RemoveElementAt(i);
       return true;
     }
   }
   return false;
 }
 
-#ifdef SPIDERMONKEY_PROMISE
-
 /* static */ void
 PromiseDebugging::AddUncaughtRejection(JS::HandleObject aPromise)
 {
   // This might OOM, but won't set a pending exception, so we'll just ignore it.
   if (CycleCollectedJSContext::Get()->mUncaughtRejections.append(aPromise)) {
     FlushRejections::DispatchNeeded();
   }
 }
@@ -415,107 +291,10 @@ PromiseDebugging::FlushUncaughtRejection
 
       IgnoredErrorResult err;
       obs->OnConsumed(promise, err);
     }
   }
   storage->mConsumedRejections.clear();
 }
 
-#else
-
-/* static */ void
-PromiseDebugging::AddUncaughtRejection(Promise& aPromise)
-{
-  CycleCollectedJSContext::Get()->mUncaughtRejections.AppendElement(&aPromise);
-  FlushRejections::DispatchNeeded();
-}
-
-/* void */ void
-PromiseDebugging::AddConsumedRejection(Promise& aPromise)
-{
-  CycleCollectedJSContext::Get()->mConsumedRejections.AppendElement(&aPromise);
-  FlushRejections::DispatchNeeded();
-}
-
-/* static */ void
-PromiseDebugging::GetPromiseID(GlobalObject&,
-                               JS::Handle<JSObject*> aPromise,
-                               nsString& aID,
-                               ErrorResult& aRv)
-{
-  Promise* promise = UnwrapPromise(aPromise, aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-  uint64_t promiseID = promise->GetID();
-  aID = sIDPrefix;
-  aID.AppendInt(promiseID);
-}
-
-/* static */ void
-PromiseDebugging::FlushUncaughtRejectionsInternal()
-{
-  CycleCollectedJSContext* storage = CycleCollectedJSContext::Get();
-
-  // The Promise that have been left uncaught (rejected and last in
-  // their chain) since the last call to this function.
-  nsTArray<nsCOMPtr<nsISupports>> uncaught;
-  storage->mUncaughtRejections.SwapElements(uncaught);
-
-  // The Promise that have been left uncaught at some point, but that
-  // have eventually had their `then` method called.
-  nsTArray<nsCOMPtr<nsISupports>> consumed;
-  storage->mConsumedRejections.SwapElements(consumed);
-
-  nsTArray<nsCOMPtr<nsISupports>>& observers = storage->mUncaughtRejectionObservers;
-
-  nsresult rv;
-  // Notify observers of uncaught Promise.
-
-  for (size_t i = 0; i < uncaught.Length(); ++i) {
-    nsCOMPtr<Promise> promise = do_QueryInterface(uncaught[i], &rv);
-    MOZ_ASSERT(NS_SUCCEEDED(rv));
-
-    if (!promise->IsLastInChain()) {
-      // This promise is not the last in the chain anymore,
-      // so the error has been caught at some point.
-      continue;
-    }
-
-    // For the moment, the Promise is still at the end of the
-    // chain. Let's inform observers, so that they may decide whether
-    // to report it.
-    for (size_t j = 0; j < observers.Length(); ++j) {
-      ErrorResult err;
-      RefPtr<UncaughtRejectionObserver> obs =
-        static_cast<UncaughtRejectionObserver*>(observers[j].get());
-
-      obs->OnLeftUncaught(*promise, err); // Ignore errors
-    }
-
-    promise->SetNotifiedAsUncaught();
-  }
-
-  // Notify observers of consumed Promise.
-
-  for (size_t i = 0; i < consumed.Length(); ++i) {
-    nsCOMPtr<Promise> promise = do_QueryInterface(consumed[i], &rv);
-    MOZ_ASSERT(NS_SUCCEEDED(rv));
-
-    if (!promise->WasNotifiedAsUncaught()) {
-      continue;
-    }
-
-    MOZ_ASSERT(!promise->IsLastInChain());
-    for (size_t j = 0; j < observers.Length(); ++j) {
-      ErrorResult err;
-      RefPtr<UncaughtRejectionObserver> obs =
-        static_cast<UncaughtRejectionObserver*>(observers[j].get());
-
-      obs->OnConsumed(*promise, err); // Ignore errors
-    }
-  }
-}
-#endif // SPIDERMONKEY_PROMISE
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/promise/PromiseDebugging.h
+++ b/dom/promise/PromiseDebugging.h
@@ -47,47 +47,27 @@ public:
   static void GetRejectionStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
                                 JS::MutableHandle<JSObject*> aStack,
                                 ErrorResult& aRv);
   static void GetFullfillmentStack(GlobalObject&,
                                    JS::Handle<JSObject*> aPromise,
                                    JS::MutableHandle<JSObject*> aStack,
                                    ErrorResult& aRv);
 
-#ifndef SPIDERMONKEY_PROMISE
-  static void GetDependentPromises(GlobalObject&,
-                                   JS::Handle<JSObject*> aPromise,
-                                   nsTArray<RefPtr<Promise>>& aPromises,
-                                   ErrorResult& aRv);
-  static double GetPromiseLifetime(GlobalObject&,
-                                   JS::Handle<JSObject*> aPromise,
-                                   ErrorResult& aRv);
-  static double GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
-                                ErrorResult& aRv);
-#endif // SPIDERMONKEY_PROMISE
-
   // Mechanism for watching uncaught instances of Promise.
   static void AddUncaughtRejectionObserver(GlobalObject&,
                                            UncaughtRejectionObserver& aObserver);
   static bool RemoveUncaughtRejectionObserver(GlobalObject&,
                                               UncaughtRejectionObserver& aObserver);
 
-#ifdef SPIDERMONKEY_PROMISE
   // Mark a Promise as having been left uncaught at script completion.
   static void AddUncaughtRejection(JS::HandleObject);
   // Mark a Promise previously added with `AddUncaughtRejection` as
   // eventually consumed.
   static void AddConsumedRejection(JS::HandleObject);
-#else
-  // Mark a Promise as having been left uncaught at script completion.
-  static void AddUncaughtRejection(Promise&);
-  // Mark a Promise previously added with `AddUncaughtRejection` as
-  // eventually consumed.
-  static void AddConsumedRejection(Promise&);
-#endif // SPIDERMONKEY_PROMISE
   // Propagate the informations from AddUncaughtRejection
   // and AddConsumedRejection to observers.
   static void FlushUncaughtRejections();
 
 protected:
   static void FlushUncaughtRejectionsInternal();
   friend class FlushRejections;
   friend class mozilla::dom::workers::WorkerPrivate;
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -8,17 +8,16 @@ EXPORTS.mozilla.dom += [
     'Promise.h',
     'PromiseDebugging.h',
     'PromiseNativeHandler.h',
     'PromiseWorkerProxy.h',
 ]
 
 UNIFIED_SOURCES += [
     'Promise.cpp',
-    'PromiseCallback.cpp',
     'PromiseDebugging.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '../base',
     '../ipc',
     '../workers',
 ]
--- a/dom/webidl/Promise.webidl
+++ b/dom/webidl/Promise.webidl
@@ -12,66 +12,22 @@
 // function"; for now, we just use "object".
 callback PromiseInit = void (object resolve, object reject);
 
 callback PromiseJobCallback = void();
 
 [TreatNonCallableAsNull]
 callback AnyCallback = any (any value);
 
-// When using SpiderMonkey promises, we don't want to define all this stuff;
-// just define a tiny interface to make codegen of Promise arguments and return
-// values work.
-#ifndef SPIDERMONKEY_PROMISE
-[Constructor(PromiseInit init),
- Exposed=(Window,Worker,WorkerDebugger,System)]
-// Need to escape "Promise" so it's treated as an identifier.
-interface _Promise {
-  // Have to use "any" (or "object", but "any" is simpler) as the type to
-  // support the subclassing behavior, since nothing actually requires the
-  // return value of PromiseSubclass.resolve/reject to be a Promise object.
-  [NewObject, Throws]
-  static any resolve(optional any value);
-  [NewObject, Throws]
-  static any reject(optional any value);
-
-  // The [TreatNonCallableAsNull] annotation is required since then() should do
-  // nothing instead of throwing errors when non-callable arguments are passed.
-  // Have to use "any" (or "object", but "any" is simpler) as the type to
-  // support the subclassing behavior, since nothing actually requires the
-  // return value of PromiseSubclass.then/catch to be a Promise object.
-  [NewObject, Throws]
-  any then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
-           [TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
-
-  [NewObject, Throws]
-  any catch([TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
-
-  // Have to use "any" (or "object", but "any" is simpler) as the type to
-  // support the subclassing behavior, since nothing actually requires the
-  // return value of PromiseSubclass.all to be a Promise object.  As a result,
-  // we also have to do our argument conversion manually, because we want to
-  // convert its exceptions into rejections.
-  [NewObject, Throws]
-  static any all(optional any iterable);
-
-  // Have to use "any" (or "object", but "any" is simpler) as the type to
-  // support the subclassing behavior, since nothing actually requires the
-  // return value of PromiseSubclass.race to be a Promise object.  As a result,
-  // we also have to do our argument conversion manually, because we want to
-  // convert its exceptions into rejections.
-  [NewObject, Throws]
-  static any race(optional any iterable);
-};
-#else // SPIDERMONKEY_PROMISE
+// Promises are implemented in SpiderMonkey; just define a tiny interface to make
+// codegen of Promise arguments and return values work.
 [NoInterfaceObject,
  Exposed=(Window,Worker,WorkerDebugger,System)]
 // Need to escape "Promise" so it's treated as an identifier.
 interface _Promise {
 };
 
 // Hack to allow us to have JS owning and properly tracing/CCing/etc a
 // PromiseNativeHandler.
 [NoInterfaceObject,
  Exposed=(Window,Worker,System)]
 interface PromiseNativeHandler {
 };
-#endif // SPIDERMONKEY_PROMISE
--- a/dom/webidl/PromiseDebugging.webidl
+++ b/dom/webidl/PromiseDebugging.webidl
@@ -33,34 +33,26 @@ callback interface UncaughtRejectionObse
   /**
    * A Promise has been left in `rejected` state and is the
    * last in its chain.
    *
    * @param p A currently uncaught Promise. If `p` is is eventually
    * caught, i.e. if its `then` callback is called, `onConsumed` will
    * be called.
    */
-#ifdef SPIDERMONKEY_PROMISE
   void onLeftUncaught(object p);
-#else
-  void onLeftUncaught(Promise<any> p);
-#endif SPIDERMONKEY_PROMISE
 
   /**
    * A Promise previously left uncaught is not the last in its
    * chain anymore.
    *
    * @param p A Promise that was previously left in uncaught state is
    * now caught, i.e. it is not the last in its chain anymore.
    */
-#ifdef SPIDERMONKEY_PROMISE
   void onConsumed(object p);
-#else
-  void onConsumed(Promise<any> p);
-#endif SPIDERMONKEY_PROMISE
 };
 
 [ChromeOnly, Exposed=(Window,System)]
 interface PromiseDebugging {
   /**
    * The various functions on this interface all expect to take promises but
    * don't want the WebIDL behavior of assimilating random passed-in objects
    * into promises.  They also want to treat Promise subclass instances as
@@ -100,52 +92,16 @@ interface PromiseDebugging {
   /**
    * Return the stack to the promise's fulfillment point, if the
    * fulfillment happened from script.  This can return null if the
    * promise has not been fulfilled or was not fulfilled from script.
    */
   [Throws]
   static object? getFullfillmentStack(object p);
 
-#ifndef SPIDERMONKEY_PROMISE
-  /**
-   * Get the promises directly depending on a given promise.  These are:
-   *
-   * 1) Return values of then() calls on the promise
-   * 2) Return values of Promise.all() if the given promise was passed in as one
-   *    of the arguments.
-   * 3) Return values of Promise.race() if the given promise was passed in as
-   *    one of the arguments.
-   *
-   * Once a promise is settled, it will generally notify its dependent promises
-   * and forget about them, so this is most useful on unsettled promises.
-   *
-   * Note that this function only returns the promises that directly depend on
-   * p.  It does not recursively return promises that depend on promises that
-   * depend on p.
-   */
-  [Throws]
-  static sequence<Promise<any>> getDependentPromises(object p);
-
-  /**
-   * Get the number of milliseconds elapsed since the given promise was created.
-   */
-  [Throws]
-  static DOMHighResTimeStamp getPromiseLifetime(object p);
-
-  /*
-   * Get the number of milliseconds elapsed between the promise being created
-   * and being settled.  Throws NS_ERROR_UNEXPECTED if the promise has not
-   * settled.
-   */
-  [Throws]
-  static DOMHighResTimeStamp getTimeToSettle(object p);
-
-#endif // SPIDERMONKEY_PROMISE
-
   /**
    * Watching uncaught rejections on the current thread.
    *
    * Adding an observer twice will cause it to be notified twice
    * of events.
    */
   static void addUncaughtRejectionObserver(UncaughtRejectionObserver o);
   static boolean removeUncaughtRejectionObserver(UncaughtRejectionObserver o);
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -6,18 +6,16 @@
 
 GENERATED_WEBIDL_FILES = [
     'CSS2Properties.webidl',
 ]
 
 PREPROCESSED_WEBIDL_FILES = [
     'Navigator.webidl',
     'Node.webidl',
-    'Promise.webidl',
-    'PromiseDebugging.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
     'AbstractWorker.webidl',
     'AddonManager.webidl',
     'AnalyserNode.webidl',
     'Animatable.webidl',
@@ -367,16 +365,18 @@ WEBIDL_FILES = [
     'PresentationAvailability.webidl',
     'PresentationConnection.webidl',
     'PresentationConnectionList.webidl',
     'PresentationDeviceInfoManager.webidl',
     'PresentationReceiver.webidl',
     'PresentationRequest.webidl',
     'ProcessingInstruction.webidl',
     'ProfileTimelineMarker.webidl',
+    'Promise.webidl',
+    'PromiseDebugging.webidl',
     'PushEvent.webidl',
     'PushManager.webidl',
     'PushManager.webidl',
     'PushMessageData.webidl',
     'PushSubscription.webidl',
     'PushSubscriptionOptions.webidl',
     'RadioNodeList.webidl',
     'Range.webidl',
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -32,29 +32,16 @@ js_option('--disable-js-shell', default=
 @depends('--disable-js-shell')
 def js_disable_shell(value):
     if not value:
         return True
 
 set_config('JS_DISABLE_SHELL', js_disable_shell)
 
 
-# Use SpiderMonkey Promise implementation if it's enabled
-# =======================================================
-js_option('--enable-sm-promise', default=True,
-          help='Enable SpiderMonkey promises')
-
-@depends('--enable-sm-promise')
-def sm_promise(value):
-    if value:
-        return True
-
-set_config('SPIDERMONKEY_PROMISE', sm_promise)
-set_define('SPIDERMONKEY_PROMISE', sm_promise)
-
 # SpiderMonkey as a shared library, and how its symbols are exported
 # ==================================================================
 js_option('--disable-shared-js', default=building_js,
           help='Do not create a shared library')
 
 js_option('--disable-export-js', default=building_js,
           help='Do not mark JS symbols as DLL exported/visible')
 
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1433,17 +1433,16 @@ OOMTest(JSContext* cx, unsigned argc, Va
     }
 
     rt->runningOOMTest = false;
     args.rval().setUndefined();
     return true;
 }
 #endif
 
-#ifdef SPIDERMONKEY_PROMISE
 static bool
 SettlePromiseNow(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (!args.requireAtLeast(cx, "settlePromiseNow", 1))
         return false;
     if (!args[0].isObject() || !args[0].toObject().is<PromiseObject>()) {
         JS_ReportErrorASCII(cx, "first argument must be a Promise object");
@@ -1542,53 +1541,16 @@ RejectPromise(JSContext* cx, unsigned ar
     }
 
     bool result = JS::RejectPromise(cx, promise, reason);
     if (result)
         args.rval().setUndefined();
     return result;
 }
 
-#else
-
-static const js::Class FakePromiseClass = {
-    "Promise", JSCLASS_IS_ANONYMOUS
-};
-
-static bool
-MakeFakePromise(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    RootedObject obj(cx, NewObjectWithGivenProto(cx, &FakePromiseClass, nullptr));
-    if (!obj)
-        return false;
-
-    JS::dbg::onNewPromise(cx, obj);
-    args.rval().setObject(*obj);
-    return true;
-}
-
-static bool
-SettleFakePromise(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    if (!args.requireAtLeast(cx, "settleFakePromise", 1))
-        return false;
-    if (!args[0].isObject() || args[0].toObject().getClass() != &FakePromiseClass) {
-        JS_ReportErrorASCII(cx, "first argument must be a (fake) Promise object");
-        return false;
-    }
-
-    RootedObject promise(cx, &args[0].toObject());
-    JS::dbg::onPromiseSettled(cx, promise);
-    return true;
-}
-#endif // SPIDERMONKEY_PROMISE
-
 static unsigned finalizeCount = 0;
 
 static void
 finalize_counter_finalize(JSFreeOp* fop, JSObject* obj)
 {
     ++finalizeCount;
 }
 
@@ -4209,47 +4171,32 @@ static const JSFunctionSpecWithHelp Test
 "  Test that the passed function behaves correctly under OOM conditions by\n"
 "  repeatedly executing it and simulating allocation failure at successive\n"
 "  allocations until the function completes without seeing a failure.\n"
 "  By default this tests that an exception is raised if execution fails, but\n"
 "  this can be disabled by passing false as the optional second parameter.\n"
 "  This is also disabled when --fuzzing-safe is specified."),
 #endif
 
-#ifdef SPIDERMONKEY_PROMISE
     JS_FN_HELP("settlePromiseNow", SettlePromiseNow, 1, 0,
 "settlePromiseNow(promise)",
 "  'Settle' a 'promise' immediately. This just marks the promise as resolved\n"
 "  with a value of `undefined` and causes the firing of any onPromiseSettled\n"
 "  hooks set on Debugger instances that are observing the given promise's\n"
 "  global as a debuggee."),
     JS_FN_HELP("getWaitForAllPromise", GetWaitForAllPromise, 1, 0,
 "getWaitForAllPromise(densePromisesArray)",
 "  Calls the 'GetWaitForAllPromise' JSAPI function and returns the result\n"
 "  Promise."),
 JS_FN_HELP("resolvePromise", ResolvePromise, 2, 0,
 "resolvePromise(promise, resolution)",
 "  Resolve a Promise by calling the JSAPI function JS::ResolvePromise."),
 JS_FN_HELP("rejectPromise", RejectPromise, 2, 0,
 "rejectPromise(promise, reason)",
 "  Reject a Promise by calling the JSAPI function JS::RejectPromise."),
-#else
-    JS_FN_HELP("makeFakePromise", MakeFakePromise, 0, 0,
-"makeFakePromise()",
-"  Create an object whose [[Class]] name is 'Promise' and call\n"
-"  JS::dbg::onNewPromise on it before returning it. It doesn't actually have\n"
-"  any of the other behavior associated with promises."),
-
-    JS_FN_HELP("settleFakePromise", SettleFakePromise, 1, 0,
-"settleFakePromise(promise)",
-"  'Settle' a 'promise' created by makeFakePromise(). This doesn't have any\n"
-"  observable effects outside of firing any onPromiseSettled hooks set on\n"
-"  Debugger instances that are observing the given promise's global as a\n"
-"  debuggee."),
-#endif // SPIDERMONKEY_PROMISE
 
     JS_FN_HELP("makeFinalizeObserver", MakeFinalizeObserver, 0, 0,
 "makeFinalizeObserver()",
 "  Get a special object whose finalization increases the counter returned\n"
 "  by the finalizeCount function."),
 
     JS_FN_HELP("finalizeCount", FinalizeCount, 0, 0,
 "finalizeCount()",
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -72,16 +72,17 @@ UNIFIED_SOURCES += [
     'testObjectEmulatingUndefined.cpp',
     'testOOM.cpp',
     'testParseJSON.cpp',
     'testPersistentRooted.cpp',
     'testPreserveJitCode.cpp',
     'testPrintf.cpp',
     'testPrivateGCThingValue.cpp',
     'testProfileStrings.cpp',
+    'testPromise.cpp',
     'testPropCache.cpp',
     'testRegExp.cpp',
     'testResolveRecursion.cpp',
     'tests.cpp',
     'testSameValue.cpp',
     'testSavedStacks.cpp',
     'testScriptInfo.cpp',
     'testScriptObject.cpp',
@@ -119,21 +120,16 @@ if CONFIG['ENABLE_ION']:
         'testJitMacroAssembler.cpp',
         'testJitMoveEmitterCycles-mips32.cpp',
         'testJitMoveEmitterCycles.cpp',
         'testJitRangeAnalysis.cpp',
         'testJitRegisterSet.cpp',
         'testJitRValueAlloc.cpp',
     ]
 
-if CONFIG['SPIDERMONKEY_PROMISE']:
-    UNIFIED_SOURCES += [
-        'testPromise.cpp',
-    ]
-
 DEFINES['EXPORT_JS_API'] = True
 
 LOCAL_INCLUDES += [
     '!..',
     '..',
 ]
 
 if CONFIG['ENABLE_INTL_API'] and CONFIG['MOZ_ICU_DATA_ARCHIVE']:
--- a/js/src/jsprototypes.h
+++ b/js/src/jsprototypes.h
@@ -56,22 +56,16 @@
 #endif
 
 #ifdef ENABLE_SHARED_ARRAY_BUFFER
 #define IF_SAB(real,imaginary) real
 #else
 #define IF_SAB(real,imaginary) imaginary
 #endif
 
-#ifdef SPIDERMONKEY_PROMISE
-#define IF_PROMISE(real,imaginary) real
-#else
-#define IF_PROMISE(real,imaginary) imaginary
-#endif
-
 #define JS_FOR_PROTOTYPES(real,imaginary) \
     imaginary(Null,              0,     InitNullClass,          dummy) \
     real(Object,                 1,     InitViaClassSpec,       OCLASP(Plain)) \
     real(Function,               2,     InitViaClassSpec,       &JSFunction::class_) \
     real(Array,                  3,     InitViaClassSpec,       OCLASP(Array)) \
     real(Boolean,                4,     InitBooleanClass,       OCLASP(Boolean)) \
     real(JSON,                   5,     InitJSONClass,          CLASP(JSON)) \
     real(Date,                   6,     InitViaClassSpec,       OCLASP(Date)) \
@@ -117,13 +111,13 @@ IF_SIMD(real,imaginary)(SIMD,           
     real(TypedArray,            46,     InitViaClassSpec,       &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
 IF_SAB(real,imaginary)(Atomics, 47,     InitAtomicsClass, OCLASP(Atomics)) \
     real(SavedFrame,            48,     InitViaClassSpec,       &js::SavedFrame::class_) \
     real(WebAssembly,           49,     InitWebAssemblyClass,   CLASP(WebAssembly)) \
     imaginary(WasmModule,       50,     dummy,                  dummy) \
     imaginary(WasmInstance,     51,     dummy,                  dummy) \
     imaginary(WasmMemory,       52,     dummy,                  dummy) \
     imaginary(WasmTable,        53,     dummy,                  dummy) \
-IF_PROMISE(real,imaginary)(Promise,             54,     InitViaClassSpec, OCLASP(Promise)) \
+    real(Promise,               54,     InitViaClassSpec,       OCLASP(Promise)) \
 
 #define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
 
 #endif /* jsprototypes_h */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -761,32 +761,30 @@ selfhosted.inputs = [
     'builtin/Generator.js',
     'builtin/Intl.js',
     'builtin/IntlData.js',
     'builtin/Iterator.js',
     'builtin/Map.js',
     'builtin/Module.js',
     'builtin/Number.js',
     'builtin/Object.js',
+    'builtin/Promise.js',
     'builtin/Reflect.js',
     'builtin/RegExp.js',
     'builtin/RegExpGlobalReplaceOpt.h.js',
     'builtin/RegExpLocalReplaceOpt.h.js',
     'builtin/String.js',
     'builtin/Set.js',
     'builtin/Sorting.js',
     'builtin/TypedArray.js',
     'builtin/TypedObject.js',
     'builtin/WeakMap.js',
     'builtin/WeakSet.js'
 ]
 
-if CONFIG['SPIDERMONKEY_PROMISE']:
-    selfhosted.inputs += ['builtin/Promise.js']
-
 if CONFIG['JS_HAS_CTYPES']:
     if CONFIG['MOZ_SYSTEM_FFI']:
         CXXFLAGS += CONFIG['MOZ_FFI_CFLAGS']
     else:
         # Windows needs this to be linked with a static library.
         DEFINES['FFI_BUILDING'] = True
 
 if CONFIG['GNU_CXX']:
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -146,30 +146,28 @@ static const size_t gMaxStackSize = 128 
 static const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(1800.0);
 
 #ifdef NIGHTLY_BUILD
 # define SHARED_MEMORY_DEFAULT 1
 #else
 # define SHARED_MEMORY_DEFAULT 0
 #endif
 
-#ifdef SPIDERMONKEY_PROMISE
 using JobQueue = GCVector<JSObject*, 0, SystemAllocPolicy>;
 
 struct ShellAsyncTasks
 {
     explicit ShellAsyncTasks(JSContext* cx)
       : outstanding(0),
         finished(cx)
     {}
 
     size_t outstanding;
     Vector<JS::AsyncTask*> finished;
 };
-#endif // SPIDERMONKEY_PROMISE
 
 enum class ScriptKind
 {
     Script,
     Module
 };
 
 class OffThreadState {
@@ -264,22 +262,20 @@ struct ShellContext
     bool isWorker;
     double timeoutInterval;
     double startTime;
     Atomic<bool> serviceInterrupt;
     Atomic<bool> haveInterruptFunc;
     JS::PersistentRootedValue interruptFunc;
     bool lastWarningEnabled;
     JS::PersistentRootedValue lastWarning;
-#ifdef SPIDERMONKEY_PROMISE
     JS::PersistentRootedValue promiseRejectionTrackerCallback;
     JS::PersistentRooted<JobQueue> jobQueue;
     ExclusiveData<ShellAsyncTasks> asyncTasks;
     bool drainingJobQueue;
-#endif // SPIDERMONKEY_PROMISE
 
     /*
      * Watchdog thread state.
      */
     Mutex watchdogLock;
     ConditionVariable watchdogWakeup;
     Maybe<Thread> watchdogThread;
     Maybe<TimeStamp> watchdogTimeout;
@@ -431,21 +427,19 @@ ShellContext::ShellContext(JSContext* cx
   : isWorker(false),
     timeoutInterval(-1.0),
     startTime(PRMJ_Now()),
     serviceInterrupt(false),
     haveInterruptFunc(false),
     interruptFunc(cx, NullValue()),
     lastWarningEnabled(false),
     lastWarning(cx, NullValue()),
-#ifdef SPIDERMONKEY_PROMISE
     promiseRejectionTrackerCallback(cx, NullValue()),
     asyncTasks(mutexid::ShellAsyncTasks, cx),
     drainingJobQueue(false),
-#endif // SPIDERMONKEY_PROMISE
     watchdogLock(mutexid::ShellContextWatchdog),
     exitCode(0),
     quitting(false),
     readLineBufPos(0),
     spsProfilingStackSize(0)
 {}
 
 static ShellContext*
@@ -735,17 +729,16 @@ RunModule(JSContext* cx, const char* fil
     JS::AutoValueArray<2> args(cx);
     args[0].setString(JS_NewStringCopyZ(cx, filename));
     args[1].setUndefined();
 
     RootedValue value(cx);
     return JS_CallFunction(cx, loaderObj, importFun, args, &value);
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 static JSObject*
 ShellGetIncumbentGlobalCallback(JSContext* cx)
 {
     return JS::CurrentGlobalOrNull(cx);
 }
 
 static bool
 ShellEnqueuePromiseJobCallback(JSContext* cx, JS::HandleObject job, JS::HandleObject allocationSite,
@@ -772,22 +765,20 @@ ShellFinishAsyncTaskCallback(JS::AsyncTa
 {
     ShellContext* sc = (ShellContext*)task->user;
 
     ExclusiveData<ShellAsyncTasks>::Guard asyncTasks = sc->asyncTasks.lock();
     MOZ_ASSERT(asyncTasks->outstanding > 0);
     asyncTasks->outstanding--;
     return asyncTasks->finished.append(task);
 }
-#endif // SPIDERMONKEY_PROMISE
 
 static bool
 DrainJobQueue(JSContext* cx)
 {
-#ifdef SPIDERMONKEY_PROMISE
     ShellContext* sc = GetShellContext(cx);
     if (sc->quitting || sc->drainingJobQueue)
         return true;
 
     // Wait for any outstanding async tasks to finish so that the
     // finishedAsyncTasks list is fixed.
     while (true) {
         AutoLockHelperThreadState lock;
@@ -828,32 +819,30 @@ DrainJobQueue(JSContext* cx)
         {
             AutoReportException are(cx);
             JS::Call(cx, UndefinedHandleValue, job, args, &rval);
         }
         sc->jobQueue[i].set(nullptr);
     }
     sc->jobQueue.clear();
     sc->drainingJobQueue = false;
-#endif // SPIDERMONKEY_PROMISE
     return true;
 }
 
 static bool
 DrainJobQueue(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (!DrainJobQueue(cx))
         return false;
     args.rval().setUndefined();
     return true;
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 static void
 ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promise,
                                           PromiseRejectionHandlingState state, void* data)
 {
     RootedValue callback(cx, GetShellContext(cx)->promiseRejectionTrackerCallback);
     if (callback.isNull()) {
         return;
     }
@@ -866,35 +855,32 @@ ForwardingPromiseRejectionTrackerCallbac
 
     if (!JS_WrapValue(cx, args[0]))
         return;
 
     RootedValue rval(cx);
     if (!Call(cx, callback, UndefinedHandleValue, args, &rval))
         JS_ClearPendingException(cx);
 }
-#endif // SPIDERMONKEY_PROMISE
 
 static bool
 SetPromiseRejectionTrackerCallback(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-#ifdef SPIDERMONKEY_PROMISE
     if (!IsCallable(args.get(0))) {
         JS_ReportErrorASCII(cx,
                             "setPromiseRejectionTrackerCallback expects a function as its sole "
                             "argument");
         return false;
     }
 
     GetShellContext(cx)->promiseRejectionTrackerCallback = args[0];
     JS::SetPromiseRejectionTrackerCallback(cx, ForwardingPromiseRejectionTrackerCallback);
 
-#endif // SPIDERMONKEY_PROMISE
     args.rval().setUndefined();
     return true;
 }
 
 #ifdef ENABLE_INTL_API
 static bool
 AddIntlExtras(JSContext* cx, unsigned argc, Value* vp)
 {
@@ -3319,22 +3305,20 @@ WorkerMain(void* arg)
     SetWorkerContextOptions(cx);
 
     if (!JS::InitSelfHostedCode(cx)) {
         JS_DestroyContext(cx);
         js_delete(input);
         return;
     }
 
-#ifdef SPIDERMONKEY_PROMISE
     sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
     JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
     JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
     JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
-#endif // SPIDERMONKEY_PROMISE
 
     EnvironmentPreparer environmentPreparer(cx);
 
     JS::SetLargeAllocationFailureCallback(cx, my_LargeAllocFailCallback, (void*)cx);
 
     do {
         JSAutoRequest ar(cx);
 
@@ -3355,21 +3339,19 @@ WorkerMain(void* arg)
         if (!JS::Compile(cx, options, input->chars, input->length, &script))
             break;
         RootedValue result(cx);
         JS_ExecuteScript(cx, script, &result);
     } while (0);
 
     JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
 
-#ifdef SPIDERMONKEY_PROMISE
     JS::SetGetIncumbentGlobalCallback(cx, nullptr);
     JS::SetEnqueuePromiseJobCallback(cx, nullptr);
     sc->jobQueue.reset();
-#endif // SPIDERMONKEY_PROMISE
 
     KillWatchdog(cx);
 
     JS_DestroyContext(cx);
 
     js_delete(input);
 }
 
@@ -7910,22 +7892,20 @@ main(int argc, char** argv, char** envp)
 
     JS_SetNativeStackQuota(cx, gMaxStackSize);
 
     JS::dbg::SetDebuggerMallocSizeOf(cx, moz_malloc_size_of);
 
     if (!JS::InitSelfHostedCode(cx))
         return 1;
 
-#ifdef SPIDERMONKEY_PROMISE
     sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
     JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
     JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
     JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
-#endif // SPIDERMONKEY_PROMISE
 
     EnvironmentPreparer environmentPreparer(cx);
 
     JS_SetGCParameter(cx, JSGC_MODE, JSGC_MODE_INCREMENTAL);
 
     JS::SetLargeAllocationFailureCallback(cx, my_LargeAllocFailCallback, (void*)cx);
 
     // Set some parameters to allow incremental GC in low memory conditions,
@@ -7945,21 +7925,19 @@ main(int argc, char** argv, char** envp)
 
 #ifdef DEBUG
     if (OOM_printAllocationCount)
         printf("OOM max count: %" PRIu64 "\n", js::oom::counter);
 #endif
 
     JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
 
-#ifdef SPIDERMONKEY_PROMISE
     JS::SetGetIncumbentGlobalCallback(cx, nullptr);
     JS::SetEnqueuePromiseJobCallback(cx, nullptr);
     sc->jobQueue.reset();
-#endif // SPIDERMONKEY_PROMISE
 
     KillWatchdog(cx);
 
     KillWorkerThreads();
 
     DestructSharedArrayBufferMailbox();
 
     JS_DestroyContext(cx);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -8880,17 +8880,16 @@ DebuggerObject::proxyHandlerGetter(JSCon
     Rooted<DebuggerObject*> result(cx);
     if (!DebuggerObject::getScriptedProxyHandler(cx, object, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 /* static */ bool
 DebuggerObject::isPromiseGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "get isPromise", args, object)
 
     args.rval().setBoolean(object->isPromise());
     return true;
 }
@@ -9049,17 +9048,16 @@ DebuggerObject::promiseDependentPromises
         promises = NewDenseEmptyArray(cx);
     else
         promises = NewDenseCopiedArray(cx, values.length(), values[0].address());
     if (!promises)
         return false;
     args.rval().setObject(*promises);
     return true;
 }
-#endif // SPIDERMONKEY_PROMISE
 
 /* static */ bool
 DebuggerObject::isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "isExtensible", args, object)
 
     bool result;
     if (!DebuggerObject::isExtensible(cx, object, result))
@@ -9487,31 +9485,29 @@ const JSPropertySpec DebuggerObject::pro
     JS_PSG("errorLineNumber", DebuggerObject::errorLineNumberGetter, 0),
     JS_PSG("errorColumnNumber", DebuggerObject::errorColumnNumberGetter, 0),
     JS_PSG("isProxy", DebuggerObject::isProxyGetter, 0),
     JS_PSG("proxyTarget", DebuggerObject::proxyTargetGetter, 0),
     JS_PSG("proxyHandler", DebuggerObject::proxyHandlerGetter, 0),
     JS_PS_END
 };
 
-#ifdef SPIDERMONKEY_PROMISE
 const JSPropertySpec DebuggerObject::promiseProperties_[] = {
     JS_PSG("isPromise", DebuggerObject::isPromiseGetter, 0),
     JS_PSG("promiseState", DebuggerObject::promiseStateGetter, 0),
     JS_PSG("promiseValue", DebuggerObject::promiseValueGetter, 0),
     JS_PSG("promiseReason", DebuggerObject::promiseReasonGetter, 0),
     JS_PSG("promiseLifetime", DebuggerObject::promiseLifetimeGetter, 0),
     JS_PSG("promiseTimeToResolution", DebuggerObject::promiseTimeToResolutionGetter, 0),
     JS_PSG("promiseAllocationSite", DebuggerObject::promiseAllocationSiteGetter, 0),
     JS_PSG("promiseResolutionSite", DebuggerObject::promiseResolutionSiteGetter, 0),
     JS_PSG("promiseID", DebuggerObject::promiseIDGetter, 0),
     JS_PSG("promiseDependentPromises", DebuggerObject::promiseDependentPromisesGetter, 0),
     JS_PS_END
 };
-#endif // SPIDERMONKEY_PROMISE
 
 const JSFunctionSpec DebuggerObject::methods_[] = {
     JS_FN("isExtensible", DebuggerObject::isExtensibleMethod, 0, 0),
     JS_FN("isSealed", DebuggerObject::isSealedMethod, 0, 0),
     JS_FN("isFrozen", DebuggerObject::isFrozenMethod, 0, 0),
     JS_FN("getOwnPropertyNames", DebuggerObject::getOwnPropertyNamesMethod, 0, 0),
     JS_FN("getOwnPropertySymbols", DebuggerObject::getOwnPropertySymbolsMethod, 0, 0),
     JS_FN("getOwnPropertyDescriptor", DebuggerObject::getOwnPropertyDescriptorMethod, 1, 0),
@@ -9541,20 +9537,18 @@ DebuggerObject::initClass(JSContext* cx,
 
     RootedNativeObject objectProto(cx, InitClass(cx, debugCtor, objProto, &class_,
                                                  construct, 0, properties_,
                                                  methods_, nullptr, nullptr));
 
     if (!objectProto)
         return nullptr;
 
-#ifdef SPIDERMONKEY_PROMISE
     if (!DefinePropertiesAndFunctions(cx, objectProto, promiseProperties_, nullptr))
         return nullptr;
-#endif // SPIDERMONKEY_PROMISE
 
     return objectProto;
 }
 
 /* static */ DebuggerObject*
 DebuggerObject::create(JSContext* cx, HandleObject proto, HandleObject referent,
                        HandleNativeObject debugger)
 {
@@ -9612,31 +9606,29 @@ DebuggerObject::isGlobal() const
 }
 
 bool
 DebuggerObject::isScriptedProxy() const
 {
     return js::IsScriptedProxy(referent());
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 bool
 DebuggerObject::isPromise() const
 {
     JSObject* referent = this->referent();
 
     if (IsCrossCompartmentWrapper(referent)) {
         referent = CheckedUnwrap(referent);
         if (!referent)
             return false;
     }
 
     return referent->is<PromiseObject>();
 }
-#endif // SPIDERMONKEY_PROMISE
 
 /* static */ bool
 DebuggerObject::getClassName(JSContext* cx, HandleDebuggerObject object,
                              MutableHandleString result)
 {
     RootedObject referent(cx, object->referent());
 
     const char* className;
@@ -9885,17 +9877,16 @@ DebuggerObject::getErrorColumnNumber(JSC
         result.setUndefined();
         return true;
     }
 
     result.setNumber(report->column);
     return true;
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 /* static */ bool
 DebuggerObject::getPromiseValue(JSContext* cx, HandleDebuggerObject object,
                                 MutableHandleValue result)
 {
     MOZ_ASSERT(object->promiseState() == JS::PromiseState::Fulfilled);
 
     result.set(object->promise()->value());
     return object->owner()->wrapDebuggeeValue(cx, result);
@@ -9905,17 +9896,16 @@ DebuggerObject::getPromiseValue(JSContex
 DebuggerObject::getPromiseReason(JSContext* cx, HandleDebuggerObject object,
                                  MutableHandleValue result)
 {
     MOZ_ASSERT(object->promiseState() == JS::PromiseState::Rejected);
 
     result.set(object->promise()->reason());
     return object->owner()->wrapDebuggeeValue(cx, result);
 }
-#endif // SPIDERMONKEY_PROMISE
 
 /* static */ bool
 DebuggerObject::isExtensible(JSContext* cx, HandleDebuggerObject object, bool& result)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
@@ -10373,17 +10363,16 @@ DebuggerObject::requireGlobal(JSContext*
                                   "a global object", nullptr);
         }
         return false;
     }
 
     return true;
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 /* static */ bool
 DebuggerObject::requirePromise(JSContext* cx, HandleDebuggerObject object)
 {
    RootedObject referent(cx, object->referent());
 
    if (IsCrossCompartmentWrapper(referent)) {
        referent = CheckedUnwrap(referent);
        if (!referent) {
@@ -10395,17 +10384,16 @@ DebuggerObject::requirePromise(JSContext
    if (!referent->is<PromiseObject>()) {
       JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
                                 "Debugger", "Promise", object->getClass()->name);
       return false;
    }
 
    return true;
 }
-#endif // SPIDERMONKEY_PROMISE
 
 /* static */ bool
 DebuggerObject::getScriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
                                        MutableHandleDebuggerObject result)
 {
     MOZ_ASSERT(object->isScriptedProxy());
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -1360,22 +1360,20 @@ class DebuggerObject : public NativeObje
     static MOZ_MUST_USE bool getErrorLineNumber(JSContext* cx, HandleDebuggerObject object,
                                                 MutableHandleValue result);
     static MOZ_MUST_USE bool getErrorColumnNumber(JSContext* cx, HandleDebuggerObject object,
                                                   MutableHandleValue result);
     static MOZ_MUST_USE bool getScriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
                                                     MutableHandleDebuggerObject result);
     static MOZ_MUST_USE bool getScriptedProxyHandler(JSContext* cx, HandleDebuggerObject object,
                                                      MutableHandleDebuggerObject result);
-#ifdef SPIDERMONKEY_PROMISE
     static MOZ_MUST_USE bool getPromiseValue(JSContext* cx, HandleDebuggerObject object,
                                              MutableHandleValue result);
     static MOZ_MUST_USE bool getPromiseReason(JSContext* cx, HandleDebuggerObject object,
                                               MutableHandleValue result);
-#endif // SPIDERMONKEY_PROMISE
 
     // Methods
     static MOZ_MUST_USE bool isExtensible(JSContext* cx, HandleDebuggerObject object,
                                           bool& result);
     static MOZ_MUST_USE bool isSealed(JSContext* cx, HandleDebuggerObject object, bool& result);
     static MOZ_MUST_USE bool isFrozen(JSContext* cx, HandleDebuggerObject object, bool& result);
     static MOZ_MUST_USE bool getPrototypeOf(JSContext* cx, HandleDebuggerObject object,
                                             MutableHandleDebuggerObject result);
@@ -1415,59 +1413,47 @@ class DebuggerObject : public NativeObje
     // Infallible properties
     bool isCallable() const;
     bool isFunction() const;
     bool isDebuggeeFunction() const;
     bool isBoundFunction() const;
     bool isArrowFunction() const;
     bool isGlobal() const;
     bool isScriptedProxy() const;
-#ifdef SPIDERMONKEY_PROMISE
     bool isPromise() const;
-#endif // SPIDERMONKEY_PROMISE
     JSAtom* name() const;
     JSAtom* displayName() const;
-#ifdef SPIDERMONKEY_PROMISE
     JS::PromiseState promiseState() const;
     double promiseLifetime() const;
     double promiseTimeToResolution() const;
-#endif // SPIDERMONKEY_PROMISE
 
   private:
     enum {
         OWNER_SLOT
     };
 
     static const unsigned RESERVED_SLOTS = 1;
 
     static const ClassOps classOps_;
 
     static const JSPropertySpec properties_[];
-#ifdef SPIDERMONKEY_PROMISE
     static const JSPropertySpec promiseProperties_[];
-#endif // SPIDERMONKEY_PROMISE
     static const JSFunctionSpec methods_[];
 
     JSObject* referent() const {
         JSObject* obj = (JSObject*) getPrivate();
         MOZ_ASSERT(obj);
         return obj;
     }
 
     Debugger* owner() const;
-
-#ifdef SPIDERMONKEY_PROMISE
     PromiseObject* promise() const;
-#endif // SPIDERMONKEY_PROMISE
 
     static MOZ_MUST_USE bool requireGlobal(JSContext* cx, HandleDebuggerObject object);
-#ifdef SPIDERMONKEY_PROMISE
     static MOZ_MUST_USE bool requirePromise(JSContext* cx, HandleDebuggerObject object);
-#endif // SPIDERMONKEY_PROMISE
-
     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
 
     // JSNative properties
     static MOZ_MUST_USE bool callableGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isBoundFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isArrowFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool protoGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool classGetter(JSContext* cx, unsigned argc, Value* vp);
@@ -1482,28 +1468,26 @@ class DebuggerObject : public NativeObje
     static MOZ_MUST_USE bool globalGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool allocationSiteGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool errorMessageNameGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool errorLineNumberGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool errorColumnNumberGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isProxyGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool proxyTargetGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp);
-#ifdef SPIDERMONKEY_PROMISE
     static MOZ_MUST_USE bool isPromiseGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseStateGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseValueGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseReasonGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseLifetimeGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseTimeToResolutionGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseAllocationSiteGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseResolutionSiteGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseIDGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Value* vp);
-#endif // SPIDERMONKEY_PROMISE
 
     // JSNative methods
     static MOZ_MUST_USE bool isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isSealedMethod(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isFrozenMethod(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool getOwnPropertyNamesMethod(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool getOwnPropertySymbolsMethod(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool getOwnPropertyDescriptorMethod(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -18,19 +18,17 @@
 #include "builtin/AtomicsObject.h"
 #include "builtin/Eval.h"
 #if EXPOSE_INTL_API
 # include "builtin/Intl.h"
 #endif
 #include "builtin/MapObject.h"
 #include "builtin/ModuleObject.h"
 #include "builtin/Object.h"
-#ifdef SPIDERMONKEY_PROMISE
 #include "builtin/Promise.h"
-#endif
 #include "builtin/RegExp.h"
 #include "builtin/SelfHostingDefines.h"
 #include "builtin/SymbolObject.h"
 #include "builtin/TypedObject.h"
 #include "builtin/WeakMapObject.h"
 #include "builtin/WeakSetObject.h"
 #include "vm/Debugger.h"
 #include "vm/EnvironmentObject.h"
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -1616,17 +1616,16 @@ static bool
 WebAssembly_toSource(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setString(cx->names().WebAssembly);
     return true;
 }
 #endif
 
-#ifdef SPIDERMONKEY_PROMISE
 static bool
 Nop(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setUndefined();
     return true;
 }
 
@@ -1890,17 +1889,16 @@ WebAssembly_instantiate(JSContext* cx, u
 
         if (!StartPromiseTask(cx, Move(task)))
             return false;
     }
 
     callArgs.rval().setObject(*promise);
     return true;
 }
-#endif
 
 static bool
 WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs callArgs = CallArgsFromVp(argc, vp);
 
     MutableBytes bytecode;
     if (!GetBufferSource(cx, callArgs, "WebAssembly.validate", &bytecode))
@@ -1921,20 +1919,18 @@ WebAssembly_validate(JSContext* cx, unsi
     return true;
 }
 
 static const JSFunctionSpec WebAssembly_static_methods[] =
 {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str, WebAssembly_toSource, 0, 0),
 #endif
-#ifdef SPIDERMONKEY_PROMISE
     JS_FN("compile", WebAssembly_compile, 1, 0),
     JS_FN("instantiate", WebAssembly_instantiate, 2, 0),
-#endif
     JS_FN("validate", WebAssembly_validate, 1, 0),
     JS_FS_END
 };
 
 const Class js::WebAssemblyClass =
 {
     js_WebAssembly_str,
     JSCLASS_HAS_CACHED_PROTO(JSProto_WebAssembly)
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1201,23 +1201,16 @@ xpc::CreateSandboxObject(JSContext* cx, 
             (!JS_DefineFunction(cx, sandbox, "exportFunction", SandboxExportFunction, 3, 0) ||
              !JS_DefineFunction(cx, sandbox, "createObjectIn", SandboxCreateObjectIn, 2, 0) ||
              !JS_DefineFunction(cx, sandbox, "cloneInto", SandboxCloneInto, 3, 0) ||
              !JS_DefineFunction(cx, sandbox, "isProxy", SandboxIsProxy, 1, 0)))
             return NS_ERROR_XPC_UNEXPECTED;
 
         if (!options.globalProperties.DefineInSandbox(cx, sandbox))
             return NS_ERROR_XPC_UNEXPECTED;
-
-#ifndef SPIDERMONKEY_PROMISE
-        // Promise is supposed to be part of ES, and therefore should appear on
-        // every global.
-        if (!dom::PromiseBinding::GetConstructorObject(cx))
-            return NS_ERROR_XPC_UNEXPECTED;
-#endif // SPIDERMONKEY_PROMISE
     }
 
     // We handle the case where the context isn't in a compartment for the
     // benefit of InitSingletonScopes.
     vp.setObject(*sandbox);
     if (js::GetContextCompartment(cx) && !JS_WrapValue(cx, vp))
         return NS_ERROR_UNEXPECTED;
 
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -786,30 +786,28 @@ XPCConvert::NativeInterface2JSObject(Mut
             return false;
     }
     if (flat) {
         if (allowNativeWrapper && !JS_WrapObject(cx, &flat))
             return false;
         return CreateHolderIfNeeded(flat, d, dest);
     }
 
-#ifdef SPIDERMONKEY_PROMISE
     if (iid->Equals(NS_GET_IID(nsISupports))) {
         // Check for a Promise being returned via nsISupports.  In that
         // situation, we want to dig out its underlying JS object and return
         // that.
         RefPtr<Promise> promise = do_QueryObject(aHelper.Object());
         if (promise) {
             flat = promise->PromiseObj();
             if (!JS_WrapObject(cx, &flat))
                 return false;
             return CreateHolderIfNeeded(flat, d, dest);
         }
     }
-#endif // SPIDERMONKEY_PROMISE
 
     // Don't double wrap CPOWs. This is a temporary measure for compatibility
     // with objects that don't provide necessary QIs (such as objects under
     // the new DOM bindings). We expect the other side of the CPOW to have
     // the appropriate wrappers in place.
     RootedObject cpow(cx, UnwrapNativeCPOW(aHelper.Object()));
     if (cpow) {
         if (!JS_WrapObject(cx, &cpow))
@@ -938,28 +936,26 @@ XPCConvert::JSObject2NativeInterface(voi
                     iface = nsPIDOMWindowInner::From(inner)->GetOuterWindow();
                     return NS_SUCCEEDED(iface->QueryInterface(*iid, dest));
                 }
             }
 
             return false;
         }
 
-#ifdef SPIDERMONKEY_PROMISE
         // Deal with Promises being passed as nsISupports.  In that situation we
         // want to create a dom::Promise and use that.
         if (iid->Equals(NS_GET_IID(nsISupports))) {
             RootedObject innerObj(cx, inner);
             if (IsPromiseObject(innerObj)) {
                 nsIGlobalObject* glob = NativeGlobal(innerObj);
                 RefPtr<Promise> p = Promise::CreateFromExisting(glob, innerObj);
                 return p && NS_SUCCEEDED(p->QueryInterface(*iid, dest));
             }
         }
-#endif // SPIDERMONKEY_PROMISE
     }
 
     RefPtr<nsXPCWrappedJS> wrapper;
     nsresult rv = nsXPCWrappedJS::GetNewOrUsed(src, *iid, getter_AddRefs(wrapper));
     if (pErr)
         *pErr = rv;
 
     if (NS_FAILED(rv) || !wrapper)
--- a/python/mozbuild/mozbuild/mozinfo.py
+++ b/python/mozbuild/mozbuild/mozinfo.py
@@ -90,17 +90,16 @@ def build_dict(config, env=os.environ):
     d['asan'] = substs.get('MOZ_ASAN') == '1'
     d['tsan'] = substs.get('MOZ_TSAN') == '1'
     d['telemetry'] = substs.get('MOZ_TELEMETRY_REPORTING') == '1'
     d['tests_enabled'] = substs.get('ENABLE_TESTS') == "1"
     d['bin_suffix'] = substs.get('BIN_SUFFIX', '')
     d['addon_signing'] = substs.get('MOZ_ADDON_SIGNING') == '1'
     d['require_signing'] = substs.get('MOZ_REQUIRE_SIGNING') == '1'
     d['official'] = bool(substs.get('MOZILLA_OFFICIAL'))
-    d['sm_promise'] = bool(substs.get('SPIDERMONKEY_PROMISE'))
 
     def guess_platform():
         if d['buildapp'] in ('browser', 'mulet'):
             p = d['os']
             if p == 'mac':
                 p = 'macosx64'
             elif d['bits'] == 64:
                 p = '{}64'.format(p)
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -465,20 +465,18 @@ CycleCollectedJSContext::~CycleCollected
   MOZ_ASSERT(mStableStateEvents.IsEmpty());
 
   // Clear mPendingException first, since it might be cycle collected.
   mPendingException = nullptr;
 
   MOZ_ASSERT(mDebuggerPromiseMicroTaskQueue.empty());
   MOZ_ASSERT(mPromiseMicroTaskQueue.empty());
 
-#ifdef SPIDERMONKEY_PROMISE
   mUncaughtRejections.reset();
   mConsumedRejections.reset();
-#endif // SPIDERMONKEY_PROMISE
 
   JS_DestroyContext(mJSContext);
   mJSContext = nullptr;
   nsCycleCollector_forgetJSContext();
 
   mozilla::dom::DestroyScriptSettings();
 
   mOwningThread->SetScriptObserver(nullptr);
@@ -545,22 +543,20 @@ CycleCollectedJSContext::Initialize(JSCo
   static js::DOMCallbacks DOMcallbacks = {
     InstanceClassHasProtoAtDepth
   };
   SetDOMCallbacks(mJSContext, &DOMcallbacks);
   js::SetScriptEnvironmentPreparer(mJSContext, &mEnvironmentPreparer);
 
   JS::SetGetIncumbentGlobalCallback(mJSContext, GetIncumbentGlobalCallback);
 
-#ifdef SPIDERMONKEY_PROMISE
   JS::SetEnqueuePromiseJobCallback(mJSContext, EnqueuePromiseJobCallback, this);
   JS::SetPromiseRejectionTrackerCallback(mJSContext, PromiseRejectionTrackerCallback, this);
   mUncaughtRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
   mConsumedRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
-#endif // SPIDERMONKEY_PROMISE
 
   JS::dbg::SetDebuggerMallocSizeOf(mJSContext, moz_malloc_size_of);
 
   nsCycleCollector_registerJSContext(this);
 
   return NS_OK;
 }
 
@@ -976,17 +972,16 @@ CycleCollectedJSContext::EnqueuePromiseJ
   if (aIncumbentGlobal) {
     global = xpc::NativeGlobal(aIncumbentGlobal);
   }
   nsCOMPtr<nsIRunnable> runnable = new PromiseJobRunnable(aJob, aAllocationSite, global);
   self->DispatchToMicroTask(runnable.forget());
   return true;
 }
 
-#ifdef SPIDERMONKEY_PROMISE
 /* static */
 void
 CycleCollectedJSContext::PromiseRejectionTrackerCallback(JSContext* aCx,
                                                          JS::HandleObject aPromise,
                                                          PromiseRejectionHandlingState state,
                                                          void* aData)
 {
 #ifdef DEBUG
@@ -996,17 +991,16 @@ CycleCollectedJSContext::PromiseRejectio
   MOZ_ASSERT(Get() == self);
 
   if (state == PromiseRejectionHandlingState::Unhandled) {
     PromiseDebugging::AddUncaughtRejection(aPromise);
   } else {
     PromiseDebugging::AddConsumedRejection(aPromise);
   }
 }
-#endif // SPIDERMONKEY_PROMISE
 
 struct JsGcTracer : public TraceCallbacks
 {
   virtual void Trace(JS::Heap<JS::Value>* aPtr, const char* aName,
                      void* aClosure) const override
   {
     JS::TraceEdge(static_cast<JSTracer*>(aClosure), aPtr, aName);
   }
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -219,22 +219,20 @@ private:
   static bool ContextCallback(JSContext* aCx, unsigned aOperation,
                               void* aData);
   static JSObject* GetIncumbentGlobalCallback(JSContext* aCx);
   static bool EnqueuePromiseJobCallback(JSContext* aCx,
                                         JS::HandleObject aJob,
                                         JS::HandleObject aAllocationSite,
                                         JS::HandleObject aIncumbentGlobal,
                                         void* aData);
-#ifdef SPIDERMONKEY_PROMISE
   static void PromiseRejectionTrackerCallback(JSContext* aCx,
                                               JS::HandleObject aPromise,
                                               PromiseRejectionHandlingState state,
                                               void* aData);
-#endif // SPIDERMONKEY_PROMISE
 
   virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
   void TraceNativeGrayRoots(JSTracer* aTracer);
 
   void AfterProcessMicrotask(uint32_t aRecursionDepth);
 public:
   void ProcessStableStateQueue();
 private:
@@ -401,34 +399,26 @@ public:
   // full GC.
   void PrepareWaitingZonesForGC();
 
   // Queue an async microtask to the current main or worker thread.
   virtual void DispatchToMicroTask(already_AddRefed<nsIRunnable> aRunnable);
 
   // Storage for watching rejected promises waiting for some client to
   // consume their rejection.
-#ifdef SPIDERMONKEY_PROMISE
   // Promises in this list have been rejected in the last turn of the
   // event loop without the rejection being handled.
   // Note that this can contain nullptrs in place of promises removed because
   // they're consumed before it'd be reported.
   JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mUncaughtRejections;
 
   // Promises in this list have previously been reported as rejected
   // (because they were in the above list), but the rejection was handled
   // in the last turn of the event loop.
   JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mConsumedRejections;
-#else
-  // We store values as `nsISupports` to avoid adding compile-time dependencies
-  // from xpcom to dom/promise, but they can really only have a single concrete
-  // type.
-  nsTArray<nsCOMPtr<nsISupports /* Promise */>> mUncaughtRejections;
-  nsTArray<nsCOMPtr<nsISupports /* Promise */ >> mConsumedRejections;
-#endif // SPIDERMONKEY_PROMISE
   nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
 
 private:
   JSGCThingParticipant mGCThingCycleCollectorGlobal;
 
   JSZoneParticipant mJSZoneCycleCollectorGlobal;
 
   JSContext* mJSContext;