Bug 901362 - Give EvaluateString consumers the option to propagate exceptions instead of reporting. r=gabor
authorBobby Holley <bobbyholley@gmail.com>
Thu, 08 Aug 2013 16:51:35 -0700
changeset 141845 901902206d277966d06c1b67e7d702ea671888c3
parent 141844 dacad5a4081141b0de7f63af3cd0799bbb7985c2
child 141846 adf7ff5f11d3155e0d8e2709c1616fa5069dae79
push id32246
push userbobbyholley@gmail.com
push dateThu, 08 Aug 2013 23:51:53 +0000
treeherdermozilla-inbound@901902206d27 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor
bugs901362
milestone26.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 901362 - Give EvaluateString consumers the option to propagate exceptions instead of reporting. r=gabor
dom/base/nsJSUtils.cpp
dom/base/nsJSUtils.h
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -201,16 +201,17 @@ nsJSUtils::EvaluateString(JSContext* aCx
                           JS::CompileOptions& aCompileOptions,
                           EvaluateOptions& aEvaluateOptions,
                           JS::Value* aRetValue)
 {
   PROFILER_LABEL("JS", "EvaluateString");
   MOZ_ASSERT_IF(aCompileOptions.versionSet,
                 aCompileOptions.version != JSVERSION_UNKNOWN);
   MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aRetValue);
+  MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aRetValue);
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
 
   // Unfortunately, the JS engine actually compiles scripts with a return value
   // in a different, less efficient way.  Furthermore, it can't JIT them in many
   // cases.  So we need to be explicitly told whether the caller cares about the
   // return value.  Callers use null to indicate they don't care.
   if (aRetValue) {
     *aRetValue = JSVAL_VOID;
@@ -240,22 +241,26 @@ nsJSUtils::EvaluateString(JSContext* aCx
     if (ok && aEvaluateOptions.coerceToString && !aRetValue->isUndefined()) {
       JSString* str = JS_ValueToString(aCx, *aRetValue);
       ok = !!str;
       *aRetValue = ok ? JS::StringValue(str) : JS::UndefinedValue();
     }
   }
 
   if (!ok) {
-    if (aRetValue) {
-      *aRetValue = JS::UndefinedValue();
+    if (aEvaluateOptions.reportUncaught) {
+      ReportPendingException(aCx);
+      if (aRetValue) {
+        *aRetValue = JS::UndefinedValue();
+      }
+    } else {
+      rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE
+                                      : NS_ERROR_OUT_OF_MEMORY;
+      JS_GetPendingException(aCx, aRetValue);
+      JS_ClearPendingException(aCx);
     }
-    // Tell XPConnect about any pending exceptions. This is needed
-    // to avoid dropping JS exceptions in case we got here through
-    // nested calls through XPConnect.
-    ReportPendingException(aCx);
   }
 
   // Wrap the return value into whatever compartment aCx was in.
   if (aRetValue && !JS_WrapValue(aCx, aRetValue))
     return NS_ERROR_OUT_OF_MEMORY;
-  return NS_OK;
+  return rv;
 }
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -61,24 +61,31 @@ public:
                                   const nsACString& aName,
                                   uint32_t aArgCount,
                                   const char** aArgArray,
                                   const nsAString& aBody,
                                   JSObject** aFunctionObject);
 
   struct EvaluateOptions {
     bool coerceToString;
+    bool reportUncaught;
 
     explicit EvaluateOptions() : coerceToString(false)
+                               , reportUncaught(true)
     {}
 
     EvaluateOptions& setCoerceToString(bool aCoerce) {
       coerceToString = aCoerce;
       return *this;
     }
+
+    EvaluateOptions& setReportUncaught(bool aReport) {
+      reportUncaught = aReport;
+      return *this;
+    }
   };
 
   static nsresult EvaluateString(JSContext* aCx,
                                  const nsAString& aScript,
                                  JS::Handle<JSObject*> aScopeObject,
                                  JS::CompileOptions &aCompileOptions,
                                  EvaluateOptions& aEvaluateOptions,
                                  JS::Value* aRetValue);