Bug 1322920 - Remove DOM Promise implementation. r=bz
authorTill Schneidereit <till@tillschneidereit.net>
Sun, 11 Dec 2016 09:12:01 -0800
changeset 449686 918e37b44bddf0ab04f59887a1bb753aa586b3d9
parent 449685 38470e52b9d3beb7f648d8726d0c731684ddb75c
child 449687 da76054452f3306b159d30584d4307ac3d612485
push id38624
push usermozilla@kaply.com
push dateWed, 14 Dec 2016 19:19:00 +0000
reviewersbz
bugs1322920
milestone53.0a1
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;