Bug 1249652 part 1. Add a method on ErrorResult to steal an exception, if any, from a JSContext. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 24 Feb 2016 10:38:31 -0500
changeset 321736 cfa41433ed01a8dba9572f1d86ab6213fd349324
parent 321735 00cda66bd40083d8e2e14980a50090cc7cd8ab02
child 321737 09a878e63f05af0afd116f35d96d487bce554f51
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1249652
milestone47.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 1249652 part 1. Add a method on ErrorResult to steal an exception, if any, from a JSContext. r=khuey
dom/bindings/BindingUtils.cpp
dom/bindings/ErrorResult.h
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -492,16 +492,32 @@ ErrorResult::SetPendingException(JSConte
   }
   if (IsDOMException()) {
     SetPendingDOMException(cx);
     return;
   }
   SetPendingGenericErrorException(cx);
 }
 
+void
+ErrorResult::StealExceptionFromJSContext(JSContext* cx)
+{
+  MOZ_ASSERT(mMightHaveUnreportedJSException,
+             "Why didn't you tell us you planned to throw a JS exception?");
+
+  JS::Rooted<JS::Value> exn(cx);
+  if (!JS_GetPendingException(cx, &exn)) {
+    ThrowUncatchableException();
+    return;
+  }
+
+  ThrowJSException(cx, exn);
+  JS_ClearPendingException(cx);
+}
+
 namespace dom {
 
 bool
 DefineConstants(JSContext* cx, JS::Handle<JSObject*> obj,
                 const ConstantSpec* cs)
 {
   JS::Rooted<JS::Value> value(cx);
   for (; cs->name; ++cs) {
--- a/dom/bindings/ErrorResult.h
+++ b/dom/bindings/ErrorResult.h
@@ -179,16 +179,28 @@ public:
     if (!Failed()) {
       return false;
     }
 
     SetPendingException(cx);
     return true;
   }
 
+  // Use StealExceptionFromJSContext to convert a pending exception on a
+  // JSContext to an ErrorResult.  This function must be called only when a
+  // JSAPI operation failed.  It assumes that lack of pending exception on the
+  // JSContext means an uncatchable exception was thrown.
+  //
+  // Codepaths that might call this method must call MightThrowJSException even
+  // if the relevant JSAPI calls do not fail.
+  //
+  // When this function returns, JS_IsExceptionPending(cx) will definitely be
+  // false.
+  void StealExceptionFromJSContext(JSContext* cx);
+
   template<dom::ErrNum errorNumber, typename... Ts>
   void ThrowTypeError(Ts&&... messageArgs)
   {
     ThrowErrorWithMessage<errorNumber>(NS_ERROR_TYPE_ERR,
                                        Forward<Ts>(messageArgs)...);
   }
 
   template<dom::ErrNum errorNumber, typename... Ts>
@@ -197,20 +209,20 @@ public:
     ThrowErrorWithMessage<errorNumber>(NS_ERROR_RANGE_ERR,
                                        Forward<Ts>(messageArgs)...);
   }
 
   bool IsErrorWithMessage() const { return ErrorCode() == NS_ERROR_TYPE_ERR || ErrorCode() == NS_ERROR_RANGE_ERR; }
 
   // Facilities for throwing a preexisting JS exception value via this
   // ErrorResult.  The contract is that any code which might end up calling
-  // ThrowJSException() must call MightThrowJSException() even if no exception
-  // is being thrown.  Code that conditionally calls ToJSValue on this
-  // ErrorResult only if Failed() must first call WouldReportJSException even if
-  // this ErrorResult has not failed.
+  // ThrowJSException() or StealExceptionFromJSContext() must call
+  // MightThrowJSException() even if no exception is being thrown.  Code that
+  // conditionally calls ToJSValue on this ErrorResult only if Failed() must
+  // first call WouldReportJSException even if this ErrorResult has not failed.
   //
   // The exn argument to ThrowJSException can be in any compartment.  It does
   // not have to be in the compartment of cx.  If someone later uses it, they
   // will wrap it into whatever compartment they're working in, as needed.
   void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
   bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
 
   // Facilities for throwing a DOMException.  If an empty message string is