Bug 1289050 - Part 2: Use ASCII or Latin1 variants of JS_ReportError in not-simple cases. r=jwalden
authorTooru Fujisawa <arai_a@mac.com>
Mon, 15 Aug 2016 19:20:01 +0900
changeset 315607 e78af6564ec3b4f497f35387669aff74f963009f
parent 315606 778f50f8d2bc7876d16e4a27b13d108f1fa35684
child 315608 fb604e5ff982a3520651650ce53b4991ca479e31
push id82228
push userarai_a@mac.com
push dateThu, 29 Sep 2016 03:04:21 +0000
treeherdermozilla-inbound@e78af6564ec3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1289050
milestone52.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 1289050 - Part 2: Use ASCII or Latin1 variants of JS_ReportError in not-simple cases. r=jwalden
caps/nsScriptSecurityManager.cpp
dom/plugins/base/nsJSNPRuntime.cpp
js/src/builtin/Profilers.cpp
js/src/builtin/TestingFunctions.cpp
js/src/irregexp/RegExpEngine.cpp
js/src/irregexp/RegExpEngine.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/shell/js.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/wrappers/AccessCheck.cpp
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -142,24 +142,25 @@ GetPrincipalDomainOrigin(nsIPrincipal* a
   if (!uri) {
     aPrincipal->GetURI(getter_AddRefs(uri));
   }
   NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
 
   return GetOriginFromURI(uri, aOrigin);
 }
 
-inline void SetPendingException(JSContext *cx, const char *aMsg)
+inline void SetPendingExceptionASCII(JSContext *cx, const char *aMsg)
 {
-    JS_ReportError(cx, "%s", aMsg);
+    JS_ReportErrorASCII(cx, "%s", aMsg);
 }
 
 inline void SetPendingException(JSContext *cx, const char16_t *aMsg)
 {
-    JS_ReportError(cx, "%hs", aMsg);
+    // FIXME: Need to convert to UTF-8 (bug XXX).
+    JS_ReportErrorLatin1(cx, "%hs", aMsg);
 }
 
 // Helper class to get stuff from the ClassInfo and not waste extra time with
 // virtual method calls for things it has already gotten
 class ClassInfoData
 {
 public:
     ClassInfoData(nsIClassInfo *aClassInfo, const char *aName)
@@ -591,17 +592,17 @@ nsScriptSecurityManager::CheckLoadURIFro
 
     // Report error.
     nsAutoCString spec;
     if (NS_FAILED(aURI->GetAsciiSpec(spec)))
         return NS_ERROR_FAILURE;
     nsAutoCString msg("Access to '");
     msg.Append(spec);
     msg.AppendLiteral("' from script denied");
-    SetPendingException(cx, msg.get());
+    SetPendingExceptionASCII(cx, msg.get());
     return NS_ERROR_DOM_BAD_URI;
 }
 
 /**
  * Helper method to handle cases where a flag passed to
  * CheckLoadURIWithPrincipal means denying loading if the given URI has certain
  * nsIProtocolHandler flags set.
  * @return if success, access is allowed. Otherwise, deny access
@@ -1300,34 +1301,34 @@ nsScriptSecurityManager::CanCreateInstan
         return NS_OK;
     }
 
     //-- Access denied, report an error
     nsAutoCString errorMsg("Permission denied to create instance of class. CID=");
     char cidStr[NSID_LENGTH];
     aCID.ToProvidedString(cidStr);
     errorMsg.Append(cidStr);
-    SetPendingException(cx, errorMsg.get());
+    SetPendingExceptionASCII(cx, errorMsg.get());
     return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::CanGetService(JSContext *cx,
                                        const nsCID &aCID)
 {
     if (nsContentUtils::IsCallerChrome()) {
         return NS_OK;
     }
 
     //-- Access denied, report an error
     nsAutoCString errorMsg("Permission denied to get service. CID=");
     char cidStr[NSID_LENGTH];
     aCID.ToProvidedString(cidStr);
     errorMsg.Append(cidStr);
-    SetPendingException(cx, errorMsg.get());
+    SetPendingExceptionASCII(cx, errorMsg.get());
     return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
 }
 
 /////////////////////////////////////
 // Method implementing nsIObserver //
 /////////////////////////////////////
 const char sJSEnabledPrefName[] = "javascript.enabled";
 const char sFileOriginPolicyPrefName[] =
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -605,17 +605,17 @@ JSValToNPVariant(NPP npp, JSContext *cx,
 
   // Pass over ownership of npobj to *variant
   OBJECT_TO_NPVARIANT(npobj, *variant);
 
   return true;
 }
 
 static void
-ThrowJSException(JSContext *cx, const char *message)
+ThrowJSExceptionASCII(JSContext *cx, const char *message)
 {
   const char *ex = PeekException();
 
   if (ex) {
     nsAutoString ucex;
 
     if (message) {
       AppendASCIItoUTF16(message, ucex);
@@ -633,30 +633,30 @@ ThrowJSException(JSContext *cx, const ch
 
     if (str) {
       JS::Rooted<JS::Value> exn(cx, JS::StringValue(str));
       ::JS_SetPendingException(cx, exn);
     }
 
     PopException();
   } else {
-    ::JS_ReportError(cx, message);
+    ::JS_ReportErrorASCII(cx, message);
   }
 }
 
 static bool
 ReportExceptionIfPending(JSContext *cx)
 {
   const char *ex = PeekException();
 
   if (!ex) {
     return true;
   }
 
-  ThrowJSException(cx, nullptr);
+  ThrowJSExceptionASCII(cx, nullptr);
 
   return false;
 }
 
 nsJSObjWrapper::nsJSObjWrapper(NPP npp)
   : mJSObj(nullptr), mNpp(npp), mDestroyPending(false)
 {
   MOZ_COUNT_CTOR(nsJSObjWrapper);
@@ -731,18 +731,18 @@ nsJSObjWrapper::NP_HasMethod(NPObject *n
   if (NS_WARN_IF(!globalObject)) {
     return false;
   }
 
   dom::AutoEntryScript aes(globalObject, "NPAPI HasMethod");
   JSContext *cx = aes.cx();
 
   if (!npobj) {
-    ThrowJSException(cx,
-                     "Null npobj in nsJSObjWrapper::NP_HasMethod!");
+    ThrowJSExceptionASCII(cx,
+                          "Null npobj in nsJSObjWrapper::NP_HasMethod!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   JSAutoCompartment ac(cx, npjsobj->mJSObj);
 
@@ -767,17 +767,17 @@ doInvoke(NPObject *npobj, NPIdentifier m
   }
 
   // We're about to run script via JS_CallFunctionValue, so we need an
   // AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec.
   dom::AutoEntryScript aes(globalObject, "NPAPI doInvoke");
   JSContext *cx = aes.cx();
 
   if (!npobj || !result) {
-    ThrowJSException(cx, "Null npobj, or result in doInvoke!");
+    ThrowJSExceptionASCII(cx, "Null npobj, or result in doInvoke!");
 
     return false;
   }
 
   // Initialize *result
   VOID_TO_NPVARIANT(*result);
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
@@ -859,18 +859,18 @@ nsJSObjWrapper::NP_HasProperty(NPObject 
   if (NS_WARN_IF(!globalObject)) {
     return false;
   }
 
   dom::AutoEntryScript aes(globalObject, "NPAPI HasProperty");
   JSContext *cx = aes.cx();
 
   if (!npobj) {
-    ThrowJSException(cx,
-                     "Null npobj in nsJSObjWrapper::NP_HasProperty!");
+    ThrowJSExceptionASCII(cx,
+                          "Null npobj in nsJSObjWrapper::NP_HasProperty!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
   bool found, ok = false;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
@@ -897,18 +897,18 @@ nsJSObjWrapper::NP_GetProperty(NPObject 
   }
 
   // We're about to run script via JS_CallFunctionValue, so we need an
   // AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec.
   dom::AutoEntryScript aes(globalObject, "NPAPI get");
   JSContext *cx = aes.cx();
 
   if (!npobj) {
-    ThrowJSException(cx,
-                     "Null npobj in nsJSObjWrapper::NP_GetProperty!");
+    ThrowJSExceptionASCII(cx,
+                          "Null npobj in nsJSObjWrapper::NP_GetProperty!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
   JSAutoCompartment ac(cx, npjsobj->mJSObj);
@@ -931,18 +931,18 @@ nsJSObjWrapper::NP_SetProperty(NPObject 
   }
 
   // We're about to run script via JS_CallFunctionValue, so we need an
   // AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec.
   dom::AutoEntryScript aes(globalObject, "NPAPI set");
   JSContext *cx = aes.cx();
 
   if (!npobj) {
-    ThrowJSException(cx,
-                     "Null npobj in nsJSObjWrapper::NP_SetProperty!");
+    ThrowJSExceptionASCII(cx,
+                          "Null npobj in nsJSObjWrapper::NP_SetProperty!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
   bool ok = false;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
@@ -968,18 +968,18 @@ nsJSObjWrapper::NP_RemoveProperty(NPObje
   if (NS_WARN_IF(!globalObject)) {
     return false;
   }
 
   dom::AutoEntryScript aes(globalObject, "NPAPI RemoveProperty");
   JSContext *cx = aes.cx();
 
   if (!npobj) {
-    ThrowJSException(cx,
-                     "Null npobj in nsJSObjWrapper::NP_RemoveProperty!");
+    ThrowJSExceptionASCII(cx,
+                          "Null npobj in nsJSObjWrapper::NP_RemoveProperty!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
   JS::ObjectOpResult result;
@@ -1022,18 +1022,18 @@ nsJSObjWrapper::NP_Enumerate(NPObject *n
 
   dom::AutoEntryScript aes(globalObject, "NPAPI Enumerate");
   JSContext *cx = aes.cx();
 
   *idarray = 0;
   *count = 0;
 
   if (!npobj) {
-    ThrowJSException(cx,
-                     "Null npobj in nsJSObjWrapper::NP_Enumerate!");
+    ThrowJSExceptionASCII(cx,
+                          "Null npobj in nsJSObjWrapper::NP_Enumerate!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
   JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
@@ -1042,17 +1042,17 @@ nsJSObjWrapper::NP_Enumerate(NPObject *n
   JS::Rooted<JS::IdVector> ida(cx, JS::IdVector(cx));
   if (!JS_Enumerate(cx, jsobj, &ida)) {
     return false;
   }
 
   *count = ida.length();
   *idarray = (NPIdentifier *)PR_Malloc(*count * sizeof(NPIdentifier));
   if (!*idarray) {
-    ThrowJSException(cx, "Memory allocation failed for NPIdentifier!");
+    ThrowJSExceptionASCII(cx, "Memory allocation failed for NPIdentifier!");
     return false;
   }
 
   for (uint32_t i = 0; i < *count; i++) {
     JS::Rooted<JS::Value> v(cx);
     if (!JS_IdToValue(cx, ida[i], &v)) {
       PR_Free(*idarray);
       return false;
@@ -1211,17 +1211,17 @@ GetNPObject(JSContext *cx, JSObject *obj
 // SetProperty call.
 static bool
 NPObjWrapper_AddProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> v)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
-    ThrowJSException(cx, "Bad NPObject as private data!");
+    ThrowJSExceptionASCII(cx, "Bad NPObject as private data!");
 
     return false;
   }
 
   if (NPObjectIsOutOfProcessProxy(npobj)) {
     return true;
   }
 
@@ -1237,33 +1237,33 @@ NPObjWrapper_AddProperty(JSContext *cx, 
 
   // We must permit methods here since JS_DefineUCFunction() will add
   // the function as a property
   bool hasMethod = npobj->_class->hasMethod(npobj, identifier);
   if (!ReportExceptionIfPending(cx))
     return false;
 
   if (!hasMethod) {
-    ThrowJSException(cx, "Trying to add unsupported property on NPObject!");
+    ThrowJSExceptionASCII(cx, "Trying to add unsupported property on NPObject!");
 
     return false;
   }
 
   return true;
 }
 
 static bool
 NPObjWrapper_DelProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                          JS::ObjectOpResult &result)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->removeProperty) {
-    ThrowJSException(cx, "Bad NPObject as private data!");
+    ThrowJSExceptionASCII(cx, "Bad NPObject as private data!");
 
     return false;
   }
 
   PluginDestructionGuard pdg(LookupNPP(npobj));
 
   NPIdentifier identifier = JSIdToNPIdentifier(id);
 
@@ -1289,76 +1289,76 @@ NPObjWrapper_DelProperty(JSContext *cx, 
 static bool
 NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                          JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->setProperty) {
-    ThrowJSException(cx, "Bad NPObject as private data!");
+    ThrowJSExceptionASCII(cx, "Bad NPObject as private data!");
 
     return false;
   }
 
   // Find out what plugin (NPP) is the owner of the object we're
   // manipulating, and make it own any JSObject wrappers created here.
   NPP npp = LookupNPP(npobj);
 
   if (!npp) {
-    ThrowJSException(cx, "No NPP found for NPObject!");
+    ThrowJSExceptionASCII(cx, "No NPP found for NPObject!");
 
     return false;
   }
 
   PluginDestructionGuard pdg(npp);
 
   NPIdentifier identifier = JSIdToNPIdentifier(id);
 
   if (!NPObjectIsOutOfProcessProxy(npobj)) {
     bool hasProperty = npobj->_class->hasProperty(npobj, identifier);
     if (!ReportExceptionIfPending(cx))
       return false;
 
     if (!hasProperty) {
-      ThrowJSException(cx, "Trying to set unsupported property on NPObject!");
+      ThrowJSExceptionASCII(cx, "Trying to set unsupported property on NPObject!");
 
       return false;
     }
   }
 
   NPVariant npv;
   if (!JSValToNPVariant(npp, cx, vp, &npv)) {
-    ThrowJSException(cx, "Error converting jsval to NPVariant!");
+    ThrowJSExceptionASCII(cx, "Error converting jsval to NPVariant!");
 
     return false;
   }
 
   bool ok = npobj->_class->setProperty(npobj, identifier, &npv);
   _releasevariantvalue(&npv); // Release the variant
   if (!ReportExceptionIfPending(cx))
     return false;
 
   if (!ok) {
-    ThrowJSException(cx, "Error setting property on NPObject!");
+    ThrowJSExceptionASCII(cx, "Error setting property on NPObject!");
 
     return false;
   }
 
   return result.succeed();
 }
 
 static bool
 NPObjWrapper_GetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod || !npobj->_class->getProperty) {
-    ThrowJSException(cx, "Bad NPObject as private data!");
+    ThrowJSExceptionASCII(cx, "Bad NPObject as private data!");
 
     return false;
   }
 
   if (JSID_IS_SYMBOL(id)) {
     JS::RootedSymbol sym(cx, JSID_TO_SYMBOL(id));
     if (JS::GetSymbolCode(sym) == JS::SymbolCode::toPrimitive) {
       JS::RootedObject obj(cx, JS_GetFunctionObject(
@@ -1384,17 +1384,17 @@ NPObjWrapper_GetProperty(JSContext *cx, 
     vp.setUndefined();
     return true;
   }
 
   // Find out what plugin (NPP) is the owner of the object we're
   // manipulating, and make it own any JSObject wrappers created here.
   NPP npp = LookupNPP(npobj);
   if (!npp) {
-    ThrowJSException(cx, "No NPP found for NPObject!");
+    ThrowJSExceptionASCII(cx, "No NPP found for NPObject!");
 
     return false;
   }
 
   PluginDestructionGuard pdg(npp);
 
   bool hasProperty, hasMethod;
 
@@ -1470,53 +1470,53 @@ NPObjWrapper_GetProperty(JSContext *cx, 
 
 static bool
 CallNPMethodInternal(JSContext *cx, JS::Handle<JSObject*> obj, unsigned argc,
                      JS::Value *argv, JS::Value *rval, bool ctorCall)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class) {
-    ThrowJSException(cx, "Bad NPObject as private data!");
+    ThrowJSExceptionASCII(cx, "Bad NPObject as private data!");
 
     return false;
   }
 
   // Find out what plugin (NPP) is the owner of the object we're
   // manipulating, and make it own any JSObject wrappers created here.
   NPP npp = LookupNPP(npobj);
 
   if (!npp) {
-    ThrowJSException(cx, "Error finding NPP for NPObject!");
+    ThrowJSExceptionASCII(cx, "Error finding NPP for NPObject!");
 
     return false;
   }
 
   PluginDestructionGuard pdg(npp);
 
   NPVariant npargs_buf[8];
   NPVariant *npargs = npargs_buf;
 
   if (argc > (sizeof(npargs_buf) / sizeof(NPVariant))) {
     // Our stack buffer isn't large enough to hold all arguments,
     // malloc a buffer.
     npargs = (NPVariant *)PR_Malloc(argc * sizeof(NPVariant));
 
     if (!npargs) {
-      ThrowJSException(cx, "Out of memory!");
+      ThrowJSExceptionASCII(cx, "Out of memory!");
 
       return false;
     }
   }
 
   // Convert arguments
   uint32_t i;
   for (i = 0; i < argc; ++i) {
     if (!JSValToNPVariant(npp, cx, argv[i], npargs + i)) {
-      ThrowJSException(cx, "Error converting jsvals to NPVariants!");
+      ThrowJSExceptionASCII(cx, "Error converting jsvals to NPVariants!");
 
       if (npargs != npargs_buf) {
         PR_Free(npargs);
       }
 
       return false;
     }
   }
@@ -1578,17 +1578,17 @@ CallNPMethodInternal(JSContext *cx, JS::
   if (npargs != npargs_buf) {
     PR_Free(npargs);
   }
 
   if (!ok) {
     // ReportExceptionIfPending returns a return value, which is true
     // if no exception was thrown. In that case, throw our own.
     if (ReportExceptionIfPending(cx))
-      ThrowJSException(cx, msg);
+      ThrowJSExceptionASCII(cx, msg);
 
     return false;
   }
 
   *rval = NPVariantToJSVal(npp, cx, &v);
 
   // *rval now owns the value, release our reference.
   _releasevariantvalue(&v);
@@ -1608,35 +1608,35 @@ CallNPMethod(JSContext *cx, unsigned arg
 }
 
 static bool
 NPObjWrapper_Enumerate(JSContext *cx, JS::Handle<JSObject*> obj,
                        JS::AutoIdVector &properties, bool enumerableOnly)
 {
   NPObject *npobj = GetNPObject(cx, obj);
   if (!npobj || !npobj->_class) {
-    ThrowJSException(cx, "Bad NPObject as private data!");
+    ThrowJSExceptionASCII(cx, "Bad NPObject as private data!");
     return false;
   }
 
   PluginDestructionGuard pdg(LookupNPP(npobj));
 
   if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj->_class) ||
       !npobj->_class->enumerate) {
     return true;
   }
 
   NPIdentifier *identifiers;
   uint32_t length;
   if (!npobj->_class->enumerate(npobj, &identifiers, &length)) {
     if (ReportExceptionIfPending(cx)) {
       // ReportExceptionIfPending returns a return value, which is true
       // if no exception was thrown. In that case, throw our own.
-      ThrowJSException(cx, "Error enumerating properties on scriptable "
-                           "plugin object");
+      ThrowJSExceptionASCII(cx, "Error enumerating properties on scriptable "
+                            "plugin object");
     }
     return false;
   }
 
   if (!properties.reserve(length))
     return false;
 
   JS::Rooted<jsid> id(cx);
@@ -1657,17 +1657,17 @@ NPObjWrapper_Resolve(JSContext *cx, JS::
     return true;
 
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::JS);
 
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
-    ThrowJSException(cx, "Bad NPObject as private data!");
+    ThrowJSExceptionASCII(cx, "Bad NPObject as private data!");
 
     return false;
   }
 
   PluginDestructionGuard pdg(LookupNPP(npobj));
 
   NPIdentifier identifier = JSIdToNPIdentifier(id);
 
@@ -2055,17 +2055,17 @@ LookupNPP(NPObject *npobj)
 
 static bool
 CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
                      JS::Handle<jsid> id,  NPVariant* getPropertyResult,
                      JS::MutableHandle<JS::Value> vp)
 {
   if (!npobj || !npobj->_class || !npobj->_class->getProperty ||
       !npobj->_class->invoke) {
-    ThrowJSException(cx, "Bad NPObject");
+    ThrowJSExceptionASCII(cx, "Bad NPObject");
 
     return false;
   }
 
   NPObjectMemberPrivate *memberPrivate =
     (NPObjectMemberPrivate *)PR_Malloc(sizeof(NPObjectMemberPrivate));
   if (!memberPrivate)
     return false;
@@ -2165,40 +2165,40 @@ NPObjectMember_Call(JSContext *cx, unsig
     (NPObjectMemberPrivate *)::JS_GetInstancePrivate(cx, memobj,
                                                      &sNPObjectMemberClass,
                                                      &args);
   if (!memberPrivate || !memberPrivate->npobjWrapper)
     return false;
 
   NPObject *npobj = GetNPObject(cx, memberPrivate->npobjWrapper);
   if (!npobj) {
-    ThrowJSException(cx, "Call on invalid member object");
+    ThrowJSExceptionASCII(cx, "Call on invalid member object");
 
     return false;
   }
 
   NPVariant npargs_buf[8];
   NPVariant *npargs = npargs_buf;
 
   if (args.length() > (sizeof(npargs_buf) / sizeof(NPVariant))) {
     // Our stack buffer isn't large enough to hold all arguments,
     // malloc a buffer.
     npargs = (NPVariant *)PR_Malloc(args.length() * sizeof(NPVariant));
 
     if (!npargs) {
-      ThrowJSException(cx, "Out of memory!");
+      ThrowJSExceptionASCII(cx, "Out of memory!");
 
       return false;
     }
   }
 
   // Convert arguments
   for (uint32_t i = 0; i < args.length(); ++i) {
     if (!JSValToNPVariant(memberPrivate->npp, cx, args[i], npargs + i)) {
-      ThrowJSException(cx, "Error converting jsvals to NPVariants!");
+      ThrowJSExceptionASCII(cx, "Error converting jsvals to NPVariants!");
 
       if (npargs != npargs_buf) {
         PR_Free(npargs);
       }
 
       return false;
     }
   }
@@ -2217,17 +2217,17 @@ NPObjectMember_Call(JSContext *cx, unsig
   if (npargs != npargs_buf) {
     PR_Free(npargs);
   }
 
   if (!ok) {
     // ReportExceptionIfPending returns a return value, which is true
     // if no exception was thrown. In that case, throw our own.
     if (ReportExceptionIfPending(cx))
-      ThrowJSException(cx, "Error calling method on NPObject!");
+      ThrowJSExceptionASCII(cx, "Error calling method on NPObject!");
 
     return false;
   }
 
   args.rval().set(NPVariantToJSVal(memberPrivate->npp, cx, &npv));
 
   // *vp now owns the value, release our reference.
   _releasevariantvalue(&npv);
@@ -2294,18 +2294,18 @@ nsJSObjWrapper::HasOwnProperty(NPObject 
   if (NS_WARN_IF(!globalObject)) {
     return false;
   }
 
   dom::AutoEntryScript aes(globalObject, "NPAPI HasOwnProperty");
   JSContext *cx = aes.cx();
 
   if (!npobj) {
-    ThrowJSException(cx,
-                     "Null npobj in nsJSObjWrapper::NP_HasOwnProperty!");
+    ThrowJSExceptionASCII(cx,
+                          "Null npobj in nsJSObjWrapper::NP_HasOwnProperty!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
   bool found, ok = false;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
--- a/js/src/builtin/Profilers.cpp
+++ b/js/src/builtin/Profilers.cpp
@@ -191,19 +191,19 @@ JS_DumpProfile(const char* outfile, cons
 
 struct RequiredStringArg {
     JSContext* mCx;
     char* mBytes;
     RequiredStringArg(JSContext* cx, const CallArgs& args, size_t argi, const char* caller)
         : mCx(cx), mBytes(nullptr)
     {
         if (args.length() <= argi) {
-            JS_ReportError(cx, "%s: not enough arguments", caller);
+            JS_ReportErrorASCII(cx, "%s: not enough arguments", caller);
         } else if (!args[argi].isString()) {
-            JS_ReportError(cx, "%s: invalid arguments (string expected)", caller);
+            JS_ReportErrorASCII(cx, "%s: invalid arguments (string expected)", caller);
         } else {
             mBytes = JS_EncodeString(cx, args[argi].toString());
         }
     }
     operator void*() {
         return (void*) mBytes;
     }
     ~RequiredStringArg() {
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -387,35 +387,35 @@ GCParameter(JSContext* cx, unsigned argc
 
     JSFlatString* flatStr = JS_FlattenString(cx, str);
     if (!flatStr)
         return false;
 
     size_t paramIndex = 0;
     for (;; paramIndex++) {
         if (paramIndex == ArrayLength(paramMap)) {
-            JS_ReportError(cx,
-                           "the first argument must be one of:" GC_PARAMETER_ARGS_LIST);
+            JS_ReportErrorASCII(cx,
+                                "the first argument must be one of:" GC_PARAMETER_ARGS_LIST);
             return false;
         }
         if (JS_FlatStringEqualsAscii(flatStr, paramMap[paramIndex].name))
             break;
     }
     const ParamInfo& info = paramMap[paramIndex];
     JSGCParamKey param = info.param;
 
     // Request mode.
     if (args.length() == 1) {
         uint32_t value = JS_GetGCParameter(cx, param);
         args.rval().setNumber(value);
         return true;
     }
 
     if (!info.writable) {
-        JS_ReportError(cx, "Attempt to change read-only parameter %s", info.name);
+        JS_ReportErrorASCII(cx, "Attempt to change read-only parameter %s", info.name);
         return false;
     }
 
     if (disableOOMFunctions && (param == JSGC_MAX_BYTES || param == JSGC_MAX_MALLOC_BYTES)) {
         args.rval().setUndefined();
         return true;
     }
 
@@ -519,27 +519,27 @@ WasmTextToBinary(JSContext* cx, unsigned
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
 
     if (!args.requireAtLeast(cx, "wasmTextToBinary", 1))
         return false;
 
     if (!args[0].isString()) {
-        ReportUsageError(cx, callee, "First argument must be a String");
+        ReportUsageErrorASCII(cx, callee, "First argument must be a String");
         return false;
     }
 
     AutoStableStringChars twoByteChars(cx);
     if (!twoByteChars.initTwoByte(cx, args[0].toString()))
         return false;
 
     if (args.hasDefined(1)) {
         if (!args[1].isString()) {
-            ReportUsageError(cx, callee, "Second argument, if present, must be a String");
+            ReportUsageErrorASCII(cx, callee, "Second argument, if present, must be a String");
             return false;
         }
     }
 
     wasm::Bytes bytes;
     UniqueChars error;
     if (!wasm::TextToBinary(twoByteChars.twoByteChars(), &bytes, &error)) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_TEXT_FAIL,
@@ -683,17 +683,17 @@ InternalConst(JSContext* cx, unsigned ar
 
 static bool
 GCPreserveCode(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() != 0) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     cx->runtime()->gc.setAlwaysPreserveCode();
 
     args.rval().setUndefined();
     return true;
 }
@@ -701,17 +701,17 @@ GCPreserveCode(JSContext* cx, unsigned a
 #ifdef JS_GC_ZEAL
 static bool
 GCZeal(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() > 2) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Too many arguments");
+        ReportUsageErrorASCII(cx, callee, "Too many arguments");
         return false;
     }
 
     uint32_t zeal;
     if (!ToUint32(cx, args.get(0), &zeal))
         return false;
 
     if (zeal > uint32_t(gc::ZealMode::Limit)) {
@@ -732,17 +732,17 @@ GCZeal(JSContext* cx, unsigned argc, Val
 
 static bool
 ScheduleGC(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() > 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Too many arguments");
+        ReportUsageErrorASCII(cx, callee, "Too many arguments");
         return false;
     }
 
     if (args.length() == 0) {
         /* Fetch next zeal trigger only. */
     } else if (args[0].isInt32()) {
         /* Schedule a GC to happen after |arg| allocations. */
         JS_ScheduleGC(cx, args[0].toInt32());
@@ -789,47 +789,47 @@ SelectForGC(JSContext* cx, unsigned argc
 
 static bool
 VerifyPreBarriers(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() > 0) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Too many arguments");
+        ReportUsageErrorASCII(cx, callee, "Too many arguments");
         return false;
     }
 
     gc::VerifyBarriers(cx->runtime(), gc::PreBarrierVerifier);
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 VerifyPostBarriers(JSContext* cx, unsigned argc, Value* vp)
 {
     // This is a no-op since the post barrier verifier was removed.
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length()) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Too many arguments");
+        ReportUsageErrorASCII(cx, callee, "Too many arguments");
         return false;
     }
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 GCState(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() != 0) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Too many arguments");
+        ReportUsageErrorASCII(cx, callee, "Too many arguments");
         return false;
     }
 
     const char* state = StateName(cx->runtime()->gc.state());
     JSString* str = JS_NewStringCopyZ(cx, state);
     if (!str)
         return false;
     args.rval().setString(str);
@@ -838,34 +838,34 @@ GCState(JSContext* cx, unsigned argc, Va
 
 static bool
 DeterministicGC(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() != 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     cx->runtime()->gc.setDeterministic(ToBoolean(args[0]));
     args.rval().setUndefined();
     return true;
 }
 #endif /* JS_GC_ZEAL */
 
 static bool
 StartGC(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() > 2) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     auto budget = SliceBudget::unlimited();
     if (args.length() >= 1) {
         uint32_t work = 0;
         if (!ToUint32(cx, args[0], &work))
             return false;
@@ -897,17 +897,17 @@ StartGC(JSContext* cx, unsigned argc, Va
 
 static bool
 GCSlice(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() > 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     auto budget = SliceBudget::unlimited();
     if (args.length() == 1) {
         uint32_t work = 0;
         if (!ToUint32(cx, args[0], &work))
             return false;
@@ -926,49 +926,49 @@ GCSlice(JSContext* cx, unsigned argc, Va
 
 static bool
 AbortGC(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() != 0) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     cx->runtime()->gc.abortGC();
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 FullCompartmentChecks(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() != 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     cx->runtime()->gc.setFullCompartmentChecks(ToBoolean(args[0]));
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 NondeterministicGetWeakMapKeys(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() != 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
     if (!args[0].isObject()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
                              "nondeterministicGetWeakMapKeys", "WeakMap",
                              InformalValueTypeName(args[0]));
         return false;
     }
@@ -1697,17 +1697,17 @@ EnableOsiPointRegisterChecks(JSContext*,
 }
 
 static bool
 DisplayName(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (!args.get(0).isObject() || !args[0].toObject().is<JSFunction>()) {
         RootedObject arg(cx, &args.callee());
-        ReportUsageError(cx, arg, "Must have one function argument");
+        ReportUsageErrorASCII(cx, arg, "Must have one function argument");
         return false;
     }
 
     JSFunction* fun = &args[0].toObject().as<JSFunction>();
     JSString* str = fun->displayAtom();
     args.rval().setString(str ? str : cx->runtime()->emptyString);
     return true;
 }
@@ -1926,27 +1926,27 @@ js::testingFunc_assertRecoveredOnBailout
 
 static bool
 SetJitCompilerOption(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
 
     if (args.length() != 2) {
-        ReportUsageError(cx, callee, "Wrong number of arguments.");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments.");
         return false;
     }
 
     if (!args[0].isString()) {
-        ReportUsageError(cx, callee, "First argument must be a String.");
+        ReportUsageErrorASCII(cx, callee, "First argument must be a String.");
         return false;
     }
 
     if (!args[1].isInt32()) {
-        ReportUsageError(cx, callee, "Second argument must be an Int32.");
+        ReportUsageErrorASCII(cx, callee, "Second argument must be an Int32.");
         return false;
     }
 
     JSFlatString* strArg = JS_FlattenString(cx, args[0].toString());
     if (!strArg)
         return false;
 
 #define JIT_COMPILER_MATCH(key, string)                 \
@@ -1954,17 +1954,17 @@ SetJitCompilerOption(JSContext* cx, unsi
         opt = JSJITCOMPILER_ ## key;
 
     JSJitCompilerOption opt = JSJITCOMPILER_NOT_AN_OPTION;
     if (false) {}
     JIT_COMPILER_OPTIONS(JIT_COMPILER_MATCH);
 #undef JIT_COMPILER_MATCH
 
     if (opt == JSJITCOMPILER_NOT_AN_OPTION) {
-        ReportUsageError(cx, callee, "First argument does not name a valid option (see jsapi.h).");
+        ReportUsageErrorASCII(cx, callee, "First argument does not name a valid option (see jsapi.h).");
         return false;
     }
 
     int32_t number = args[1].toInt32();
     if (number < 0)
         number = -1;
 
     // Throw if disabling the JITs and there's JIT code on the stack, to avoid
@@ -2344,22 +2344,22 @@ SharedMemoryEnabled(JSContext* cx, unsig
 
 #ifdef NIGHTLY_BUILD
 static bool
 ObjectAddress(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
     if (!args[0].isObject()) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Expected object");
+        ReportUsageErrorASCII(cx, callee, "Expected object");
         return false;
     }
 
 #ifdef JS_MORE_DETERMINISTIC
     args.rval().setInt32(0);
 #else
     void* ptr = js::UncheckedUnwrap(&args[0].toObject(), true);
     char buffer[64];
@@ -2376,22 +2376,22 @@ ObjectAddress(JSContext* cx, unsigned ar
 }
 
 static bool
 SharedAddress(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
     if (!args[0].isObject()) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Expected object");
+        ReportUsageErrorASCII(cx, callee, "Expected object");
         return false;
     }
 
 #ifdef JS_MORE_DETERMINISTIC
     args.rval().setString(cx->staticStrings().getUint(0));
 #else
     RootedObject obj(cx, CheckedUnwrap(&args[0].toObject()));
     if (!obj) {
@@ -2433,17 +2433,17 @@ GetBacktrace(JSContext* cx, unsigned arg
     CallArgs args = CallArgsFromVp(argc, vp);
 
     bool showArgs = false;
     bool showLocals = false;
     bool showThisProps = false;
 
     if (args.length() > 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Too many arguments");
+        ReportUsageErrorASCII(cx, callee, "Too many arguments");
         return false;
     }
 
     if (args.length() == 1) {
         RootedObject cfg(cx, ToObject(cx, args[0]));
         if (!cfg)
             return false;
         RootedValue v(cx);
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1318,17 +1318,17 @@ LoopChoiceNode::FilterASCII(int depth, b
 }
 
 // -------------------------------------------------------------------
 // Analysis
 
 void
 Analysis::EnsureAnalyzed(RegExpNode* that)
 {
-    JS_CHECK_RECURSION(cx, fail("Stack overflow"); return);
+    JS_CHECK_RECURSION(cx, failASCII("Stack overflow"); return);
 
     if (that->info()->been_analyzed || that->info()->being_analyzed)
         return;
     that->info()->being_analyzed = true;
     that->Accept(this);
     that->info()->being_analyzed = false;
     that->info()->been_analyzed = true;
 }
@@ -1867,17 +1867,17 @@ irregexp::CompilePattern(JSContext* cx, 
     }
 
     if (node == nullptr)
         node = alloc.newInfallible<EndNode>(&alloc, EndNode::BACKTRACK);
 
     Analysis analysis(cx, ignore_case, is_ascii, unicode);
     analysis.EnsureAnalyzed(node);
     if (analysis.has_failed()) {
-        JS_ReportError(cx, analysis.errorMessage());
+        JS_ReportErrorASCII(cx, analysis.errorMessage());
         return RegExpCode();
     }
 
     Maybe<jit::JitContext> ctx;
     Maybe<NativeRegExpMacroAssembler> native_assembler;
     Maybe<InterpretedRegExpMacroAssembler> interpreted_assembler;
 
     RegExpMacroAssembler* assembler;
--- a/js/src/irregexp/RegExpEngine.h
+++ b/js/src/irregexp/RegExpEngine.h
@@ -1520,17 +1520,17 @@ class Analysis : public NodeVisitor
 #undef DECLARE_VISIT
     virtual void VisitLoopChoice(LoopChoiceNode* that);
 
     bool has_failed() { return error_message_ != nullptr; }
     const char* errorMessage() {
         MOZ_ASSERT(error_message_ != nullptr);
         return error_message_;
     }
-    void fail(const char* error_message) {
+    void failASCII(const char* error_message) {
         error_message_ = error_message;
     }
 
   private:
     JSContext* cx;
     bool ignore_case_;
     bool is_ascii_;
     bool unicode_;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -374,32 +374,32 @@ js::ReportErrorVA(JSContext* cx, unsigne
     ReportError(cx, message, &report, nullptr, nullptr);
     js_free(message);
     js_free(ucmessage);
     return warning;
 }
 
 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
 void
-js::ReportUsageError(JSContext* cx, HandleObject callee, const char* msg)
+js::ReportUsageErrorASCII(JSContext* cx, HandleObject callee, const char* msg)
 {
     const char* usageStr = "usage";
     PropertyName* usageAtom = Atomize(cx, usageStr, strlen(usageStr))->asPropertyName();
     RootedId id(cx, NameToId(usageAtom));
     DebugOnly<Shape*> shape = static_cast<Shape*>(callee->as<JSFunction>().lookup(cx, id));
     MOZ_ASSERT(!shape->configurable());
     MOZ_ASSERT(!shape->writable());
     MOZ_ASSERT(shape->hasDefaultGetter());
 
     RootedValue usage(cx);
     if (!JS_GetProperty(cx, callee, "usage", &usage))
         return;
 
     if (!usage.isString()) {
-        JS_ReportError(cx, "%s", msg);
+        JS_ReportErrorASCII(cx, "%s", msg);
     } else {
         JSString* str = usage.toString();
         if (!str->ensureFlat(cx))
             return;
         AutoStableStringChars chars(cx);
         if (!chars.initTwoByte(cx, str))
             return;
 
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -617,17 +617,17 @@ extern bool
 ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
                        void* userRef, const unsigned errorNumber,
                        char** message, const char16_t** messageArgs,
                        ErrorArgumentsType argumentsType,
                        JSErrorReport* reportp, va_list ap);
 
 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
 extern void
-ReportUsageError(JSContext* cx, HandleObject callee, const char* msg);
+ReportUsageErrorASCII(JSContext* cx, HandleObject callee, const char* msg);
 
 /*
  * Prints a full report and returns true if the given report is non-nullptr
  * and the report doesn't have the JSREPORT_WARNING flag set or reportWarnings
  * is true.
  * Returns false otherwise, printing just the message if the report is nullptr.
  */
 extern bool
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4632,23 +4632,23 @@ class ShellSourceHook: public SourceHook
 
 static bool
 WithSourceHook(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
 
     if (args.length() != 2) {
-        ReportUsageError(cx, callee, "Wrong number of arguments.");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments.");
         return false;
     }
 
     if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()
         || !args[1].isObject() || !args[1].toObject().is<JSFunction>()) {
-        ReportUsageError(cx, callee, "First and second arguments must be functions.");
+        ReportUsageErrorASCII(cx, callee, "First and second arguments must be functions.");
         return false;
     }
 
     mozilla::UniquePtr<ShellSourceHook> hook =
         mozilla::MakeUnique<ShellSourceHook>(cx, args[0].toObject().as<JSFunction>());
     if (!hook)
         return false;
 
@@ -5082,22 +5082,22 @@ ReflectTrackedOptimizations(JSContext* c
     JSRuntime* rt = cx->runtime();
 
     if (!rt->hasJitRuntime() || !rt->jitRuntime()->isOptimizationTrackingEnabled(rt)) {
         JS_ReportErrorASCII(cx, "Optimization tracking is off.");
         return false;
     }
 
     if (args.length() != 1) {
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
-        ReportUsageError(cx, callee, "Argument must be a function");
+        ReportUsageErrorASCII(cx, callee, "Argument must be a function");
         return false;
     }
 
     RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
     if (!fun->hasScript() || !fun->nonLazyScript()->hasIonScript()) {
         args.rval().setNull();
         return true;
     }
@@ -5209,34 +5209,34 @@ ReflectTrackedOptimizations(JSContext* c
 
 static bool
 DumpScopeChain(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
 
     if (args.length() != 1) {
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     if (!args[0].isObject() ||
         !(args[0].toObject().is<JSFunction>() || args[0].toObject().is<ModuleObject>()))
     {
-        ReportUsageError(cx, callee, "Argument must be an interpreted function or a module");
+        ReportUsageErrorASCII(cx, callee, "Argument must be an interpreted function or a module");
         return false;
     }
 
     RootedObject obj(cx, &args[0].toObject());
     RootedScript script(cx);
 
     if (obj->is<JSFunction>()) {
         RootedFunction fun(cx, &obj->as<JSFunction>());
         if (!fun->isInterpreted()) {
-            ReportUsageError(cx, callee, "Argument must be an interpreted function");
+            ReportUsageErrorASCII(cx, callee, "Argument must be an interpreted function");
             return false;
         }
         script = fun->getOrCreateScript(cx);
     } else {
         script = obj->as<ModuleObject>().script();
     }
 
     script->bodyScope()->dump();
@@ -5482,29 +5482,29 @@ SetARMHwCapFlags(JSContext* cx, unsigned
 #ifdef __AFL_HAVE_MANUAL_CONTROL
 static bool
 WasmLoop(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
 
     if (args.length() < 1 || args.length() > 2) {
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
         return false;
     }
 
     if (!args[0].isString()) {
-        ReportUsageError(cx, callee, "First argument must be a String");
+        ReportUsageErrorASCII(cx, callee, "First argument must be a String");
         return false;
     }
 
     RootedObject importObj(cx);
     if (!args.get(1).isUndefined()) {
         if (!args.get(1).isObject()) {
-            ReportUsageError(cx, callee, "Second argument, if present, must be an Object");
+            ReportUsageErrorASCII(cx, callee, "Second argument, if present, must be an Object");
             return false;
         }
         importObj = &args[1].toObject();
     }
 
     RootedString givenPath(cx, args[0].toString());
     RootedString str(cx, ResolvePath(cx, givenPath, RootRelative));
     if (!str)
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1475,17 +1475,17 @@ OptionsBase::ParseBoolean(const char* na
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
     if (!value.isBoolean()) {
-        JS_ReportError(mCx, "Expected a boolean value for property %s", name);
+        JS_ReportErrorASCII(mCx, "Expected a boolean value for property %s", name);
         return false;
     }
 
     *prop = value.toBoolean();
     return true;
 }
 
 /*
@@ -1498,17 +1498,17 @@ OptionsBase::ParseObject(const char* nam
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
     if (!value.isObject()) {
-        JS_ReportError(mCx, "Expected an object value for property %s", name);
+        JS_ReportErrorASCII(mCx, "Expected an object value for property %s", name);
         return false;
     }
     prop.set(&value.toObject());
     return true;
 }
 
 /*
  * Helper that tries to get an object property from the options object.
@@ -1520,17 +1520,17 @@ OptionsBase::ParseJSString(const char* n
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
     if (!value.isString()) {
-        JS_ReportError(mCx, "Expected a string value for property %s", name);
+        JS_ReportErrorASCII(mCx, "Expected a string value for property %s", name);
         return false;
     }
     prop.set(value.toString());
     return true;
 }
 
 /*
  * Helper that tries to get a string property from the options object.
@@ -1542,17 +1542,17 @@ OptionsBase::ParseString(const char* nam
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
     if (!value.isString()) {
-        JS_ReportError(mCx, "Expected a string value for property %s", name);
+        JS_ReportErrorASCII(mCx, "Expected a string value for property %s", name);
         return false;
     }
 
     char* tmp = JS_EncodeString(mCx, value.toString());
     NS_ENSURE_TRUE(tmp, false);
     prop.Assign(tmp, strlen(tmp));
     js_free(tmp);
     return true;
@@ -1568,17 +1568,17 @@ OptionsBase::ParseString(const char* nam
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
     if (!value.isString()) {
-        JS_ReportError(mCx, "Expected a string value for property %s", name);
+        JS_ReportErrorASCII(mCx, "Expected a string value for property %s", name);
         return false;
     }
 
     nsAutoJSString strVal;
     if (!strVal.init(mCx, value.toString()))
         return false;
 
     prop = strVal;
@@ -1613,17 +1613,17 @@ OptionsBase::ParseUInt32(const char* nam
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
     if(!JS::ToUint32(mCx, value, prop)) {
-        JS_ReportError(mCx, "Expected a uint32_t value for property %s", name);
+        JS_ReportErrorASCII(mCx, "Expected a uint32_t value for property %s", name);
         return false;
     }
 
     return true;
 }
 
 /*
  * Helper that tries to get a list of DOM constructors and other helpers from the options object.
@@ -1656,16 +1656,17 @@ SandboxOptions::ParseGlobalProperties()
 }
 
 /*
  * Helper that parsing the sandbox options object (from) and sets the fields of the incoming options struct (options).
  */
 bool
 SandboxOptions::Parse()
 {
+    /* All option names must be ASCII-only. */
     bool ok = ParseObject("sandboxPrototype", &proto) &&
               ParseBoolean("wantXrays", &wantXrays) &&
               ParseBoolean("allowWaivers", &allowWaivers) &&
               ParseBoolean("wantComponents", &wantComponents) &&
               ParseBoolean("wantExportHelpers", &wantExportHelpers) &&
               ParseBoolean("isWebExtensionContentScript", &isWebExtensionContentScript) &&
               ParseBoolean("waiveInterposition", &waiveInterposition) &&
               ParseString("sandboxName", sandboxName) &&
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -966,17 +966,17 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWra
         return NS_ERROR_FAILURE;
 
     // [implicit_jscontext] and [optional_argc] have a different calling
     // convention, which we don't support for JS-implemented components.
     if (info->WantsOptArgc() || info->WantsContext()) {
         const char* str = "IDL methods marked with [implicit_jscontext] "
                           "or [optional_argc] may not be implemented in JS";
         // Throw and warn for good measure.
-        JS_ReportError(cx, str);
+        JS_ReportErrorASCII(cx, str);
         NS_WARNING(str);
         return CheckForException(ccx, aes, name, GetInterfaceName());
     }
 
     RootedValue fval(cx);
     RootedObject obj(cx, wrapper->GetJSObject());
     RootedObject thisObj(cx, obj);
 
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -266,20 +266,20 @@ AccessCheck::checkPassToPrivilegedCode(J
             return false;
     }
     return true;
 }
 
 enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 };
 
 static void
-EnterAndThrow(JSContext* cx, JSObject* wrapper, const char* msg)
+EnterAndThrowASCII(JSContext* cx, JSObject* wrapper, const char* msg)
 {
     JSAutoCompartment ac(cx, wrapper);
-    JS_ReportError(cx, msg);
+    JS_ReportErrorASCII(cx, msg);
 }
 
 bool
 ExposedPropertiesOnly::check(JSContext* cx, HandleObject wrapper, HandleId id, Wrapper::Action act)
 {
     RootedObject wrappedObject(cx, Wrapper::wrappedObject(wrapper));
 
     if (act == Wrapper::CALL)
@@ -332,105 +332,105 @@ ExposedPropertiesOnly::check(JSContext* 
     Rooted<PropertyDescriptor> desc(cx);
     if (!JS_GetPropertyDescriptorById(cx, wrappedObject, exposedPropsId, &desc))
         return false;
 
     if (!desc.object())
         return false;
 
     if (desc.hasGetterOrSetter()) {
-        EnterAndThrow(cx, wrapper, "__exposedProps__ must be a value property");
+        EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be a value property");
         return false;
     }
 
     RootedValue exposedProps(cx, desc.value());
     if (exposedProps.isNullOrUndefined())
         return false;
 
     if (!exposedProps.isObject()) {
-        EnterAndThrow(cx, wrapper, "__exposedProps__ must be undefined, null, or an Object");
+        EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be undefined, null, or an Object");
         return false;
     }
 
     RootedObject hallpass(cx, &exposedProps.toObject());
 
     if (!AccessCheck::subsumes(js::UncheckedUnwrap(hallpass), wrappedObject)) {
-        EnterAndThrow(cx, wrapper, "Invalid __exposedProps__");
+        EnterAndThrowASCII(cx, wrapper, "Invalid __exposedProps__");
         return false;
     }
 
     Access access = NO_ACCESS;
 
     if (!JS_GetPropertyDescriptorById(cx, hallpass, id, &desc)) {
         return false; // Error
     }
     if (!desc.object() || !desc.enumerable())
         return false;
 
     if (!desc.value().isString()) {
-        EnterAndThrow(cx, wrapper, "property must be a string");
+        EnterAndThrowASCII(cx, wrapper, "property must be a string");
         return false;
     }
 
     JSFlatString* flat = JS_FlattenString(cx, desc.value().toString());
     if (!flat)
         return false;
 
     size_t length = JS_GetStringLength(JS_FORGET_STRING_FLATNESS(flat));
 
     for (size_t i = 0; i < length; ++i) {
         char16_t ch = JS_GetFlatStringCharAt(flat, i);
         switch (ch) {
         case 'r':
             if (access & READ) {
-                EnterAndThrow(cx, wrapper, "duplicate 'readable' property flag");
+                EnterAndThrowASCII(cx, wrapper, "duplicate 'readable' property flag");
                 return false;
             }
             access = Access(access | READ);
             break;
 
         case 'w':
             if (access & WRITE) {
-                EnterAndThrow(cx, wrapper, "duplicate 'writable' property flag");
+                EnterAndThrowASCII(cx, wrapper, "duplicate 'writable' property flag");
                 return false;
             }
             access = Access(access | WRITE);
             break;
 
         default:
-            EnterAndThrow(cx, wrapper, "properties can only be readable or read and writable");
+            EnterAndThrowASCII(cx, wrapper, "properties can only be readable or read and writable");
             return false;
         }
     }
 
     if (access == NO_ACCESS) {
-        EnterAndThrow(cx, wrapper, "specified properties must have a permission bit set");
+        EnterAndThrowASCII(cx, wrapper, "specified properties must have a permission bit set");
         return false;
     }
 
     if ((act == Wrapper::SET && !(access & WRITE)) ||
         (act != Wrapper::SET && !(access & READ))) {
         return false;
     }
 
     // Inspect the property on the underlying object to check for red flags.
     if (!JS_GetPropertyDescriptorById(cx, wrappedObject, id, &desc))
         return false;
 
     // Reject accessor properties.
     if (desc.hasGetterOrSetter()) {
-        EnterAndThrow(cx, wrapper, "Exposing privileged accessor properties is prohibited");
+        EnterAndThrowASCII(cx, wrapper, "Exposing privileged accessor properties is prohibited");
         return false;
     }
 
     // Reject privileged or cross-origin callables.
     if (desc.value().isObject()) {
         RootedObject maybeCallable(cx, js::UncheckedUnwrap(&desc.value().toObject()));
         if (JS::IsCallable(maybeCallable) && !AccessCheck::subsumes(wrapper, maybeCallable)) {
-            EnterAndThrow(cx, wrapper, "Exposing privileged or cross-origin callable is prohibited");
+            EnterAndThrowASCII(cx, wrapper, "Exposing privileged or cross-origin callable is prohibited");
             return false;
         }
     }
 
     return true;
 }
 
 bool