diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index 38db74b020..0e1349d087 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -227,15 +227,6 @@ Promise::Then(JSContext* aCx, aRetval.setObject(*retval); } -// We need a dummy function to pass to JS::NewPromiseObject. -static bool -DoNothingPromiseExecutor(JSContext*, unsigned aArgc, JS::Value* aVp) -{ - JS::CallArgs args = CallArgsFromVp(aArgc, aVp); - args.rval().setUndefined(); - return true; -} - void Promise::CreateWrapper(JS::Handle aDesiredProto, ErrorResult& aRv) { @@ -246,17 +237,7 @@ Promise::CreateWrapper(JS::Handle aDesiredProto, ErrorResult& aRv) } JSContext* cx = jsapi.cx(); - JSFunction* doNothingFunc = - JS_NewFunction(cx, DoNothingPromiseExecutor, /* nargs = */ 2, - /* flags = */ 0, nullptr); - if (!doNothingFunc) { - JS_ClearPendingException(cx); - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - - JS::Rooted doNothingObj(cx, JS_GetFunctionObject(doNothingFunc)); - mPromiseObj = JS::NewPromiseObject(cx, doNothingObj, aDesiredProto); + mPromiseObj = JS::NewPromiseObject(cx, nullptr, aDesiredProto); if (!mPromiseObj) { JS_ClearPendingException(cx); aRv.Throw(NS_ERROR_OUT_OF_MEMORY); diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp index 4da00a8671..daeb2c3d68 100644 --- a/js/src/builtin/Promise.cpp +++ b/js/src/builtin/Promise.cpp @@ -2478,8 +2478,11 @@ RunResolutionFunction(JSContext *cx, HandleObject resolutionFun, HandleValue res { // The absence of a resolve/reject function can mean that, as an // optimization, those weren't created. In that case, a flag is set on - // the Promise object. There are also reactions where the Promise - // itself is missing. For those, there's nothing left to do here. + // the Promise object. (It's also possible to not have a resolution + // function without that flag being set. This can occur if a Promise + // subclass constructor passes null/undefined to `super()`.) + // There are also reactions where the Promise itself is missing. For + // those, there's nothing left to do here. assertSameCompartment(cx, resolutionFun); assertSameCompartment(cx, result); assertSameCompartment(cx, promiseObj); @@ -4826,7 +4829,7 @@ PromiseObject::reject(JSContext* cx, Handle promise, HandleValue return true; if (PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS)) - return RejectMaybeWrappedPromise(cx, promise, rejectionValue); + return ResolvePromise(cx, promise, rejectionValue, JS::PromiseState::Rejected); RootedValue funVal(cx, promise->getFixedSlot(PromiseSlot_RejectFunction)); MOZ_ASSERT(IsCallable(funVal)); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 6c10eba821..fc013c14cb 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4902,11 +4902,14 @@ JS_PUBLIC_API(JSObject*) JS::NewPromiseObject(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */) { MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); - MOZ_ASSERT(IsCallable(executor)); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); assertSameCompartment(cx, executor, proto); + if (!executor) + return PromiseObject::createSkippingExecutor(cx); + + MOZ_ASSERT(IsCallable(executor)); return PromiseObject::create(cx, executor, proto); } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index dc3af6bf87..2714533354 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -4536,9 +4536,14 @@ SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerCallb /** * Returns a new instance of the Promise builtin class in the current - * compartment, with the right slot layout. If a `proto` is passed, that gets - * set as the instance's [[Prototype]] instead of the original value of - * `Promise.prototype`. + * compartment, with the right slot layout. + * + * The `executor` can be a `nullptr`. In that case, the only way to resolve or + * reject the returned promise is via the `JS::ResolvePromise` and + * `JS::RejectPromise` JSAPI functions. + * + * If a `proto` is passed, that gets set as the instance's [[Prototype]] + * instead of the original value of `Promise.prototype`. */ extern JS_PUBLIC_API(JSObject*) NewPromiseObject(JSContext* cx, JS::HandleObject executor, JS::HandleObject proto = nullptr);