Bug 958816 - Make strings in nsIStackFrame API sane, r=bz
☠☠ backed out by 7b0a1d41b80f ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Fri, 17 Jan 2014 15:24:03 +0100
changeset 163952 965cf4cbedc833a357c2f738d362a669ed48466a
parent 163951 885523f03d87a7d8d80b3d7f49e3c091a1d36e2b
child 163953 ff662b5b45f4dcd08c4b64dba00c6ac4f99c4ab6
push id38591
push useramarchesini@mozilla.com
push dateFri, 17 Jan 2014 14:24:22 +0000
treeherdermozilla-inbound@965cf4cbedc8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs958816
milestone29.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 958816 - Make strings in nsIStackFrame API sane, r=bz
content/base/src/nsHostObjectProtocolHandler.cpp
dom/base/DOMError.cpp
dom/base/DOMException.cpp
dom/base/DOMException.h
dom/bindings/Exceptions.cpp
js/xpconnect/idl/xpccomponents.idl
js/xpconnect/idl/xpcexception.idl
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
xpcom/base/nsIException.idl
--- a/content/base/src/nsHostObjectProtocolHandler.cpp
+++ b/content/base/src/nsHostObjectProtocolHandler.cpp
@@ -89,41 +89,39 @@ class BlobURLsReporter MOZ_FINAL : publi
     nsAutoCString origin;
     nsCOMPtr<nsIURI> principalURI;
     if (NS_SUCCEEDED(aInfo->mPrincipal->GetURI(getter_AddRefs(principalURI)))
         && principalURI) {
       principalURI->GetPrePath(origin);
     }
 
     for (uint32_t i = 0; i < maxFrames && frame; ++i) {
-      nsAutoCString fileNameEscaped;
-      char* fileName = nullptr;
+      nsCString fileName;
       int32_t lineNumber = 0;
 
-      frame->GetFilename(&fileName);
+      frame->GetFilename(fileName);
       frame->GetLineNumber(&lineNumber);
 
-      if (fileName != nullptr && fileName[0] != '\0') {
+      if (!fileName.IsEmpty()) {
         stack += "js(";
-        fileNameEscaped = fileName;
         if (!origin.IsEmpty()) {
           // Make the file name root-relative for conciseness if possible.
           const char* originData;
           uint32_t originLen;
 
           originLen = origin.GetData(&originData);
           // If fileName starts with origin + "/", cut up to that "/".
-          if (strlen(fileName) >= originLen + 1 &&
-              memcmp(fileName, originData, originLen) == 0 &&
+          if (fileName.Length() >= originLen + 1 &&
+              memcmp(fileName.get(), originData, originLen) == 0 &&
               fileName[originLen] == '/') {
-            fileNameEscaped.Cut(0, originLen);
+            fileName.Cut(0, originLen);
           }
         }
-        fileNameEscaped.ReplaceChar('/', '\\');
-        stack += fileNameEscaped;
+        fileName.ReplaceChar('/', '\\');
+        stack += fileName;
         if (lineNumber > 0) {
           stack += ", line=";
           stack.AppendInt(lineNumber);
         }
         stack += ")/";
       }
 
       rv = frame->GetCaller(getter_AddRefs(frame));
--- a/dom/base/DOMError.cpp
+++ b/dom/base/DOMError.cpp
@@ -24,21 +24,21 @@ DOMError::DOMError(nsPIDOMWindow* aWindo
   : mWindow(aWindow)
 {
   SetIsDOMBinding();
 }
 
 DOMError::DOMError(nsPIDOMWindow* aWindow, nsresult aValue)
   : mWindow(aWindow)
 {
-  const char *name, *message;
-  NS_GetNameAndMessageForDOMNSResult(aValue, &name, &message);
+  nsCString name, message;
+  NS_GetNameAndMessageForDOMNSResult(aValue, name, message);
 
-  mName = NS_ConvertASCIItoUTF16(name);
-  mMessage = NS_ConvertASCIItoUTF16(message);
+  CopyUTF8toUTF16(name, mName);
+  CopyUTF8toUTF16(message, mMessage);
 
   SetIsDOMBinding();
 }
 
 DOMError::DOMError(nsPIDOMWindow* aWindow, const nsAString& aName)
   : mWindow(aWindow)
   , mName(aName)
 {
--- a/dom/base/DOMException.cpp
+++ b/dom/base/DOMException.cpp
@@ -84,49 +84,51 @@ static const struct ResultStruct
 #include "domerr.msg"
 };
 
 #undef DOM4_MSG_DEF
 #undef DOM_MSG_DEF
 
 static void
 NSResultToNameAndMessage(nsresult aNSResult,
-                         const char** aName,
-                         const char** aMessage,
+                         nsCString& aName,
+                         nsCString& aMessage,
                          uint16_t* aCode)
 {
-  *aName = nullptr;
-  *aMessage = nullptr;
+  aName.Truncate();
+  aMessage.Truncate();
   *aCode = 0;
   for (uint32_t idx = 0; idx < ArrayLength(sDOMErrorMsgMap); idx++) {
     if (aNSResult == sDOMErrorMsgMap[idx].mNSResult) {
-      *aName = sDOMErrorMsgMap[idx].mName;
-      *aMessage = sDOMErrorMsgMap[idx].mMessage;
+      aName.Rebind(sDOMErrorMsgMap[idx].mName,
+                   strlen(sDOMErrorMsgMap[idx].mName));
+      aMessage.Rebind(sDOMErrorMsgMap[idx].mMessage,
+                   strlen(sDOMErrorMsgMap[idx].mMessage));
       *aCode = sDOMErrorMsgMap[idx].mCode;
       return;
     }
   }
 
   NS_WARNING("Huh, someone is throwing non-DOM errors using the DOM module!");
 
   return;
 }
 
 nsresult
-NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
-                                   const char** aMessage, uint16_t* aCode)
+NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, nsACString& aName,
+                                   nsACString& aMessage, uint16_t* aCode)
 {
-  const char* name = nullptr;
-  const char* message = nullptr;
+  nsCString name;
+  nsCString message;
   uint16_t code = 0;
-  NSResultToNameAndMessage(aNSResult, &name, &message, &code);
+  NSResultToNameAndMessage(aNSResult, name, message, &code);
 
-  if (name && message) {
-    *aName = name;
-    *aMessage = message;
+  if (!name.IsEmpty() && !message.IsEmpty()) {
+    aName = name;
+    aMessage = message;
     if (aCode) {
       *aCode = code;
     }
     return NS_OK;
   }
 
   return NS_ERROR_NOT_AVAILABLE;
 }
@@ -165,29 +167,23 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Ex
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mInner)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   tmp->mThrownJSVal.setNull();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CI_INTERFACE_GETTER1(Exception, nsIXPCException)
 
-Exception::Exception(const char *aMessage,
+Exception::Exception(const nsACString& aMessage,
                      nsresult aResult,
-                     const char *aName,
+                     const nsACString& aName,
                      nsIStackFrame *aLocation,
                      nsISupports *aData)
-: mMessage(nullptr),
-  mResult(NS_OK),
-  mName(nullptr),
-  mLocation(nullptr),
-  mData(nullptr),
-  mFilename(nullptr),
+: mResult(NS_OK),
   mLineNumber(0),
-  mInner(nullptr),
   mInitialized(false),
   mHoldingJSVal(false)
 {
   SetIsDOMBinding();
 
   // A little hack... The nsIGenericModule nsIClassInfo scheme relies on there
   // having been at least one instance made via the factory. Otherwise, the
   // shared factory/classinsance object never gets created and our QI getter
@@ -230,41 +226,25 @@ Exception::Exception(const char *aMessag
       location = caller;
     }
   }
 
   Initialize(aMessage, aResult, aName, location, aData, nullptr);
 }
 
 Exception::Exception()
-  : mMessage(nullptr),
-    mResult(NS_OK),
-    mName(nullptr),
-    mFilename(nullptr),
+  : mResult(NS_OK),
     mLineNumber(-1),
     mInitialized(false),
     mHoldingJSVal(false)
 {
 }
 
 Exception::~Exception()
 {
-  if (mMessage) {
-    nsMemory::Free(mMessage);
-    mMessage = nullptr;
-  }
-  if (mName) {
-    nsMemory::Free(mName);
-    mName = nullptr;
-  }
-  if (mFilename) {
-    nsMemory::Free(mFilename);
-    mFilename = nullptr;
-  }
-
   if (mHoldingJSVal) {
     MOZ_ASSERT(NS_IsMainThread());
 
     mozilla::DropJSObjects(this);
   }
 }
 
 bool
@@ -291,76 +271,71 @@ Exception::StowJSVal(JS::Value& aVp)
 
   mThrownJSVal = aVp;
   if (!mHoldingJSVal) {
     mozilla::HoldJSObjects(this);
     mHoldingJSVal = true;
   }
 }
 
-/* readonly attribute string message; */
+/* readonly attribute AUTF8String message; */
 NS_IMETHODIMP
-Exception::GetMessageMoz(char** aMessage)
+Exception::GetMessageMoz(nsACString& aMessage)
 {
-  NS_ENSURE_ARG_POINTER(aMessage);
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
-  if (mMessage) {
-    *aMessage =
-      (char*) nsMemory::Clone(mMessage, sizeof(char)*(strlen(mMessage)+1));
-  } else {
-    *aMessage = nullptr;
-  }
-
+  aMessage.Assign(mMessage);
   return NS_OK;
 }
 
 /* readonly attribute nsresult result; */
 NS_IMETHODIMP
 Exception::GetResult(nsresult* aResult)
 {
   NS_ENSURE_ARG_POINTER(aResult);
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
   *aResult = mResult;
   return NS_OK;
 }
 
-/* readonly attribute string name; */
+/* readonly attribute AUTF8String name; */
 NS_IMETHODIMP
-Exception::GetName(char** aName)
+Exception::GetName(nsACString& aName)
 {
-  NS_ENSURE_ARG_POINTER(aName);
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
-  const char* name = mName;
-  if (!name) {
-    nsXPCException::NameAndFormatForNSResult(mResult, &name, nullptr);
-  }
+  if (!mName.IsEmpty()) {
+    aName.Assign(mName);
+  } else {
+    aName.Truncate();
 
-  if (name) {
-    *aName = (char*) nsMemory::Clone(name, sizeof(char)*(strlen(name)+1));
-  } else {
-    *aName = nullptr;
+    const char* name = nullptr;
+    nsXPCException::NameAndFormatForNSResult(mResult, &name, nullptr);
+
+    if (name) {
+      aName.Assign(name);
+    }
   }
 
   return NS_OK;
 }
 
-/* readonly attribute string filename; */
+/* readonly attribute AUTF8String filename; */
 NS_IMETHODIMP
-Exception::GetFilename(char** aFilename)
+Exception::GetFilename(nsACString& aFilename)
 {
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (mLocation) {
     return mLocation->GetFilename(aFilename);
   }
 
-  XPC_STRING_GETTER_BODY(aFilename, mFilename);
+  aFilename.Assign(mFilename);
+  return NS_OK;
 }
 
 /* readonly attribute uint32_t lineNumber; */
 NS_IMETHODIMP
 Exception::GetLineNumber(uint32_t *aLineNumber)
 {
   NS_ENSURE_ARG_POINTER(aLineNumber);
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
@@ -418,80 +393,70 @@ Exception::GetInner(nsIException** aExce
   NS_ENSURE_ARG_POINTER(aException);
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
   nsCOMPtr<nsIException> inner = mInner;
   inner.forget(aException);
   return NS_OK;
 }
 
-/* string toString (); */
+/* AUTF8String toString (); */
 NS_IMETHODIMP
-Exception::ToString(char **_retval)
+Exception::ToString(nsACString& _retval)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
   static const char defaultMsg[] = "<no message>";
   static const char defaultLocation[] = "<unknown>";
   static const char format[] =
 "[Exception... \"%s\"  nsresult: \"0x%x (%s)\"  location: \"%s\"  data: %s]";
 
-  char* indicatedLocation = nullptr;
+  nsCString location;
 
   if (mLocation) {
     // we need to free this if it does not fail
-    nsresult rv = mLocation->ToString(&indicatedLocation);
+    nsresult rv = mLocation->ToString(location);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  const char* msg = mMessage ? mMessage : nullptr;
-  const char* location = indicatedLocation ?
-                              indicatedLocation : defaultLocation;
-  const char* resultName = mName;
+  if (location.IsEmpty()) {
+    location.Assign(defaultLocation);
+  }
+
+  const char* msg = mMessage.IsEmpty() ? nullptr : mMessage.get();
+
+  const char* resultName = mName.IsEmpty() ? nullptr: mName.get();
   if (!resultName &&
       !nsXPCException::NameAndFormatForNSResult(mResult, &resultName,
                                                 (!msg) ? &msg : nullptr)) {
     if (!msg) {
       msg = defaultMsg;
     }
     resultName = "<unknown>";
   }
   const char* data = mData ? "yes" : "no";
 
-  char* temp = JS_smprintf(format, msg, mResult, resultName, location, data);
-  if (indicatedLocation) {
-    nsMemory::Free(indicatedLocation);
-  }
-
-  char* final = nullptr;
-  if (temp) {
-    final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1));
-    JS_smprintf_free(temp);
-  }
-
-  *_retval = final;
-  return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+  _retval.Truncate();
+  _retval.AppendPrintf(format, msg, mResult, resultName,
+                       location.get(), data);
+  return NS_OK;
 }
 
-/* void initialize (in string aMessage, in nsresult aResult, in string aName, in nsIStackFrame aLocation, in nsISupports aData, in nsIException aInner); */
+/* void initialize (in AUTF8String aMessage, in nsresult aResult,
+ *                  in AUTF8String aName, in nsIStackFrame aLocation,
+ *                  in nsISupports aData, in nsIException aInner); */
 NS_IMETHODIMP
-Exception::Initialize(const char *aMessage, nsresult aResult, const char *aName, nsIStackFrame *aLocation, nsISupports *aData, nsIException *aInner)
+Exception::Initialize(const nsACString& aMessage, nsresult aResult,
+                      const nsACString& aName, nsIStackFrame *aLocation,
+                      nsISupports *aData, nsIException *aInner)
 {
   NS_ENSURE_FALSE(mInitialized, NS_ERROR_ALREADY_INITIALIZED);
 
-  if (aMessage) {
-    mMessage =
-      (char*) nsMemory::Clone(aMessage, sizeof(char)*(strlen(aMessage)+1));
-  }
-
-  if (aName) {
-    mName = (char*) nsMemory::Clone(aName, sizeof(char)*(strlen(aName)+1));
-  }
-
+  mMessage = aMessage;
+  mName = aName;
   mResult = aResult;
 
   if (aLocation) {
     mLocation = aLocation;
   } else {
     nsresult rv;
     nsXPConnect* xpc = nsXPConnect::XPConnect();
     rv = xpc->GetCurrentJSStack(getter_AddRefs(mLocation));
@@ -511,56 +476,53 @@ JSObject*
 Exception::WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
 {
   return ExceptionBinding::Wrap(cx, scope, this);
 }
 
 void
 Exception::GetMessageMoz(nsString& retval)
 {
-  char* str = nullptr;
+  nsCString str;
 #ifdef DEBUG
   DebugOnly<nsresult> rv = 
 #endif
-  GetMessageMoz(&str);
+  GetMessageMoz(str);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   CopyUTF8toUTF16(str, retval);
-  nsMemory::Free(str);
 }
 
 uint32_t
 Exception::Result() const
 {
   return (uint32_t)mResult;
 }
 
 void
 Exception::GetName(nsString& retval)
 {
-  char* str = nullptr;
+  nsCString str;
 #ifdef DEBUG
   DebugOnly<nsresult> rv =
 #endif
-  GetName(&str);
+  GetName(str);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   CopyUTF8toUTF16(str, retval);
-  nsMemory::Free(str);
 }
 
 void
 Exception::GetFilename(nsString& retval)
 {
-  char* str = nullptr;
+  nsCString str;
 #ifdef DEBUG
   DebugOnly<nsresult> rv =
 #endif
-  GetFilename(&str);
+  GetFilename(str);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   CopyUTF8toUTF16(str, retval);
-  nsMemory::Free(str);
 }
 
 uint32_t
 Exception::LineNumber() const
 {
   if (mLocation) {
     int32_t lineno;
     if (NS_SUCCEEDED(mLocation->GetLineNumber(&lineno))) {
@@ -597,35 +559,34 @@ Exception::GetData() const
 {
   nsCOMPtr<nsISupports> data = mData;
   return data.forget();
 }
 
 void
 Exception::Stringify(nsString& retval)
 {
-  char* str = nullptr;
+  nsCString str;
 #ifdef DEBUG
   DebugOnly<nsresult> rv =
 #endif
-  ToString(&str);
+  ToString(str);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   CopyUTF8toUTF16(str, retval);
-  nsMemory::Free(str);
 }
 
 NS_IMPL_ADDREF_INHERITED(DOMException, Exception)
 NS_IMPL_RELEASE_INHERITED(DOMException, Exception)
 NS_INTERFACE_MAP_BEGIN(DOMException)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDOMException)
 NS_INTERFACE_MAP_END_INHERITING(Exception)
 
-DOMException::DOMException(nsresult aRv, const char* aMessage,
-                           const char* aName, uint16_t aCode)
-  : Exception(nullptr, aRv, nullptr, nullptr, nullptr),
+DOMException::DOMException(nsresult aRv, const nsACString& aMessage,
+                           const nsACString& aName, uint16_t aCode)
+  : Exception(EmptyCString(), aRv, EmptyCString(), nullptr, nullptr),
     mName(aName),
     mMessage(aMessage),
     mCode(aCode)
 {
   SetIsDOMBinding();
 }
 
 NS_IMETHODIMP
@@ -642,32 +603,31 @@ DOMException::GetCode(uint16_t* aCode)
       doc->WarnOnceAbout(nsIDocument::eDOMExceptionCode);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DOMException::ToString(char **aReturn)
+DOMException::ToString(nsACString& aReturn)
 {
-  *aReturn = nullptr;
+  aReturn.Truncate();
 
   static const char defaultMsg[] = "<no message>";
   static const char defaultLocation[] = "<unknown>";
   static const char defaultName[] = "<unknown>";
   static const char format[] =
     "[Exception... \"%s\"  code: \"%d\" nsresult: \"0x%x (%s)\"  location: \"%s\"]";
 
   nsAutoCString location;
 
   if (mInner) {
-    nsXPIDLCString filename;
-
-    mInner->GetFilename(getter_Copies(filename));
+    nsCString filename;
+    mInner->GetFilename(filename);
 
     if (!filename.IsEmpty()) {
       uint32_t line_nr = 0;
 
       mInner->GetLineNumber(&line_nr);
 
       char *temp = PR_smprintf("%s Line: %d", filename.get(), line_nr);
       if (temp) {
@@ -676,23 +636,23 @@ DOMException::ToString(char **aReturn)
       }
     }
   }
 
   if (location.IsEmpty()) {
     location = defaultLocation;
   }
 
-  const char* msg = mMessage ? mMessage : defaultMsg;
-  const char* resultName = mName ? mName : defaultName;
+  const char* msg = !mMessage.IsEmpty() ? mMessage.get() : defaultMsg;
+  const char* resultName = !mName.IsEmpty() ? mName.get() : defaultName;
 
-  *aReturn = PR_smprintf(format, msg, mCode, mResult, resultName,
-                         location.get());
+  aReturn.AppendPrintf(format, msg, mCode, mResult, resultName,
+                       location.get());
 
-  return *aReturn ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+  return NS_OK;
 }
 
 void
 DOMException::GetName(nsString& retval)
 {
   CopyUTF8toUTF16(mName, retval);
 }
 
@@ -706,19 +666,19 @@ JSObject*
 DOMException::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return DOMExceptionBinding::Wrap(aCx, aScope, this);
 }
 
 /* static */already_AddRefed<DOMException>
 DOMException::Create(nsresult aRv)
 {
-  const char* name;
-  const char* message;
+  nsCString name;
+  nsCString message;
   uint16_t code;
-  NSResultToNameAndMessage(aRv, &name, &message, &code);
+  NSResultToNameAndMessage(aRv, name, message, &code);
   nsRefPtr<DOMException> inst =
     new DOMException(aRv, message, name, code);
   return inst.forget();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/DOMException.h
+++ b/dom/base/DOMException.h
@@ -16,23 +16,24 @@
 #include "jspubtd.h"
 #include "js/GCAPI.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsID.h"
 #include "nsIDOMDOMException.h"
 #include "nsWrapperCache.h"
 #include "xpcexception.h"
+#include "nsString.h"
 
 class nsIStackFrame;
 class nsString;
 
 nsresult
-NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
-                                   const char** aMessage,
+NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, nsACString& aName,
+                                   nsACString& aMessage,
                                    uint16_t* aCode = nullptr);
 
 namespace mozilla {
 namespace dom {
 
 #define MOZILLA_EXCEPTION_IID \
 { 0x55eda557, 0xeba0, 0x4fe3, \
   { 0xae, 0x2e, 0xf3, 0x94, 0x49, 0x23, 0x62, 0xd6 } }
@@ -80,31 +81,31 @@ public:
 
   already_AddRefed<nsISupports> GetData() const;
 
   void Stringify(nsString& retval);
 
   // XPCOM factory ctor.
   Exception();
 
-  Exception(const char *aMessage,
+  Exception(const nsACString& aMessage,
             nsresult aResult,
-            const char *aName,
+            const nsACString& aName,
             nsIStackFrame *aLocation,
             nsISupports *aData);
 
 protected:
   virtual ~Exception();
 
-  char*           mMessage;
+  nsCString       mMessage;
   nsresult        mResult;
-  char*           mName;
+  nsCString       mName;
   nsCOMPtr<nsIStackFrame> mLocation;
   nsCOMPtr<nsISupports> mData;
-  char*           mFilename;
+  nsCString       mFilename;
   int             mLineNumber;
   nsCOMPtr<nsIException> mInner;
   bool            mInitialized;
 
   bool mHoldingJSVal;
   JS::Heap<JS::Value> mThrownJSVal;
 
 private:
@@ -112,24 +113,24 @@ private:
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(Exception, MOZILLA_EXCEPTION_IID)
 
 class DOMException : public Exception,
                      public nsIDOMDOMException
 {
 public:
-  DOMException(nsresult aRv, const char* aMessage,
-               const char* aName, uint16_t aCode);
+  DOMException(nsresult aRv, const nsACString& aMessage,
+               const nsACString& aName, uint16_t aCode);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDOMEXCEPTION
 
   // nsIException overrides
-  NS_IMETHOD ToString(char **aReturn) MOZ_OVERRIDE;
+  NS_IMETHOD ToString(nsACString& aReturn) MOZ_OVERRIDE;
 
   // nsWrapperCache overrides
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
     MOZ_OVERRIDE;
 
   uint16_t Code() const {
     return mCode;
   }
@@ -140,19 +141,18 @@ public:
 
   static already_AddRefed<DOMException>
   Create(nsresult aRv);
 
 protected:
 
   virtual ~DOMException() {}
 
-  // Intentionally shadow the nsXPCException version.
-  const char* mName;
-  const char* mMessage;
+  nsCString mName;
+  nsCString mMessage;
 
   uint16_t mCode;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #ifdef __GNUC__
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -142,17 +142,18 @@ Throw(JSContext* aCx, nsresult aRv, cons
     break;
 
   default:
       break;
   }
 
   // If not, use the default.
   if (!finalException) {
-    finalException = new Exception(aMessage, aRv, nullptr, nullptr, nullptr);
+    finalException = new Exception(nsCString(aMessage), aRv,
+                                   EmptyCString(), nullptr, nullptr);
   }
 
   MOZ_ASSERT(finalException);
   if (!ThrowExceptionObject(aCx, finalException)) {
     // If we weren't able to throw an exception we're
     // most likely out of memory
     JS_ReportOutOfMemory(aCx);
   }
@@ -287,42 +288,38 @@ public:
                            int32_t aLineNumber,
                            nsIStackFrame* aCaller);
 
 private:
   bool IsJSFrame() const {
     return mLanguage == nsIProgrammingLanguage::JAVASCRIPT;
   }
 
-  const char* GetFilename();
-  const char* GetFunname();
   int32_t GetLineno();
 
   nsRefPtr<StackDescriptionOwner> mStackDescription;
   nsCOMPtr<nsIStackFrame> mCaller;
 
   // Cached values
-  char* mFilename;
-  char* mFunname;
+  nsCString mFilename;
+  nsCString mFunname;
   int32_t mLineno;
   uint32_t mLanguage;
 
   size_t mIndex;
 
   bool mFilenameInitialized;
   bool mFunnameInitialized;
   bool mLinenoInitialized;
   bool mCallerInitialized;
 };
 
 JSStackFrame::JSStackFrame(StackDescriptionOwner* aStackDescription,
                            size_t aIndex)
-  : mFilename(nullptr),
-    mFunname(nullptr),
-    mLineno(0)
+  : mLineno(0)
 {
   if (aStackDescription && aIndex < aStackDescription->NumFrames()) {
     mStackDescription = aStackDescription;
     mIndex = aIndex;
     mFilenameInitialized = false;
     mFunnameInitialized = false;
     mLinenoInitialized = false;
     mCallerInitialized = false;
@@ -335,22 +332,16 @@ JSStackFrame::JSStackFrame(StackDescript
     mLinenoInitialized = true;
     mCallerInitialized = true;
     mLanguage = nsIProgrammingLanguage::UNKNOWN;
   }
 }
 
 JSStackFrame::~JSStackFrame()
 {
-  if (mFilename) {
-    nsMemory::Free(mFilename);
-  }
-  if (mFunname) {
-    nsMemory::Free(mFunname);
-  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_2(JSStackFrame, mStackDescription, mCaller)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(JSStackFrame)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(JSStackFrame)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JSStackFrame)
@@ -361,110 +352,84 @@ NS_INTERFACE_MAP_END
 /* readonly attribute uint32_t language; */
 NS_IMETHODIMP JSStackFrame::GetLanguage(uint32_t* aLanguage)
 {
   *aLanguage = mLanguage;
   return NS_OK;
 }
 
 /* readonly attribute string languageName; */
-NS_IMETHODIMP JSStackFrame::GetLanguageName(char** aLanguageName)
+NS_IMETHODIMP JSStackFrame::GetLanguageName(nsACString& aLanguageName)
 {
   static const char js[] = "JavaScript";
   static const char cpp[] = "C++";
 
   if (IsJSFrame()) {
-    *aLanguageName = (char*) nsMemory::Clone(js, sizeof(js));
+    aLanguageName.AssignASCII(js);
   } else {
-    *aLanguageName = (char*) nsMemory::Clone(cpp, sizeof(cpp));
+    aLanguageName.AssignASCII(cpp);
   }
 
   return NS_OK;
 }
 
-const char*
-JSStackFrame::GetFilename()
+/* readonly attribute string filename; */
+NS_IMETHODIMP JSStackFrame::GetFilename(nsACString& aFilename)
 {
   if (!mFilenameInitialized) {
     JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
     if (desc.script()) {
       // This cx dance is silly, since JS_GetScriptFilename ignores
       // its cx argument.
       JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
       JSAutoRequest ar(cx);
       JSAutoCompartment ac(cx, desc.script());
       const char* filename = JS_GetScriptFilename(cx, desc.script());
       if (filename) {
-        mFilename =
-          (char*)nsMemory::Clone(filename, sizeof(char)*(strlen(filename)+1));
+        mFilename.Assign(filename);
       }
     }
     mFilenameInitialized = true;
   }
 
-  return mFilename;
-}
-
-/* readonly attribute string filename; */
-NS_IMETHODIMP JSStackFrame::GetFilename(char** aFilename)
-{
-  NS_ENSURE_ARG_POINTER(aFilename);
-
-  const char* filename = GetFilename();
-  if (filename) {
-    *aFilename = (char*) nsMemory::Clone(filename,
-                                         sizeof(char)*(strlen(filename)+1));
+  if (mFilename.IsEmpty()) {
+    aFilename.SetIsVoid(true);
   } else {
-    *aFilename = nullptr;
+    aFilename.Assign(mFilename);
   }
-
   return NS_OK;
 }
 
-const char*
-JSStackFrame::GetFunname()
+/* readonly attribute string name; */
+NS_IMETHODIMP JSStackFrame::GetName(nsACString& aFunction)
 {
   if (!mFunnameInitialized) {
     JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
     if (desc.fun() && desc.script()) {
       JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
       JSAutoRequest ar(cx);
       JSAutoCompartment ac(cx, desc.script());
       JS::Rooted<JSFunction*> fun(cx, desc.fun());
       JS::Rooted<JSString*> funid(cx, JS_GetFunctionDisplayId(fun));
       if (funid) {
         size_t length = JS_GetStringEncodingLength(cx, funid);
         if (length != size_t(-1)) {
-          mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
-          if (mFunname) {
-            JS_EncodeStringToBuffer(cx, funid, mFunname, length);
-            mFunname[length] = '\0';
-          }
+          mFunname.SetLength(uint32_t(length));
+          JS_EncodeStringToBuffer(cx, funid, mFunname.BeginWriting(), length);
         }
       }
     }
     mFunnameInitialized = true;
   }
 
-  return mFunname;
-}
-
-/* readonly attribute string name; */
-NS_IMETHODIMP JSStackFrame::GetName(char** aFunction)
-{
-  NS_ENSURE_ARG_POINTER(aFunction);
-
-  const char* funname = GetFunname();
-  if (funname) {
-    *aFunction = (char*) nsMemory::Clone(funname,
-                                         sizeof(char)*(strlen(funname)+1));
+  if (mFunname.IsEmpty()) {
+    aFunction.SetIsVoid(true);
   } else {
-    *aFunction = nullptr;
+    aFunction.Assign(mFunname);
   }
-
   return NS_OK;
 }
 
 int32_t
 JSStackFrame::GetLineno()
 {
   if (!mLinenoInitialized) {
     JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
@@ -477,54 +442,59 @@ JSStackFrame::GetLineno()
 
 /* readonly attribute int32_t lineNumber; */
 NS_IMETHODIMP JSStackFrame::GetLineNumber(int32_t* aLineNumber)
 {
   *aLineNumber = GetLineno();
   return NS_OK;
 }
 
-/* readonly attribute string sourceLine; */
-NS_IMETHODIMP JSStackFrame::GetSourceLine(char** aSourceLine)
+/* readonly attribute AUTF8String sourceLine; */
+NS_IMETHODIMP JSStackFrame::GetSourceLine(nsACString& aSourceLine)
 {
-  *aSourceLine = nullptr;
+  aSourceLine.Truncate();
   return NS_OK;
 }
 
 /* readonly attribute nsIStackFrame caller; */
 NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
 {
   if (!mCallerInitialized) {
     mCaller = new JSStackFrame(mStackDescription, mIndex+1);
     mCallerInitialized = true;
   }
   NS_IF_ADDREF(*aCaller = mCaller);
   return NS_OK;
 }
 
-/* string toString (); */
-NS_IMETHODIMP JSStackFrame::ToString(char** _retval)
+/* AUTF8String toString (); */
+NS_IMETHODIMP JSStackFrame::ToString(nsACString& _retval)
 {
+  _retval.Truncate();
+
   const char* frametype = IsJSFrame() ? "JS" : "native";
-  const char* filename = GetFilename();
-  if (!filename) {
-    filename = "<unknown filename>";
+
+  nsCString filename;
+  nsresult rv = GetFilename(filename);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (filename.IsEmpty()) {
+    filename.AssignASCII("<unknown filename>");
   }
-  const char* funname = GetFunname();
-  if (!funname) {
-    funname = "<TOP_LEVEL>";
+
+  nsCString funname;
+  rv = GetName(funname);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (funname.IsEmpty()) {
+    funname.AssignASCII("<TOP_LEVEL>");
   }
   static const char format[] = "%s frame :: %s :: %s :: line %d";
-  int len = sizeof(char)*
-              (strlen(frametype) + strlen(filename) + strlen(funname)) +
-            sizeof(format) + 3 * sizeof(mLineno);
-
-  char* buf = (char*) nsMemory::Alloc(len);
-  JS_snprintf(buf, len, format, frametype, filename, funname, GetLineno());
-  *_retval = buf;
+  _retval.AppendPrintf(format, frametype, filename.get(),
+                       funname.get(), GetLineno());
   return NS_OK;
 }
 
 /* static */ already_AddRefed<nsIStackFrame>
 JSStackFrame::CreateStack(JSContext* cx)
 {
   static const unsigned MAX_FRAMES = 100;
 
@@ -545,27 +515,18 @@ JSStackFrame::CreateStackFrameLocation(u
                                        const char* aFunctionName,
                                        int32_t aLineNumber,
                                        nsIStackFrame* aCaller)
 {
   nsRefPtr<JSStackFrame> self = new JSStackFrame(nullptr, 0);
 
   self->mLanguage = aLanguage;
   self->mLineno = aLineNumber;
-
-  if (aFilename) {
-    self->mFilename =
-      (char*)nsMemory::Clone(aFilename, sizeof(char)*(strlen(aFilename)+1));
-  }
-
-  if (aFunctionName) {
-    self->mFunname = 
-      (char*)nsMemory::Clone(aFunctionName,
-                             sizeof(char)*(strlen(aFunctionName)+1));
-  }
+  self->mFilename = aFilename;
+  self->mFunname = aFunctionName;
 
   self->mCaller = aCaller;
 
   return self.forget();
 }
 
 already_AddRefed<nsIStackFrame>
 CreateStack(JSContext* cx)
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -148,17 +148,17 @@ interface nsIXPCComponents_Utils : nsISu
      * var res = C.u.evalInSandbox("var five = 5; 2 + five", s);
      * var outerFive = s.five;
      * s.seven = res;
      * var thirtyFive = C.u.evalInSandbox("five * seven", s);
      */
     [implicit_jscontext,optional_argc]
     jsval evalInSandbox(in AString source, in jsval sandbox,
                         [optional] in jsval version,
-                        [optional] in jsval filename,
+                        [optional] in AUTF8String filename,
                         [optional] in long lineNo);
 
     /*
      * getSandboxMetadata is designed to be called from JavaScript only.
      *
      * getSandboxMetadata retrieves the metadata associated with
      * a sandbox object. It will return undefined if there
      * is no metadata attached to the sandbox.
--- a/js/xpconnect/idl/xpcexception.idl
+++ b/js/xpconnect/idl/xpcexception.idl
@@ -7,19 +7,19 @@
 #include "nsISupports.idl"
 #include "nsIException.idl"
 
 [scriptable, uuid(ce83229c-0a82-4ba4-937b-7fd4cd45f34b)]
 interface nsIXPCException : nsIException
 {
     // inherits methods from nsIException
 
-    void initialize(in string           aMessage,
+    void initialize(in AUTF8String      aMessage,
                     in nsresult         aResult,
-                    in string           aName,
+                    in AUTF8String      aName,
                     in nsIStackFrame    aLocation,
                     in nsISupports      aData,
                     in nsIException     aInner);
 };
 
 /* this goes into the C++ header verbatim. */
 %{ C++
 /********************************************************/
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1510,17 +1510,17 @@ AssembleSandboxMemoryReporterName(JSCont
     // Get the current source info from xpc.
     nsCOMPtr<nsIStackFrame> frame;
     xpc->GetCurrentJSStack(getter_AddRefs(frame));
 
     // Append the caller's location information.
     if (frame) {
         nsCString location;
         int32_t lineNumber = 0;
-        frame->GetFilename(getter_Copies(location));
+        frame->GetFilename(location);
         frame->GetLineNumber(&lineNumber);
 
         sandboxName.AppendLiteral(" (from: ");
         sandboxName.Append(location);
         sandboxName.AppendLiteral(":");
         sandboxName.AppendInt(lineNumber);
         sandboxName.AppendLiteral(")");
     }
@@ -1629,17 +1629,17 @@ ContextHolder::ContextHolder(JSContext *
 ContextHolder::~ContextHolder()
 {
     if (mJSContext)
         JS_DestroyContextNoGC(mJSContext);
 }
 
 nsresult
 xpc::EvalInSandbox(JSContext *cx, HandleObject sandboxArg, const nsAString& source,
-                   const char *filename, int32_t lineNo,
+                   const nsACString& filename, int32_t lineNo,
                    JSVersion jsVersion, bool returnStringOnly, MutableHandleValue rval)
 {
     JS_AbortIfWrongThread(JS_GetRuntime(cx));
     rval.set(UndefinedValue());
 
     bool waiveXray = xpc::WrapperFactory::HasWaiveXrayFlag(sandboxArg);
     RootedObject sandbox(cx, js::CheckedUnwrap(sandboxArg));
     if (!sandbox || js::GetObjectJSClass(sandbox) != &SandboxClass) {
@@ -1648,20 +1648,21 @@ xpc::EvalInSandbox(JSContext *cx, Handle
 
     nsIScriptObjectPrincipal *sop =
         (nsIScriptObjectPrincipal*)xpc_GetJSPrivate(sandbox);
     MOZ_ASSERT(sop, "Invalid sandbox passed");
     nsCOMPtr<nsIPrincipal> prin = sop->GetPrincipal();
     NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
 
     nsAutoCString filenameBuf;
-    if (!filename) {
+    if (!filename.IsVoid()) {
+        filenameBuf.Assign(filename);
+    } else {
         // Default to the spec of the principal.
         nsJSPrincipals::get(prin)->GetScriptLocation(filenameBuf);
-        filename = filenameBuf.get();
         lineNo = 1;
     }
 
     // We create a separate cx to do the sandbox evaluation. Scope it.
     RootedValue v(cx, UndefinedValue());
     RootedValue exn(cx, UndefinedValue());
     bool ok = true;
     {
@@ -1675,17 +1676,17 @@ xpc::EvalInSandbox(JSContext *cx, Handle
             return NS_ERROR_OUT_OF_MEMORY;
         }
         nsCxPusher pusher;
         pusher.Push(sandcx);
         JSAutoCompartment ac(sandcx, sandbox);
 
         JS::CompileOptions options(sandcx);
         options.setPrincipals(nsJSPrincipals::get(prin))
-               .setFileAndLine(filename, lineNo);
+               .setFileAndLine(filenameBuf.get(), lineNo);
         if (jsVersion != JSVERSION_DEFAULT)
                options.setVersion(jsVersion);
         JS::RootedObject rootedSandbox(sandcx, sandbox);
         ok = JS::Evaluate(sandcx, rootedSandbox, options,
                           PromiseFlatString(source).get(), source.Length(),
                           v.address());
         if (ok && returnStringOnly && !v.isUndefined()) {
             JSString *str = ToString(sandcx, v);
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -1856,18 +1856,20 @@ nsXPCComponents_Exception::CallOrConstru
         return NS_OK;
     }
 
     // Parse the arguments to the Exception constructor.
     ExceptionArgParser parser(cx, xpc);
     if (!parser.parse(args))
         return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
-    nsCOMPtr<nsIException> e = new Exception(parser.eMsg, parser.eResult,
-                                             nullptr, parser.eStack,
+    nsCOMPtr<nsIException> e = new Exception(nsCString(parser.eMsg),
+                                             parser.eResult,
+                                             EmptyCString(),
+                                             parser.eStack,
                                              parser.eData);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     RootedObject newObj(cx);
 
     if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
                                   getter_AddRefs(holder))) || !holder ||
         // Assign, not compare
@@ -2577,43 +2579,43 @@ nsXPCComponents_Utils::ReportError(Handl
     RootedString msgstr(cx, ToString(cx, error));
     if (!msgstr)
         return NS_OK;
 
     nsCOMPtr<nsIStackFrame> frame;
     nsXPConnect *xpc = nsXPConnect::XPConnect();
     xpc->GetCurrentJSStack(getter_AddRefs(frame));
 
-    nsXPIDLCString fileName;
+    nsCString fileName;
     int32_t lineNo = 0;
     if (frame) {
-        frame->GetFilename(getter_Copies(fileName));
+        frame->GetFilename(fileName);
         frame->GetLineNumber(&lineNo);
     }
 
     const jschar *msgchars = JS_GetStringCharsZ(cx, msgstr);
     if (!msgchars)
         return NS_OK;
 
     nsresult rv = scripterr->InitWithWindowID(
             nsDependentString(static_cast<const char16_t *>(msgchars)),
-            NS_ConvertUTF8toUTF16(fileName),
-            EmptyString(), lineNo, 0, 0, "XPConnect JavaScript", innerWindowID);
+            NS_ConvertUTF8toUTF16(fileName), EmptyString(), lineNo, 0, 0,
+            "XPConnect JavaScript", innerWindowID);
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
     console->LogMessage(scripterr);
     return NS_OK;
 }
 
 /* void evalInSandbox(in AString source, in nativeobj sandbox); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
                                      HandleValue sandboxVal,
                                      HandleValue version,
-                                     HandleValue filenameVal,
+                                     const nsACString& filenameArg,
                                      int32_t lineNumber,
                                      JSContext *cx,
                                      uint8_t optionalArgc,
                                      MutableHandleValue retval)
 {
     RootedObject sandbox(cx);
     if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox)
         return NS_ERROR_INVALID_ARG;
@@ -2637,42 +2639,35 @@ nsXPCComponents_Utils::EvalInSandbox(con
         {
             jsVersion = JSVERSION_LATEST;
         }
         if (jsVersion == JSVERSION_UNKNOWN)
             return NS_ERROR_INVALID_ARG;
     }
 
     // Optional fourth and fifth arguments: filename and line number.
-    nsXPIDLCString filename;
     int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1;
-    if (optionalArgc >= 2) {
-        JSString *filenameStr = ToString(cx, filenameVal);
-        if (!filenameStr)
-            return NS_ERROR_INVALID_ARG;
-
-        JSAutoByteString filenameBytes;
-        if (!filenameBytes.encodeLatin1(cx, filenameStr))
-            return NS_ERROR_INVALID_ARG;
-        filename = filenameBytes.ptr();
+    nsCString filename;
+    if (!filenameArg.IsVoid()) {
+        filename.Assign(filenameArg);
     } else {
         // Get the current source info from xpc.
         nsresult rv;
         nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
         NS_ENSURE_SUCCESS(rv, rv);
 
         nsCOMPtr<nsIStackFrame> frame;
         xpc->GetCurrentJSStack(getter_AddRefs(frame));
         if (frame) {
-            frame->GetFilename(getter_Copies(filename));
+            frame->GetFilename(filename);
             frame->GetLineNumber(&lineNo);
         }
     }
 
-    return xpc::EvalInSandbox(cx, sandbox, source, filename.get(), lineNo,
+    return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo,
                               jsVersion, false, retval);
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal,
                                           JSContext *cx, MutableHandleValue rval)
 {
     if (!sandboxVal.isObject())
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -1065,43 +1065,41 @@ XPCConvert::ConstructException(nsresult 
                                nsIException** exceptn,
                                JSContext* cx,
                                jsval* jsExceptionPtr)
 {
     MOZ_ASSERT(!cx == !jsExceptionPtr, "Expected cx and jsExceptionPtr to cooccur.");
 
     static const char format[] = "\'%s\' when calling method: [%s::%s]";
     const char * msg = message;
-    char* sz = nullptr;
     nsXPIDLString xmsg;
     nsAutoCString sxmsg;
 
     nsCOMPtr<nsIScriptError> errorObject = do_QueryInterface(data);
     if (errorObject) {
         if (NS_SUCCEEDED(errorObject->GetMessageMoz(getter_Copies(xmsg)))) {
             CopyUTF16toUTF8(xmsg, sxmsg);
             msg = sxmsg.get();
         }
     }
     if (!msg)
         if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &msg) || ! msg)
             msg = "<error>";
+
+    nsCString msgStr(msg);
     if (ifaceName && methodName)
-        msg = sz = JS_smprintf(format, msg, ifaceName, methodName);
+        msgStr.AppendPrintf(format, msg, ifaceName, methodName);
 
-    nsRefPtr<Exception> e = new Exception(msg, rv, nullptr, nullptr, data);
+    nsRefPtr<Exception> e = new Exception(msgStr, rv, EmptyCString(), nullptr, data);
 
     if (cx && jsExceptionPtr) {
         e->StowJSVal(*jsExceptionPtr);
     }
 
     e.forget(exceptn);
-
-    if (sz)
-        JS_smprintf_free(sz);
     return NS_OK;
 }
 
 /********************************/
 
 class MOZ_STACK_CLASS AutoExceptionRestorer
 {
 public:
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -894,21 +894,21 @@ nsXPCWrappedJSClass::CheckForException(X
                         "************************************************************\n";
                     static const char preamble[] =
                         "* Call to xpconnect wrapped JSObject produced this error:  *\n";
                     static const char cant_get_text[] =
                         "FAILED TO GET TEXT FROM EXCEPTION\n";
 
                     fputs(line, stdout);
                     fputs(preamble, stdout);
-                    char* text;
-                    if (NS_SUCCEEDED(xpc_exception->ToString(&text)) && text) {
-                        fputs(text, stdout);
+                    nsCString text;
+                    if (NS_SUCCEEDED(xpc_exception->ToString(text)) &&
+                        !text.IsEmpty()) {
+                        fputs(text.get(), stdout);
                         fputs("\n", stdout);
-                        nsMemory::Free(text);
                     } else
                         fputs(cant_get_text, stdout);
                     fputs(line, stdout);
                 }
 
                 // Log the exception to the JS Console, so that users can do
                 // something with it.
                 nsCOMPtr<nsIConsoleService> consoleService
@@ -921,41 +921,37 @@ nsXPCWrappedJSClass::CheckForException(X
                     if (NS_SUCCEEDED(rv))
                         scriptError = do_QueryInterface(errorData);
 
                     if (nullptr == scriptError) {
                         // No luck getting one from the exception, so
                         // try to cook one up.
                         scriptError = do_CreateInstance(XPC_SCRIPT_ERROR_CONTRACTID);
                         if (nullptr != scriptError) {
-                            char* exn_string;
-                            rv = xpc_exception->ToString(&exn_string);
+                            nsCString newMessage;
+                            rv = xpc_exception->ToString(newMessage);
                             if (NS_SUCCEEDED(rv)) {
-                                // use toString on the exception as the message
-                                NS_ConvertASCIItoUTF16 newMessage(exn_string);
-                                nsMemory::Free((void *) exn_string);
-
                                 // try to get filename, lineno from the first
                                 // stack frame location.
                                 int32_t lineNumber = 0;
-                                nsXPIDLCString sourceName;
+                                nsCString sourceName;
 
                                 nsCOMPtr<nsIStackFrame> location;
                                 xpc_exception->
                                     GetLocation(getter_AddRefs(location));
                                 if (location) {
                                     // Get line number w/o checking; 0 is ok.
                                     location->GetLineNumber(&lineNumber);
 
                                     // get a filename.
-                                    rv = location->GetFilename(getter_Copies(sourceName));
+                                    rv = location->GetFilename(sourceName);
                                 }
 
-                                rv = scriptError->InitWithWindowID(newMessage,
-                                                                   NS_ConvertASCIItoUTF16(sourceName),
+                                rv = scriptError->InitWithWindowID(NS_ConvertUTF8toUTF16(newMessage),
+                                                                   NS_ConvertUTF8toUTF16(sourceName),
                                                                    EmptyString(),
                                                                    lineNumber, 0, 0,
                                                                    "XPConnect JavaScript",
                                                                    nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
                                 if (NS_FAILED(rv))
                                     scriptError = nullptr;
                             }
                         }
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -893,19 +893,24 @@ NS_IMETHODIMP
 nsXPConnect::EvalInSandboxObject(const nsAString& source, const char *filename,
                                  JSContext *cx, JSObject *sandboxArg,
                                  bool returnStringOnly, MutableHandleValue rval)
 {
     if (!sandboxArg)
         return NS_ERROR_INVALID_ARG;
 
     RootedObject sandbox(cx, sandboxArg);
-    return EvalInSandbox(cx, sandbox, source, filename ? filename :
-                         "x-bogus://XPConnect/Sandbox", 1, JSVERSION_DEFAULT,
-                         returnStringOnly, rval);
+    nsCString filenameStr;
+    if (filename) {
+        filenameStr.Assign(filename);
+    } else {
+        filenameStr = NS_LITERAL_CSTRING("x-bogus://XPConnect/Sandbox");
+    }
+    return EvalInSandbox(cx, sandbox, source, filenameStr, 1,
+                         JSVERSION_DEFAULT, returnStringOnly, rval);
 }
 
 /* nsIXPConnectJSObjectHolder getWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo); */
 NS_IMETHODIMP
 nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext,
                                        JSObject * aScopeArg,
                                        nsIClassInfo *aClassInfo,
                                        nsIXPConnectJSObjectHolder **_retval)
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3522,17 +3522,17 @@ CreateSandboxObject(JSContext *cx, JS::M
 // and if no filename is provided it will use the codebase from the
 // principal and line number 1 as a fallback. if returnStringOnly is
 // true, then the result in *rval, or the exception in cx->exception
 // will be coerced into strings. If an exception is thrown converting
 // an exception to a string, evalInSandbox will return an NS_ERROR_*
 // result, and cx->exception will be empty.
 nsresult
 EvalInSandbox(JSContext *cx, JS::HandleObject sandbox, const nsAString& source,
-              const char *filename, int32_t lineNo,
+              const nsACString& filename, int32_t lineNo,
               JSVersion jsVersion, bool returnStringOnly,
               JS::MutableHandleValue rval);
 
 // Helper for retrieving metadata stored in a reserved slot. The metadata
 // is set during the sandbox creation using the "metadata" option.
 nsresult
 GetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
                    JS::MutableHandleValue rval);
--- a/xpcom/base/nsIException.idl
+++ b/xpcom/base/nsIException.idl
@@ -5,64 +5,60 @@
 
 /*
  * Interfaces for representing cross-language exceptions and stack traces.
  */
 
 
 #include "nsISupports.idl"
 
-// XXX - most "string"s in this file should probably move to Unicode
-//       so may as well use AStrings...
-
-
 [scriptable, uuid(91d82105-7c62-4f8b-9779-154277c0ee90)]
 interface nsIStackFrame : nsISupports
 {
     // see nsIProgrammingLanguage for list of language consts
     readonly attribute uint32_t                language;
-    readonly attribute string                  languageName;
-    readonly attribute string                  filename;
-    readonly attribute string                  name;
+    readonly attribute AUTF8String             languageName;
+    readonly attribute AUTF8String             filename;
+    readonly attribute AUTF8String             name;
     // Valid line numbers begin at '1'. '0' indicates unknown.
     readonly attribute int32_t                 lineNumber;
-    readonly attribute string                  sourceLine;
+    readonly attribute AUTF8String             sourceLine;
     readonly attribute nsIStackFrame           caller;
 
-    string toString();
+    AUTF8String toString();
 };
 
 [scriptable, uuid(F3A8D3B4-C424-4edc-8BF6-8974C983BA78)]
 interface nsIException : nsISupports
 {
     // A custom message set by the thrower.
-    [binaryname(MessageMoz)] readonly attribute string message;
+    [binaryname(MessageMoz)] readonly attribute AUTF8String message;
     // The nsresult associated with this exception.
     readonly attribute nsresult                result;
     // The name of the error code (ie, a string repr of |result|)
-    readonly attribute string                  name;
+    readonly attribute AUTF8String             name;
 
     // Filename location.  This is the location that caused the
     // error, which may or may not be a source file location.
     // For example, standard language errors would generally have
     // the same location as their top stack entry.  File
     // parsers may put the location of the file they were parsing,
     // etc.
 
     // null indicates "no data"
-    readonly attribute string                  filename;
+    readonly attribute AUTF8String             filename;
     // Valid line numbers begin at '1'. '0' indicates unknown.
     readonly attribute uint32_t                lineNumber;
     // Valid column numbers begin at 0. 
     // We don't have an unambiguous indicator for unknown.
     readonly attribute uint32_t                columnNumber;
 
     // A stack trace, if available.
     readonly attribute nsIStackFrame           location;
     // An inner exception that triggered this, if available.
     readonly attribute nsIException            inner;
 
     // Arbitary data for the implementation.
     readonly attribute nsISupports             data;
 
     // A generic formatter - make it suitable to print, etc.
-    string toString();
+    AUTF8String toString();
 };