Bug 1157754 part 1. Add a way to "catch" an ErrorResult, and a way to safely convert an ErrorResult to an nsresult. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Sun, 26 Apr 2015 22:38:17 -0400
changeset 241114 a03d304acdb37dbd7b1bf4d5b5267f2fbace336d
parent 241113 eff50867d7e130353d72c6074ff69a10c9d5a188
child 241115 c944fc7df69278ef6aee1cc1f71c8b987b448bd0
push id28652
push usercbook@mozilla.com
push dateMon, 27 Apr 2015 10:00:58 +0000
treeherdermozilla-central@8aff0d2a7bc7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1157754
milestone40.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 1157754 part 1. Add a way to "catch" an ErrorResult, and a way to safely convert an ErrorResult to an nsresult. r=peterv
dom/bindings/BindingUtils.cpp
dom/bindings/ErrorResult.h
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -373,16 +373,34 @@ ErrorResult::operator=(ErrorResult&& aRH
   }
   // Note: It's important to do this last, since this affects the condition
   // checks above!
   mResult = aRHS.mResult;
   aRHS.mResult = NS_OK;
   return *this;
 }
 
+void
+ErrorResult::SuppressException()
+{
+  WouldReportJSException();
+  if (IsErrorWithMessage()) {
+    ClearMessage();
+  } else if (IsJSException()) {
+    JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
+    // Just steal it into a stack value (unrooting it in the process)
+    // that we then allow to die.
+    JS::Rooted<JS::Value> temp(cx);
+    StealJSException(cx, &temp);
+  }
+  // We don't use AssignErrorCode, because we want to override existing error
+  // states, which AssignErrorCode is not allowed to do.
+  mResult = NS_OK;
+}
+
 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
@@ -72,16 +72,30 @@ public:
     AssignErrorCode(aRv);
   }
 
   void Throw(nsresult rv) {
     MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
     AssignErrorCode(rv);
   }
 
+  // Use SuppressException when you want to suppress any exception that might be
+  // on the ErrorResult.  After this call, the ErrorResult will be back a "no
+  // exception thrown" state.
+  void SuppressException();
+
+  // Use StealNSResult() when you want to safely convert the ErrorResult to an
+  // nsresult that you will then return to a caller.  This will
+  // SuppressException(), since there will no longer be a way to report it.
+  nsresult StealNSResult() {
+    nsresult rv = ErrorCode();
+    SuppressException();
+    return rv;
+  }
+
   void ThrowTypeError(const dom::ErrNum errorNumber, ...);
   void ThrowRangeError(const dom::ErrNum errorNumber, ...);
   void ReportErrorWithMessage(JSContext* cx);
   void ClearMessage();
   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