Backed out changeset cfd2fd77ff04 (bug 1339999) for failing handling-oom-during-exception-throwing.js. r=backout on a CLOSED TREE
authorSebastian Hengst <archaeopteryx@coole-files.de>
Fri, 03 Mar 2017 15:43:24 +0100
changeset 345902 4dbbd735c27d7a4a2968c819c5022d31e71b2dc8
parent 345901 c3e6f013c7718a829dbd34f2941708fb86bca4b5
child 345903 e090bd2b732cfb91b4b84ac7803a2e3160ef0615
push id38337
push userkwierso@gmail.com
push dateSat, 04 Mar 2017 01:30:14 +0000
treeherderautoland@b691557cb7a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1339999
milestone54.0a1
backs outcfd2fd77ff046cfbe2d1693858f093df9af41d74
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
Backed out changeset cfd2fd77ff04 (bug 1339999) for failing handling-oom-during-exception-throwing.js. r=backout on a CLOSED TREE
js/src/builtin/Promise.cpp
js/src/jit-test/tests/promise/handling-oom-during-exception-throwing.js
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -126,44 +126,34 @@ NewPromiseAllDataHolder(JSContext* cx, H
 
     dataHolder->setFixedSlot(PromiseAllDataHolderSlot_Promise, ObjectValue(*resultPromise));
     dataHolder->setFixedSlot(PromiseAllDataHolderSlot_RemainingElements, Int32Value(1));
     dataHolder->setFixedSlot(PromiseAllDataHolderSlot_ValuesArray, valuesArray);
     dataHolder->setFixedSlot(PromiseAllDataHolderSlot_ResolveFunction, ObjectValue(*resolve));
     return dataHolder;
 }
 
-/**
- * Wrapper for GetAndClearException that handles cases where no exception is
- * pending, but an error occurred. This can be the case if an OOM was
- * encountered while throwing the error.
- */
-static bool
-MaybeGetAndClearException(JSContext* cx, MutableHandleValue rval)
-{
-    if (!cx->isExceptionPending())
-        return false;
-
-    return GetAndClearException(cx, rval);
-}
-
 static MOZ_MUST_USE bool RunResolutionFunction(JSContext *cx, HandleObject resolutionFun,
                                                HandleValue result, ResolutionMode mode,
                                                HandleObject promiseObj);
 
 // ES2016, 25.4.1.1.1, Steps 1.a-b.
 // Extracting all of this internal spec algorithm into a helper function would
 // be tedious, so the check in step 1 and the entirety of step 2 aren't
 // included.
 static bool
 AbruptRejectPromise(JSContext *cx, CallArgs& args, HandleObject promiseObj, HandleObject reject)
 {
+    // Not much we can do about uncatchable exceptions, so just bail.
+    if (!cx->isExceptionPending())
+        return false;
+
     // Step 1.a.
     RootedValue reason(cx);
-    if (!MaybeGetAndClearException(cx, &reason))
+    if (!GetAndClearException(cx, &reason))
         return false;
 
     if (!RunResolutionFunction(cx, reject, reason, RejectMode, promiseObj))
         return false;
 
     // Step 1.b.
     args.rval().setObject(*promiseObj);
     return true;
@@ -356,31 +346,30 @@ ResolvePromiseInternal(JSContext* cx, Ha
     RootedObject resolution(cx, &resolutionVal.toObject());
 
     // Step 6.
     if (resolution == promise) {
         // Step 6.a.
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                                   JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF);
         RootedValue selfResolutionError(cx);
-        if (!MaybeGetAndClearException(cx, &selfResolutionError))
-            return false;
+        MOZ_ALWAYS_TRUE(GetAndClearException(cx, &selfResolutionError));
 
         // Step 6.b.
         return RejectMaybeWrappedPromise(cx, promise, selfResolutionError);
     }
 
     // Step 8.
     RootedValue thenVal(cx);
     bool status = GetProperty(cx, resolution, resolution, cx->names().then, &thenVal);
 
     // Step 9.
     if (!status) {
         RootedValue error(cx);
-        if (!MaybeGetAndClearException(cx, &error))
+        if (!GetAndClearException(cx, &error))
             return false;
 
         return RejectMaybeWrappedPromise(cx, promise, error);
     }
 
     // Step 10 (implicit).
 
     // Step 11.
@@ -905,17 +894,19 @@ PromiseReactionJob(JSContext* cx, unsign
             handlerResult = argument;
         }
     } else {
         // Step 6.
         FixedInvokeArgs<1> args2(cx);
         args2[0].set(argument);
         if (!Call(cx, handlerVal, UndefinedHandleValue, args2, &handlerResult)) {
             resolutionMode = RejectMode;
-            if (!MaybeGetAndClearException(cx, &handlerResult))
+            // Not much we can do about uncatchable exceptions, so just bail
+            // for those.
+            if (!cx->isExceptionPending() || !GetAndClearException(cx, &handlerResult))
                 return false;
         }
     }
 
     // Steps 7-9.
     size_t hookSlot = resolutionMode == RejectMode
                       ? ReactionRecordSlot_Reject
                       : ReactionRecordSlot_Resolve;
@@ -982,17 +973,17 @@ PromiseResolveThenableJob(JSContext* cx,
     args2[1].set(rejectVal);
 
     RootedValue rval(cx);
 
     // In difference to the usual pattern, we return immediately on success.
     if (Call(cx, then, thenable, args2, &rval))
         return true;
 
-    if (!MaybeGetAndClearException(cx, &rval))
+    if (!GetAndClearException(cx, &rval))
         return false;
 
     FixedInvokeArgs<1> rejectArgs(cx);
     rejectArgs[0].set(rval);
 
     return Call(cx, rejectVal, UndefinedHandleValue, rejectArgs, &rval);
 }
 
@@ -1325,17 +1316,19 @@ PromiseObject::create(JSContext* cx, Han
 
         RootedValue calleeOrRval(cx, ObjectValue(*executor));
         success = Call(cx, calleeOrRval, UndefinedHandleValue, args, &calleeOrRval);
     }
 
     // Step 10.
     if (!success) {
         RootedValue exceptionVal(cx);
-        if (!MaybeGetAndClearException(cx, &exceptionVal))
+        // Not much we can do about uncatchable exceptions, so just bail
+        // for those.
+        if (!cx->isExceptionPending() || !GetAndClearException(cx, &exceptionVal))
             return nullptr;
 
         FixedInvokeArgs<1> args(cx);
 
         args[0].set(exceptionVal);
 
         // |rejectVal| is unused after this, so we can safely write to it.
         if (!Call(cx, rejectVal, UndefinedHandleValue, args, &rejectVal))
@@ -2127,19 +2120,23 @@ js::CreatePromiseObjectForAsync(JSContex
     promise->setFixedSlot(PromiseSlot_AwaitGenerator, generatorVal);
     return promise;
 }
 
 // Async Functions proposal 2.2 steps 3.f, 3.g.
 MOZ_MUST_USE bool
 js::AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise)
 {
+    // Not much we can do about uncatchable exceptions, so just bail.
+    if (!cx->isExceptionPending())
+        return false;
+
     // Step 3.f.
     RootedValue exc(cx);
-    if (!MaybeGetAndClearException(cx, &exc))
+    if (!GetAndClearException(cx, &exc))
         return false;
 
     if (!RejectMaybeWrappedPromise(cx, resultPromise, exc))
         return false;
 
     // Step 3.g.
     return true;
 }
deleted file mode 100644
--- a/js/src/jit-test/tests/promise/handling-oom-during-exception-throwing.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// |jit-test| error: out of memory
-var y = {
-    then: function(m) {
-        throw 0;
-    }
-};
-Promise.resolve(y);
-
-g = newGlobal();
-g.parent = this;
-g.eval("Debugger(parent).onExceptionUnwind = function(fr, e) {return {throw:e}};");
-gcparam("maxBytes", gcparam("gcBytes"));