Bug 1197973 - Use MOZ_MUST_USE in AutoJSAPI. r=bz.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 14 Jul 2016 13:18:11 +1000
changeset 330391 5102f1b9bccae81f88e8431c817d6ecce5c45529
parent 330390 994235fda74bd1d05003546f98d23e46f6ceecef
child 330392 0659b20212650c5c3321a7e3aad9e44410fda10e
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1197973
milestone50.0a1
Bug 1197973 - Use MOZ_MUST_USE in AutoJSAPI. r=bz.
docshell/base/nsDocShell.cpp
dom/base/ScriptSettings.h
dom/base/nsDOMClassInfo.cpp
dom/fetch/Fetch.cpp
dom/html/nsBrowserElement.cpp
dom/promise/Promise.cpp
js/ipc/WrapperAnswer.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/nsXPConnect.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -14231,17 +14231,20 @@ nsDocShell::SetOriginAttributes(const Do
 NS_IMETHODIMP
 nsDocShell::SetOriginAttributesBeforeLoading(JS::Handle<JS::Value> aOriginAttributes)
 {
   if (!aOriginAttributes.isObject()) {
     return NS_ERROR_INVALID_ARG;
   }
 
   AutoJSAPI jsapi;
-  jsapi.Init(&aOriginAttributes.toObject());
+  if (!jsapi.Init(&aOriginAttributes.toObject())) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
   JSContext* cx = jsapi.cx();
   if (NS_WARN_IF(!cx)) {
     return NS_ERROR_FAILURE;
   }
 
   DocShellOriginAttributes attrs;
   if (!aOriginAttributes.isObject() || !attrs.Init(cx, aOriginAttributes)) {
     return NS_ERROR_INVALID_ARG;
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -220,39 +220,39 @@ public:
   // This uses the SafeJSContext (or worker equivalent), and enters the
   // compartment of aGlobalObject.
   // If aGlobalObject or its associated JS global are null then it returns
   // false and use of cx() will cause an assertion.
   //
   // If aGlobalObject represents a web-visible global, errors reported by this
   // AutoJSAPI as it comes off the stack will fire the relevant error events and
   // show up in the corresponding web console.
-  bool Init(nsIGlobalObject* aGlobalObject);
+  MOZ_MUST_USE bool Init(nsIGlobalObject* aGlobalObject);
 
   // This is a helper that grabs the native global associated with aObject and
   // invokes the above Init() with that.
-  bool Init(JSObject* aObject);
+  MOZ_MUST_USE bool Init(JSObject* aObject);
 
   // Unsurprisingly, this uses aCx and enters the compartment of aGlobalObject.
   // If aGlobalObject or its associated JS global are null then it returns
   // false and use of cx() will cause an assertion.
   // If aCx is null it will cause an assertion.
   //
   // If aGlobalObject represents a web-visible global, errors reported by this
   // AutoJSAPI as it comes off the stack will fire the relevant error events and
   // show up in the corresponding web console.
-  bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx);
+  MOZ_MUST_USE bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx);
 
   // Convenience functions to take an nsPIDOMWindow* or nsGlobalWindow*,
   // when it is more easily available than an nsIGlobalObject.
-  bool Init(nsPIDOMWindowInner* aWindow);
-  bool Init(nsPIDOMWindowInner* aWindow, JSContext* aCx);
+  MOZ_MUST_USE bool Init(nsPIDOMWindowInner* aWindow);
+  MOZ_MUST_USE bool Init(nsPIDOMWindowInner* aWindow, JSContext* aCx);
 
-  bool Init(nsGlobalWindow* aWindow);
-  bool Init(nsGlobalWindow* aWindow, JSContext* aCx);
+  MOZ_MUST_USE bool Init(nsGlobalWindow* aWindow);
+  MOZ_MUST_USE bool Init(nsGlobalWindow* aWindow, JSContext* aCx);
 
   JSContext* cx() const {
     MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
     MOZ_ASSERT(IsStackTop());
     return mCx;
   }
 
 #ifdef DEBUG
@@ -268,25 +268,25 @@ public:
   };
 
   // Transfers ownership of the current exception from the JS engine to the
   // caller. Callers must ensure that HasException() is true, and that cx()
   // is in a non-null compartment.
   //
   // Note that this fails if and only if we OOM while wrapping the exception
   // into the current compartment.
-  bool StealException(JS::MutableHandle<JS::Value> aVal);
+  MOZ_MUST_USE bool StealException(JS::MutableHandle<JS::Value> aVal);
 
   // Peek the current exception from the JS engine, without stealing it.
   // Callers must ensure that HasException() is true, and that cx() is in a
   // non-null compartment.
   //
   // Note that this fails if and only if we OOM while wrapping the exception
   // into the current compartment.
-  bool PeekException(JS::MutableHandle<JS::Value> aVal);
+  MOZ_MUST_USE bool PeekException(JS::MutableHandle<JS::Value> aVal);
 
   void ClearException() {
     MOZ_ASSERT(IsStackTop());
     JS_ClearPendingException(cx());
   }
 
 protected:
   // Protected constructor for subclasses.  This constructor initialises the
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -322,17 +322,19 @@ nsDOMClassInfo::GetNative(nsIXPConnectWr
 {
   return wrapper ? wrapper->Native() : static_cast<nsISupports*>(js::GetObjectPrivate(obj));
 }
 
 nsresult
 nsDOMClassInfo::DefineStaticJSVals()
 {
   AutoJSAPI jsapi;
-  jsapi.Init(xpc::UnprivilegedJunkScope());
+  if (!jsapi.Init(xpc::UnprivilegedJunkScope())) {
+    return NS_ERROR_UNEXPECTED;
+  }
   JSContext* cx = jsapi.cx();
 
 #define SET_JSID_TO_STRING(_id, _cx, _str)                              \
   if (JSString *str = ::JS_AtomizeAndPinString(_cx, _str))                             \
       _id = INTERNED_STRING_TO_JSID(_cx, str);                                \
   else                                                                        \
       return NS_ERROR_OUT_OF_MEMORY;
 
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -164,19 +164,22 @@ FetchRequest(nsIGlobalObject* aGlobal, c
   // policy type has been overridden.  Note, we must do this before
   // entering the global below.  Otherwise the IsCallerChrome() will
   // always fail.
   MOZ_ASSERT_IF(aInput.IsRequest() &&
                 aInput.GetAsRequest().IsContentPolicyTypeOverridden(),
                 nsContentUtils::IsCallerChrome());
 
   AutoJSAPI jsapi;
-  jsapi.Init(aGlobal);
+  if (!jsapi.Init(aGlobal)) {
+    aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+    return nullptr;
+  }
+
   JSContext* cx = jsapi.cx();
-
   JS::Rooted<JSObject*> jsGlobal(cx, aGlobal->GetGlobalJSObject());
   GlobalObject global(cx, jsGlobal);
 
   RefPtr<Request> request = Request::Constructor(global, aInput, aInit, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
@@ -1090,19 +1093,22 @@ FetchBody<Derived>::ContinueConsumeBody(
   if (NS_FAILED(aStatus)) {
     return;
   }
 
   // Finish successfully consuming body according to type.
   MOZ_ASSERT(aResult);
 
   AutoJSAPI jsapi;
-  jsapi.Init(DerivedClass()->GetParentObject());
+  if (!jsapi.Init(DerivedClass()->GetParentObject())) {
+    localPromise->MaybeReject(NS_ERROR_UNEXPECTED);
+    return;
+  }
+
   JSContext* cx = jsapi.cx();
-
   ErrorResult error;
 
   switch (mConsumeType) {
     case CONSUME_ARRAYBUFFER: {
       JS::Rooted<JSObject*> arrayBuffer(cx);
       BodyUtil::ConsumeArrayBuffer(cx, &arrayBuffer, aResultLength, aResult,
                                     error);
 
--- a/dom/html/nsBrowserElement.cpp
+++ b/dom/html/nsBrowserElement.cpp
@@ -256,17 +256,20 @@ nsBrowserElement::Download(const nsAStri
 {
   NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
   NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
 
   nsCOMPtr<nsIDOMDOMRequest> req;
   nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
   MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
   AutoJSAPI jsapi;
-  jsapi.Init(wrappedObj->GetJSObject());
+  if (!jsapi.Init(wrappedObj->GetJSObject())) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
   JSContext* cx = jsapi.cx();
   JS::Rooted<JS::Value> options(cx);
   aRv.MightThrowJSException();
   if (!ToJSValue(cx, aOptions, &options)) {
     aRv.StealExceptionFromJSContext(cx);
     return nullptr;
   }
   nsresult rv = mBrowserElementAPI->Download(aUrl, options, getter_AddRefs(req));
@@ -709,17 +712,20 @@ nsBrowserElement::ExecuteScript(const ns
 {
   NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
   NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
 
   nsCOMPtr<nsIDOMDOMRequest> req;
   nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
   MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
   AutoJSAPI jsapi;
-  jsapi.Init(wrappedObj->GetJSObject());
+  if (!jsapi.Init(wrappedObj->GetJSObject())) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
   JSContext* cx = jsapi.cx();
   JS::Rooted<JS::Value> options(cx);
   aRv.MightThrowJSException();
   if (!ToJSValue(cx, aOptions, &options)) {
     aRv.StealExceptionFromJSContext(cx);
     return nullptr;
   }
 
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -1899,18 +1899,21 @@ public:
     JSContext* cx = jsapi.cx();
 
     JS::Rooted<JS::Value> value(cx, aValue);
     JS::Rooted<JSObject*> values(cx, mValues);
     if (!JS_WrapValue(cx, &value) ||
         !JS_DefineElement(cx, values, index, value, JSPROP_ENUMERATE)) {
       MOZ_ASSERT(JS_IsExceptionPending(cx));
       JS::Rooted<JS::Value> exn(cx);
-      jsapi.StealException(&exn);
-      mPromise->MaybeReject(cx, exn);
+      if (!jsapi.StealException(&exn)) {
+        mPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
+      } else {
+        mPromise->MaybeReject(cx, exn);
+      }
     }
 
     --mCountdown;
     if (mCountdown == 0) {
       JS::Rooted<JS::Value> result(cx, JS::ObjectValue(*mValues));
       mPromise->MaybeResolve(cx, result);
     }
   }
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -38,17 +38,18 @@ WrapperAnswer::fail(AutoJSAPI& jsapi, Re
     // to the IPC code, and we don't want a JS failure to cause the death
     // of the child process.
 
     JSContext* cx = jsapi.cx();
     RootedValue exn(cx);
     if (!jsapi.HasException())
         return true;
 
-    jsapi.StealException(&exn);
+    if (!jsapi.StealException(&exn))
+        return true;
 
     if (JS_IsStopIteration(exn)) {
         *rs = ReturnStatus(ReturnStopIteration());
         return true;
     }
 
     // If this fails, we still don't want to exit. Just return an invalid
     // exception.
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -42,16 +42,17 @@
 
 #include "mozilla/AddonPathService.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/MacroForEach.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/UniquePtrExtensions.h"
+#include "mozilla/unused.h"
 
 using namespace mozilla;
 using namespace mozilla::scache;
 using namespace xpc;
 using namespace JS;
 
 // This JSClass exists to trick silly code that expects toString()ing the
 // global in a component scope to return something with "BackstagePass" in it
@@ -878,17 +879,18 @@ mozJSComponentLoader::ObjectForLocation(
                                     buf.get(), bytesRead, &function);
                 }
             }
         }
         // Propagate the exception, if one exists. Also, don't leave the stale
         // exception on this context.
         if (!script && !function && aPropagateExceptions &&
             jsapi.HasException()) {
-            jsapi.StealException(aException);
+            if (!jsapi.StealException(aException))
+                return NS_ERROR_OUT_OF_MEMORY;
         }
     }
 
     if (!script && !function) {
         return NS_ERROR_FAILURE;
     }
 
     // We must have a script or a function (but not both!) here.  We have a
@@ -943,17 +945,19 @@ mozJSComponentLoader::ObjectForLocation(
         } else {
             RootedValue rval(cx);
             ok = JS_CallFunction(aescx, obj, function,
                                  JS::HandleValueArray::empty(), &rval);
         }
 
         if (!ok) {
             if (aPropagateExceptions && aes.HasException()) {
-                aes.StealException(aException);
+                // Ignore return value because we're returning an error code
+                // anyway.
+                Unused << aes.StealException(aException);
             }
             aObject.set(nullptr);
             aTableScript.set(nullptr);
             return NS_ERROR_FAILURE;
         }
     }
 
     /* Freed when we remove from the table. */
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1781,17 +1781,19 @@ xpc::EvalInSandbox(JSContext* cx, Handle
         options.setFileAndLine(filenameBuf.get(), lineNo)
                .setVersion(jsVersion);
         MOZ_ASSERT(JS_IsGlobalObject(sandbox));
         ok = JS::Evaluate(sandcx, options,
                           PromiseFlatString(source).get(), source.Length(), &v);
 
         // If the sandbox threw an exception, grab it off the context.
         if (aes.HasException()) {
-            aes.StealException(&exn);
+            if (!aes.StealException(&exn)) {
+                return NS_ERROR_OUT_OF_MEMORY;
+            }
         }
     }
 
     //
     // Alright, we're back on the caller's cx. If an error occured, try to
     // wrap and set the exception. Otherwise, wrap the return value.
     //
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1268,31 +1268,33 @@ NewAddonId(JSContext* cx, const nsACStri
 
 bool
 SetAddonInterposition(const nsACString& addonIdStr, nsIAddonInterposition* interposition)
 {
     JSAddonId* addonId;
     // We enter the junk scope just to allocate a string, which actually will go
     // in the system zone.
     AutoJSAPI jsapi;
-    jsapi.Init(xpc::PrivilegedJunkScope());
+    if (!jsapi.Init(xpc::PrivilegedJunkScope()))
+        return false;
     addonId = NewAddonId(jsapi.cx(), addonIdStr);
     if (!addonId)
         return false;
     return XPCWrappedNativeScope::SetAddonInterposition(jsapi.cx(), addonId, interposition);
 }
 
 bool
 AllowCPOWsInAddon(const nsACString& addonIdStr, bool allow)
 {
     JSAddonId* addonId;
     // We enter the junk scope just to allocate a string, which actually will go
     // in the system zone.
     AutoJSAPI jsapi;
-    jsapi.Init(xpc::PrivilegedJunkScope());
+    if (!jsapi.Init(xpc::PrivilegedJunkScope()))
+        return false;
     addonId = NewAddonId(jsapi.cx(), addonIdStr);
     if (!addonId)
         return false;
     return XPCWrappedNativeScope::AllowCPOWsInAddon(jsapi.cx(), addonId, allow);
 }
 
 } // namespace xpc