Bug 972319, part 2 - Transition some code using JS_SaveExceptionState to JS::AutoSaveExceptionState. r=bholley.
authorJason Orendorff <jorendorff@mozilla.com>
Wed, 26 Feb 2014 08:55:34 -0600
changeset 171031 aacc99e7c1e5cf869249d77ce41e64ce14068f11
parent 171030 8aed2eaed137c5d5ab03a17bf3bd033048d2126e
child 171032 5d7c2275e34668e5f23ebec57517fdfeef6e1319
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbholley
bugs972319
milestone30.0a1
Bug 972319, part 2 - Transition some code using JS_SaveExceptionState to JS::AutoSaveExceptionState. r=bholley.
js/xpconnect/src/XPCDebug.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/xpconnect/src/XPCDebug.cpp
+++ b/js/xpconnect/src/XPCDebug.cpp
@@ -41,28 +41,23 @@ xpc_DumpJSStack(JSContext* cx, bool show
     }
     return true;
 }
 
 char*
 xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
                  bool showThisProps)
 {
-    char* buf;
-    JSExceptionState *state = JS_SaveExceptionState(cx);
-    if (!state)
-        DebugDump("%s", "Call to a debug function modifying state!\n");
+    JS::AutoSaveExceptionState state(cx);
 
-    JS_ClearPendingException(cx);
-
-    buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
+    char *buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
     if (!buf)
         DebugDump("%s", "Failed to format JavaScript stack for dump\n");
 
-    JS_RestoreExceptionState(cx, state);
+    state.restore();
     return buf;
 }
 
 /***************************************************************************/
 
 static void
 xpcDumpEvalErrorReporter(JSContext *cx, const char *message,
                          JSErrorReport *report)
@@ -94,30 +89,32 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx
         num++;
     }
 
     if (!frame) {
         DebugDump("%s", "invalid frame number!\n");
         return false;
     }
 
-    JSExceptionState* exceptionState = JS_SaveExceptionState(cx);
+    JS::AutoSaveExceptionState exceptionState(cx);
     JSErrorReporter older = JS_SetErrorReporter(cx, xpcDumpEvalErrorReporter);
 
     JS::RootedValue rval(cx);
     JSString* str;
     JSAutoByteString bytes;
     if (frame.evaluateInStackFrame(cx, text, strlen(text), "eval", 1, &rval) &&
         nullptr != (str = ToString(cx, rval)) &&
         bytes.encodeLatin1(cx, str)) {
         DebugDump("%s\n", bytes.ptr());
-    } else
+    } else {
         DebugDump("%s", "eval failed!\n");
+    }
+
     JS_SetErrorReporter(cx, older);
-    JS_RestoreExceptionState(cx, exceptionState);
+    exceptionState.restore();
     return true;
 }
 
 /***************************************************************************/
 
 JSTrapStatus
 xpc_DebuggerKeywordHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
                            jsval *rval, void *closure)
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -48,36 +48,26 @@ bool AutoScriptEvaluate::StartEvaluating
     mAutoCompartment.construct(mJSContext, scope);
 
     // Saving the exception state keeps us from interfering with another script
     // that may also be running on this context.  This occurred first with the
     // js debugger, as described in
     // http://bugzilla.mozilla.org/show_bug.cgi?id=88130 but presumably could
     // show up in any situation where a script calls into a wrapped js component
     // on the same context, while the context has a nonzero exception state.
-    // Because JS_SaveExceptionState/JS_RestoreExceptionState use malloc
-    // and addroot, we avoid them if possible by returning null (as opposed to
-    // a JSExceptionState with no information) when there is no pending
-    // exception.
-    if (JS_IsExceptionPending(mJSContext)) {
-        mState = JS_SaveExceptionState(mJSContext);
-        JS_ClearPendingException(mJSContext);
-    }
+    mState.construct(mJSContext);
 
     return true;
 }
 
 AutoScriptEvaluate::~AutoScriptEvaluate()
 {
     if (!mJSContext || !mEvaluated)
         return;
-    if (mState)
-        JS_RestoreExceptionState(mJSContext, mState);
-    else
-        JS_ClearPendingException(mJSContext);
+    mState.ref().restore();
 
     JS_EndRequest(mJSContext);
 
     if (mErrorReporterSet)
         JS_SetErrorReporter(mJSContext, nullptr);
 }
 
 // It turns out that some errors may be not worth reporting. So, this
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2933,18 +2933,17 @@ private:
 class MOZ_STACK_CLASS AutoScriptEvaluate
 {
 public:
     /**
      * Saves the JSContext as well as initializing our state
      * @param cx The JSContext, this can be null, we don't do anything then
      */
     AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-         : mJSContext(cx), mState(0), mErrorReporterSet(false),
-           mEvaluated(false) {
+         : mJSContext(cx), mErrorReporterSet(false), mEvaluated(false) {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     /**
      * Does the pre script evaluation and sets the error reporter if given
      * This function should only be called once, and will assert if called
      * more than once
      * @param errorReporter the error reporter callback function to set
@@ -2953,17 +2952,17 @@ public:
     bool StartEvaluating(JS::HandleObject scope, JSErrorReporter errorReporter = nullptr);
 
     /**
      * Does the post script evaluation and resets the error reporter
      */
     ~AutoScriptEvaluate();
 private:
     JSContext* mJSContext;
-    JSExceptionState* mState;
+    mozilla::Maybe<JS::AutoSaveExceptionState> mState;
     bool mErrorReporterSet;
     bool mEvaluated;
     mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     // No copying or assignment allowed
     AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
     AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;