Bug 1418106 - Throw error when resolving or rejecting promise returned by async function with testing function. r=till
authorTooru Fujisawa <arai_a@mac.com>
Sun, 19 Nov 2017 23:32:26 +0900
changeset 392615 ba1f15d693990dbd8f114adb81187a2198e61311
parent 392614 6c90e8fb37c338b0a921befd2ddf9f17bbaa44e9
child 392616 ef82504a27826468cf9885b22380acefac277bda
push id32934
push userbtara@mozilla.com
push dateSun, 19 Nov 2017 21:52:12 +0000
treeherdermozilla-central@dd08f8b19cc3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1418106
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1418106 - Throw error when resolving or rejecting promise returned by async function with testing function. r=till
js/src/builtin/Promise.cpp
js/src/builtin/Promise.h
js/src/builtin/TestingFunctions.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -2507,16 +2507,23 @@ js::CreatePromiseObjectForAsync(JSContex
     if (!promise)
         return nullptr;
 
     AddPromiseFlags(*promise, PROMISE_FLAG_ASYNC);
     promise->setFixedSlot(PromiseSlot_AwaitGenerator, generatorVal);
     return promise;
 }
 
+bool
+js::IsPromiseForAsync(JSObject* promise)
+{
+    return promise->is<PromiseObject>() &&
+           PromiseHasAnyFlag(promise->as<PromiseObject>(), PROMISE_FLAG_ASYNC);
+}
+
 // ES 2018 draft 25.5.5.2 steps 3.f, 3.g.
 MOZ_MUST_USE bool
 js::AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise)
 {
     // Step 3.f.
     RootedValue exc(cx);
     if (!MaybeGetAndClearException(cx, &exc))
         return false;
--- a/js/src/builtin/Promise.h
+++ b/js/src/builtin/Promise.h
@@ -133,16 +133,19 @@ OriginalPromiseThen(JSContext* cx, Handl
 MOZ_MUST_USE JSObject*
 PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value);
 
 
 MOZ_MUST_USE PromiseObject*
 CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal);
 
 MOZ_MUST_USE bool
+IsPromiseForAsync(JSObject* promise);
+
+MOZ_MUST_USE bool
 AsyncFunctionReturned(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value);
 
 MOZ_MUST_USE bool
 AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise);
 
 MOZ_MUST_USE bool
 AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value);
 
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2049,16 +2049,21 @@ ResolvePromise(JSContext* cx, unsigned a
     mozilla::Maybe<AutoCompartment> ac;
     if (IsWrapper(promise)) {
         promise = UncheckedUnwrap(promise);
         ac.emplace(cx, promise);
         if (!cx->compartment()->wrap(cx, &resolution))
             return false;
     }
 
+    if (IsPromiseForAsync(promise)) {
+        JS_ReportErrorASCII(cx, "async function's promise shouldn't be manually resolved");
+        return false;
+    }
+
     bool result = JS::ResolvePromise(cx, promise, resolution);
     if (result)
         args.rval().setUndefined();
     return result;
 }
 
 static bool
 RejectPromise(JSContext* cx, unsigned argc, Value* vp)
@@ -2076,16 +2081,21 @@ RejectPromise(JSContext* cx, unsigned ar
     mozilla::Maybe<AutoCompartment> ac;
     if (IsWrapper(promise)) {
         promise = UncheckedUnwrap(promise);
         ac.emplace(cx, promise);
         if (!cx->compartment()->wrap(cx, &reason))
             return false;
     }
 
+    if (IsPromiseForAsync(promise)) {
+        JS_ReportErrorASCII(cx, "async function's promise shouldn't be manually rejected");
+        return false;
+    }
+
     bool result = JS::RejectPromise(cx, promise, reason);
     if (result)
         args.rval().setUndefined();
     return result;
 }
 
 static bool
 StreamsAreEnabled(JSContext* cx, unsigned argc, Value* vp)