Bug 1394530 - Stop using optimized path for non PromiseObject. r=till, a=sledru
authorTooru Fujisawa <arai_a@mac.com>
Sun, 17 Sep 2017 19:52:04 +0900
changeset 356433 8549cf2dab3ef65f1691c32f15b0eb772d5448d1
parent 356432 55b435cbbb550e905f7a92cf26f7dbd9ecc0d6d0
child 356434 349acf56ff49a734349139efd633f884abd3bf77
push id7356
push userryanvm@gmail.com
push dateWed, 11 Oct 2017 17:58:23 +0000
treeherdermozilla-esr52@349acf56ff49 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill, sledru
bugs1394530
milestone52.4.2
Bug 1394530 - Stop using optimized path for non PromiseObject. r=till, a=sledru
js/src/builtin/Promise.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -2065,16 +2065,25 @@ PromiseObject::unforgeableResolve(JSCont
 
 // ES2016, 25.4.5.1, implemented in Promise.js.
 
 static PromiseReactionRecord*
 NewReactionRecord(JSContext* cx, HandleObject resultPromise, HandleValue onFulfilled,
                   HandleValue onRejected, HandleObject resolve, HandleObject reject,
                   HandleObject incumbentGlobalObject)
 {
+    // Either of the following conditions must be met:
+    //   * resultPromise is a PromiseObject
+    //   * resolve and reject are callable
+    // except for Async Generator, there resultPromise can be nullptr.
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), resolve);
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), IsCallable(resolve));
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), reject);
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), IsCallable(reject));
+
     Rooted<PromiseReactionRecord*> reaction(cx, NewObjectWithClassProto<PromiseReactionRecord>(cx));
     if (!reaction)
         return nullptr;
 
     assertSameCompartment(cx, resultPromise);
     assertSameCompartment(cx, onFulfilled);
     assertSameCompartment(cx, onRejected);
     assertSameCompartment(cx, resolve);
@@ -2375,17 +2384,17 @@ BlockOnPromise(JSContext* cx, HandleValu
         RootedObject resultPromise(cx, blockedPromise_);
         RootedObject resolveFun(cx);
         RootedObject rejectFun(cx);
 
         // By default, the blocked promise is added as an extra entry to the
         // rejected promises list.
         bool addToDependent = true;
 
-        if (C == PromiseCtor) {
+        if (C == PromiseCtor && resultPromise->is<PromiseObject>()) {
             addToDependent = false;
         } else {
             // 25.4.5.3., step 4.
             if (!NewPromiseCapability(cx, C, &resultPromise, &resolveFun, &rejectFun, true))
                 return false;
         }
 
         // 25.4.5.3., step 5.
@@ -2434,22 +2443,24 @@ BlockOnPromise(JSContext* cx, HandleValu
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
             return false;
         }
         ac.emplace(cx, unwrappedPromiseObj);
         if (!cx->compartment()->wrap(cx, &blockedPromise))
             return false;
     }
 
-    // If the object to depend on isn't a, maybe-wrapped, Promise instance,
-    // we ignore it. All this does is lose some small amount of debug
-    // information in scenarios that are highly unlikely to occur in useful
-    // code.
+    // If either the object to depend on or the object that gets blocked isn't
+    // a, maybe-wrapped, Promise instance, we ignore it. All this does is lose
+    // some small amount of debug information in scenarios that are highly
+    // unlikely to occur in useful code.
     if (!unwrappedPromiseObj->is<PromiseObject>())
         return true;
+    if (!blockedPromise_->is<PromiseObject>())
+        return true;
 
     Rooted<PromiseObject*> promise(cx, &unwrappedPromiseObj->as<PromiseObject>());
     return AddPromiseReaction(cx, promise, UndefinedHandleValue, UndefinedHandleValue,
                               blockedPromise, nullptr, nullptr, nullptr);
 }
 
 static MOZ_MUST_USE bool
 AddPromiseReaction(JSContext* cx, Handle<PromiseObject*> promise,